大前端技術學習與核心整理(NodeJS/ES6/npm/babel/webpack)

2021-05-04 14:00:27

前言

本文整理了學習過程中關於NodeJS、ES6標準的新特性、npm包管理工具、babel降級、webpack打包等大前端技術,學習的原因是幾個月以後可能會用到。

NodeJS

Node 是一個讓 JavaScript 執行在伺服器端的開發平臺,它讓 JavaScript 成為與PHP、Python、Perl、Ruby 等伺服器端語言平起平坐的指令碼語言,實質是對Chrome V8引擎進行了封裝(node安裝自帶npm,node -v檢視版本)。
在這裡插入圖片描述
【案例1】用Node實現請求響應(類似flask)。建立server.js並執行node server.js

// 0.用require導包(類似python的import)
const http = require('http');

// 1.建立一個httpserver服務
http.createServer(function(request, response){
    // request用來接收引數, response用來返回內容
    // 告訴瀏覽器將以text/plain解析"hello server is running!"這個資料
    response.writeHead(200, {"Content-type":"text/plain"});
    // response.writeHead(200, {"Content-type":"text/html"}); //這樣會以html的形式解析<h1></h1>
    // 給瀏覽器輸出內容
    response.end("<h1>hello server is running!<h1>")
}).listen(8888);  
// 2.監聽埠 比如8888
// 3.啟動 node serverFileName.js
// 4.瀏覽器存取 http://127.0.0.1:8888
console.log("server已啟動 埠為8888")

【案例2】用node操作mysql資料庫。新建mysqltest.js,先在專案目錄執行npm install mysql安裝第三方庫,此時生成了node_modules資料夾和package-lock.json檔案。最後執行node mysqltest.js檢視效果。

// 0.匯入第三方模組mysql
var mysql = require('mysql');

// 1.建立mysql的Connection物件
// 2.設定連線
var connection = mysql.createConnection({
    host:"xxx.xxx.xxx.xxx",
    user:"root",
    port:3306,
    password:"xxxxx",
    database:"vaeh"
});

// 3.開啟連線
connection.connect();

// 4.執行curd
connection.query("select count(*) from cityinfo", function(error, result, fields) {
    // 如果出錯 丟擲
    if(error) {
        throw error;
    }    
    console.log("result = ", result);
});

// 5.關閉連線
connection.end();

ES6標準新特性

ECMAScript是個用來指定JavaScript規範的組織 es6就是JavaScript的標準。

  • let定義變數,const定義常數。
<!-- 以下內容在vscode打了個歎號回車就生成了 -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        // 傳統定義變數和常數都用var
        var name = "vae";
        var PI = Math.PI;
        console.log(name);
        console.log(PI);

        // ES6定義變數 (解決了變數穿透問題,比如for迴圈裡定義的var = i, 迴圈完按說i不能再用了)
        let name_es6 = "vae"

        // ES6定義常數 (解決了常數修改問題,比如圓周率PI如果用const定義就不能修改了)
        const PI_es6 = Math.PI;
        
        console.log(name_es6);
        console.log(PI_es6);

    </script>
</body>
</html>
  • 模版字串(反引號做格式化or拼字串:類似python的 f"名字是{name}的人"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        // 模版字串 類似python的 f"名字是{name}的人"
        person = {name: "vae", id: 514, url: "xusong.com"};

        // 傳統方式
        let res = person.name + "的id為" + person.id + ", 官網為" + person.url;
        console.log(res);

        // ES6 用 ` ${變數名} ` 就ok了
        let res_es6 = `${person.name}的id為${person.id}, 官網為${person.url}`;
        console.log(res_es6);
    </script>
</body>
</html>
  • 函數預設引數(函數引數預設是undefined,可手動指定)
<script>
    // 函數預設引數(預設是undefined)
    function sum(a=undefined,b=100){
        return a+b;
    }
    let res = sum(a=200);
    console.log(`res=${res}`);
</script>
  • 箭頭函數(箭頭函數=>簡化函數表達,規律如下)
<script>
    // 箭頭函數(重點。有lambda函數內味兒了,不過本質不一樣) 小程式、uniapp、腳手架中大量使用
    
    // 傳統方式:
    let sum0 = function(a,b){
        return a+b;
    };
    console.log(sum0(1,2));

    // 箭頭函數 改進1 :
    let sum1 = (a,b)=>{
        return a+b;
    };

    // 箭頭函數 改進2 :
    let sum2 = (a,b) => a+b;
    
    // 規律:
    // 1.去掉function 
    // 2.參數列括號後加上 =>
    // 3.若邏輯程式碼僅return 可省略return和大括號
    // 4.若引數只有一個 可參數列的省略小括號
    // 範例:陣列的每個數都*2
    let arr = [1,2,3]
    let new_arr = arr.map(obj=>obj*2);
    console.log(new_arr)
</script>
  • 定義物件時的簡寫(key和value一致 or value是個函數)
<script>
    // 定義物件時的簡寫
    // 1.如果key和value變數名一致 只定義一次即可
    // 2.如果value是個函數 可刪掉「function」 保留()即可

    // 傳統寫法
    let title = "About Vae+";
    let obj_example = {
        title: title,
        go: function(){
            console.log("test...");
        }
    };

    // ES6
    let title1 = "About Vae+";
    let obj_example1 = {
        title1,
        go(){
            console.log("test...");
        }
    };
    obj_example1.go();
</script>
  • 物件解構(3種獲取物件中的屬性/方法)
<script>
    // 1、通過 . 
    console.log(obj_example.title);
    obj_example.go();
    // 2、通過 []
    console.log(obj_example["title"]);
    obj_example["go"]();
    // 3、ES6的新方法 有點像python的 a,b=[1,2] 可以用冒號取小名:var {name,age,language:lan} = person;
    let {obj_title,go} = obj_example;
    go();
</script>
  • 物件傳播操作符(…)把一個物件的屬性傳播到另外一個物件中
<script>
    // 物件傳播操作符...
    let person = {
        name: "vae",
        id: 514,
        link: "xusong.com",
        address: "北京市朝陽區"
    }
    // ...linkAndAddr 來接收除了name和id的其他變數 並解構成一個obj
    let {name, id, ...linkAndAddr} = person;
    console.log(name);
    console.log(id);
    console.log(linkAndAddr);
</script>
  • map和reduce方法
    map方法可以將原陣列中的所有元素通過一個函數進行處理,並放入到一個新陣列中並返回該新陣列。
    reduce(function(),初始值(可選)) :接收一個函數(必須)和一個初始值(可選),該函數接收兩個引數:第一個引數是上一次reduce處理的結果,第二個引數是陣列中要處理的下一個元素。reduce() 會從左到右依次把陣列中的元素用reduce處理,並把處理的結果作為下次reduce的第一個引數。如果是 第一次,會把前兩個元素作為計算引數,或者把使用者指定的初始值作為起始引數。
<script>
    let arr = [1,2,3];

    // 【map(自帶回圈 並把處理值回填)】
    // 需求:對陣列arr的每個元素乘以2 賦值給new_arr
    let new_arr = []
    // 傳統方式:for迴圈
    for (let i=0;i<arr.length;i++){
        new_arr.push(arr[i]*2)
    };
    console.log(new_arr);
    // ES6的方式
    console.log(arr.map(num=>num*2));

    // 【reduce(接收倆引數,1.上一次reduce處理的結果 2.陣列中要處理的下一個元素)】
    // 需求:對陣列arr中每個元素相加
    add_res = arr.reduce(function(a,b){
        return a+b;
    });
    add_res = arr.reduce((a,b)=>a+b);  // 簡寫
    
    //(原理:輾轉相加)
    // arr = [1,2,3]
    // i=1        j=2 
    // i=3(i+j)   j=3
    // i=6(i+j)

    console.log(add_res);
</script>
  • 模組化開發(模組的匯入匯出):常用的CommonJS模組化規範(匯出用exports,匯入用require)和ES6規範(匯入用import,不過需要用babel降級到es2015)。目錄結構和程式碼如下:
    在這裡插入圖片描述

需要export的js檔案(四則運算.js):

// 模組化規範(引入自己寫的方法)
// commonjs(匯出用exports,匯入用require)

const sum = (a,b)=>a+b;
const sub = (a,b)=>a-b;
const mul = (a,b)=>a*b;
const div = (a,b)=>a/b;
// console.log(sum(1,2))

// 匯出給別人(exports不是export)
module.exports = {
    sum, sub, mul, div
}

需要require的js檔案(匯入測試.js):

const cal = require('./四則運算');

console.log(cal.sum(3,4));
console.log(cal.sub(3,4));
console.log(cal.mul(3,4));
console.log(cal.div(3,4));

es6規範:
需要export的js檔案(userApi.js):

// export function getList() {
//     // 真實業務是非同步獲取
//     console.log("獲取資料列表");
// }

// export function save() {
//     // 真實業務是儲存資料
//     console.log("儲存資料");
// }

// 也可以這麼寫(常用)
export default {
    getList() {
        console.log("獲取資料列表");
    },
    save() {
        console.log("儲存資料");
    }
}

需要import的js檔案(userTest.js):

import {getList,save} from './userApi.js'

getList();
save();
// 預設不支援es6語法 import 需要用babel降級到es2015

npm(Node Package Manager)

NPM(Node Package Manager)
node.js包管理工具(相當於pip),裝node的時候就已經自帶了
倉庫官網:https://www.npmjs.com/
看安裝版本:npm -v

npm的兩個用途:

  • 快速構建nodejs工程,方法 npm init 根據提示輸入後續內容(npm init -y預設都是yes), 最後在執行命令的目錄生成一個package.json, 內容如下:
{
    "name": "npmproj", // 工程名
    "version": "1.0.0",
    "description": "this is a npm project created by muyaostudio.",
    "main": "index.js", // 入口js
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
    },
    "author": "muyao",
    "license": "ISC"
}
// 類似maven的pom.xml
  • 快速安裝第三方依賴模組,比如 npm install mysqlnpm i mysql
    安裝完後產生在執行install命令的目錄下產生node_modules資料夾、package-lock.json檔案。
    在這裡插入圖片描述
    並在寫入package.json的屬性dependencies中:
    在這裡插入圖片描述
    這個檔案可以方便其他專案複用(類似python的requirement.txt):
    把本專案的package.json複製到新專案空白資料夾下 並執行npm install(不用init了 因為有package.json了)。為啥不直接複製node_modules資料夾呢?倒是可以,不過因為依賴錯綜複雜,不如重新下載來得方便。

下面是一些常用npm命令:

  • 匯入模組:const mysql = require("mysql")
  • 執行js:node xx.js (.js可以省略為node xx)
  • 通過cnpm命令用映象安裝依賴:
    首先安裝cnpm:npm install -g cnpm --registry:https://registry.npm.taobao.org (-g是全域性安裝)
    以後就能用了:cnpm install xxx
  • 下載多個包、指定版本號:npm install vue redis@1.1.x mysql
  • 解除安裝模組:npm uninstall vue mysql [-g]
  • 更新模組:npm update xxx

babel

es6某些高階語法在瀏覽器甚至nodejs環境裡沒法執行
於是,babel的作用:把es6程式碼降級為比如es5的程式碼

全域性安裝:npm install -g babel-cli
檢視版本:babel --version

實戰步驟:

  1. 新建node工程(npm init -y),新建./src/example.js 用es6語法寫程式碼

  2. 新建.babelrc,設定好要轉化到的版本,內容如下:
    {"presets": ["es2015"],"plugins": []}

  3. 當前目錄下安裝es2015轉化器:cnpm install --save-dev babel-preset-es2015。(--save-dev的原因是轉化器就開發時用,--save釋出的版本並不需要依賴這玩意)

  4. 執行 babel src -d dist 把src目錄下的所有js 轉化,存到dist目錄下。
    也可以通過自定義指令碼完成上述操作:改寫package.json,執行 npm run fuckes6

    "scripts": {"test": "echo "Error: no test specified" && exit 1","fuckes6": "babel src -d dist"  //新加的}

Webpack

webpack:前端資源載入、打包工具。
把多種靜態資源js css less轉成一個靜態檔案 減少頁面請求

全域性安裝:cnpm install -g webpack webpack-cli
看版本號:webpack -v

  • webpack合併js:

學習步驟:
1.建立nodejs專案 npm init -y
2.建立src目錄 存兩個需要合併的js:src/util.js和 src/common.js
3.準備一個入口檔案 src/main.js 把模組集中引入(用來彙總相關的js等資原始檔)
4.在根目錄下定義webpack.config.js設定打包規則
5.在根目錄下執行webpack命令 去dist資料夾檢視效果
6.在dist資料夾裡新建index.html引入生成的bundle.js 檢視效果

補充:
webpack -w可以監聽js改動並自動編譯打包

目錄結構如下:
在這裡插入圖片描述

  • webpack合併css

學習步驟:
1.安裝依賴npm install --save-dev style-loader css-loader(因為webpack預設只支援js打包)
2.在根目錄下定義webpack.config.js設定打包規則(module)
3.新建src/style.css,並在src/main.js 把css引入(require("./style.css");)
4.專案根目錄執行命令webpack(也可以執行webpack -w 邊改邊打包) 就會把js和css一起打包到同一個bundle.js裡!

其中:
設定打包規則webpack.config.js程式碼如下:

// 匯入path模組
const path = require("path");
// 自己定義js打包規則
module.exports = {
    // 從入口函數開始編譯打包
    entry: "./src/main.js",
    // 定義輸出的目錄 __dirname是當前專案根目錄 產生dist資料夾 合併成bundle.js
    output: {
        path: path.resolve(__dirname, "./dist"),
        filename: "bundle.js"
    },
    // 定義css打包規則
    module: {
        rules:[{
            test:/\.css$/, // 把所有css結尾的檔案打包
            use: ["style-loader", "css-loader"]
        }]
    }
}

入口檔案main.js程式碼如下:

// 匯入util和common
const util = require("./util");
const common = require("./common");

common.info(`Add result = ${util.add(3,4)}`);

// 匯入css
require("./style.css");

其他檔案:
在這裡插入圖片描述在這裡插入圖片描述
生成上圖所示壓縮和混淆後的bundle.js,寫個html,通過script引入測試一下:

<!DOCTYPE html>
<html lang="en">
<head>
    ...
</head>
<body>
    <script src="bundle.js"></script>
</body>
</html>
  • 補充
    webpack官網:https://webpack.docschina.org/
    當前 uniapp等框架或者腳手架已經內建了webpack,所以一般不用單獨去用了。

參考資料
https://www.bilibili.com/video/BV1BU4y147pS
https://www.kuangstudy.com/bbs/1351463043300708353