前端工程化築基-Node/npm/babel/polyfill/webpack

安木夕發表於2022-12-27

image.png

00、前端搬磚框架

開發構建部署上線摸魚

image


01、Node.js/npm

Node.JS 是一個基於 Chrome V8 引擎 的 JavaScript 執行時環境,不是JS庫(是C++開發的),是用來解釋執行JavaScript 程式碼的。我們開發Web應用中的JavaScript 程式碼都是執行在瀏覽器上,有了Node.JS,就可以用JavaScript 來開發中介軟體、後端服務了。

我們在VSCode中用到的很多元件都是基於Node.JS來開發執行的,如構建工具webpack、vue-cli。

image.png

1.1、什麼是npm?

npm(Node Package Manager)為Node.JS的包管理器,用來管理JS元件模組的,包括安裝、解除安裝、管理依賴等。很多語言都有自己的包管理器,如Javamaven.NetNuget等。

npm倉庫(registry):官方的 npm倉庫 存放了大量的、幾乎所有的 JS元件(輪子)。在這裡,你會發現你不是一個人在戰鬥!大家開源的各種前端元件庫都是釋出到這個集中式的大倉庫裡,使用npm工具就可以從倉庫裡學習(copy)、安裝使用各種元件了。

1.2、什麼是yarn/pnpm?

yarnpnpm的作用同npm一樣,都是包管理工具,使用方式都比較相似。

  • npm:這是Node.js官方自帶的包管理工具,
  • yarn:由於早期npm存在一些不完善的問題,於是一些大公司推出了yarn。
  • npm完善:受yarn的反向推動,後來npm逐步升級完善。
  • pnpm:一個比較新包管理工具,相比npm、yarn,有更好的下載速度、磁碟管理、依賴管理。

1.3、npm命令/配置

NodeJS官網 下載安裝包,安裝Node.JS的時候就自帶npm了,可以直接使用。npm是一個命令列工具,指令都是在cmd命令列工具中執行的,常用指令如下:

常用指令 說明
node -v 檢視nodeJS版本,也用來驗證node是否安裝
node 進入node命令環境,可執行任何JavaScript程式碼了
console.log('hello world') 在node環境中執行JS程式碼
npm -v 檢視npm版本
npm install -g <包名稱@版本號> 安裝一個模組,@可指定版本號,-g 表示全域性安裝。npm install -g vuex@3
npm uninstall <包名稱> 解除安裝一個模組
npm update <包名稱> 更新模組
npm list -g 檢視所有全域性安裝的模組
npm list <包名稱> 檢視模組的版本資訊,npm list vuex
npm init npm初始化,會生成一個 package.json 檔案
npm install 自動安裝 package.json 檔案中的模組
npm install -save <包名稱> package檔案的dependencies寫入依賴,用於生產環境。簡寫 npm i -S
npm install -save-dev <包名稱> package檔案的devDependencies寫入依賴,開發環境。簡寫:npm i -D
npm cache clean -f 清除快取

?配置本地的包儲存目錄:新建npm包的資料夾用於存放包的資源。

  • 全域性npm包儲存路徑 node_globalnpm config set prefix "D:\Project_Files\npm\node_global"
  • npm包的快取路徑 node_cachenpm config set cache "D:\Project_Files\npm\node_cache"

?環境配置:修改環境變數:系統屬性 ➤ 環境變數。重啟一下VSCode、命令列工具才生效。

  • 新增一個系統變數:系統變數 ➤ 新建:變數名=NODE_PATH,變數值= 上面準備好的全域性npm包的路徑下的模組路徑D:\Project_Files\npm\node_global\node_modules
  • 新增Path路徑:開啟系統變數列表中的Path變數,新建一個值=全域性npm路徑D:\Project_Files\npm\node_global

到這裡就完成了基礎配置了,可以透過命令安裝元件了。

image.png

?npm倉庫映象:預設的npm倉庫在國外,下載可能不穩定、比較慢,可以改為國內的淘寶映象(每10分鐘更新一次)。

  • 檢視包的倉庫地址:npm config get registry
  • 設定倉庫地址為淘寶映象:npm config set registry https://registry.npmmirror.com/
  • 或者安裝cnmp外掛:npm install -g cnpm --registry=https://registry.npmmirror.com

?在VSCode中使用

設定 >> Terminal › Integrated › Default Profile: Windows 的選項值為一個命令列工具,推薦“Git Bash”,重啟VS!就可以VSCode中的終端使用npm指令了。

image.png

1.4、package.json

每個專案都有一個 package.json 檔案,內容是一個json物件。用於定義專案依賴的各種模組,及專案配置資訊、模組的配置資訊。命令 npm init -y可建立一個初始package.json檔案。

{
  "name": "vuep3",			//*專案/模組名稱
  "version": "0.1.0",		//*專案版本,格式為:「主版本號. 次版本號. 修訂號」
  "private": true,			//是否私有
  "scripts": {					//npm 指令碼命令,透過 npm run 執行命令
    "serve": "vue-cli-service serve",					//啟動vue-cli-server服務
    "build": "vue-cli-service build",					//編譯
    "test:unit": "vue-cli-service test:unit", //執行單元測試
    "lint": "vue-cli-service lint"						//執行程式碼檢查?
  },
  "dependencies": {				//生產環境專案依賴,透過"npm install -save <包名稱>"安裝元件,或"npm i -S"
    "core-js": "^3.8.3",	//key為模組名,value為模組版本號
    "vue": "^2.6.14"		  //
  },
  "devDependencies": {		//開發環境專案依賴,開發、編譯中使用,不會輸出到生產環境,安裝指令:npm i -D
    "@babel/core": "^7.12.16",
    "@babel/eslint-parser": "^7.12.16",
    "@vue/cli-plugin-babel": "~5.0.0",
    "@vue/cli-plugin-eslint": "~5.0.0",
    "@vue/cli-service": "~5.0.0",
    "@vue/eslint-config-airbnb": "^6.0.0",
    "eslint": "^7.32.0",
    "eslint-plugin-import": "^2.25.3",
    "eslint-plugin-vue": "^8.0.3",
    "eslint-plugin-vuejs-accessibility": "^1.1.0",
    "vue-template-compiler": "^2.6.14"
  },
  "eslintConfig": {		//檢查檔案配置
    "root": true,
    "env": {"node": true},
    "extends": [ "plugin:vue/essential", "@vue/airbnb" ],
    "parserOptions": {"parser": "@babel/eslint-parser" },
    "rules": {}
  },
  "browserslist": [		//專案需要相容的瀏覽器配置,處理js、css相容性是會用到
    "> 1%",
    "last 2 versions",
    "not dead"
  ]
}

?package.json檔案中版本號的說明,版本號格式「主版本號. 次版本號. 修訂號」

  • ~:匹配最新的修改的版本號,"~1.2.3" 匹配 1.2.x 中最新的版本。
  • ^:匹配最新的此版本+修訂版本號,^1.2.3 會匹配 1.x.x 中最新的版本。
  • *:匹配最新的x.x.x版本。

02、babel/polyfill 為何物?

babel 是用來編譯JavaScript程式碼的,解決JavaScript相容性問題的。

image.png

2.1、什麼是polyfill?

polyfill 意為 膩子 /墊片,目的是解決JavaScript程式碼的相容性問題,解決方式就是用瀏覽器支援的方式模擬實現一遍。如ES2015+ 的很多不錯的特性在一些古老的瀏覽器下存在相容性問題,如非同步promise、map、新API方法等。於是就有了替代方案,如下示例程式碼,判斷如果不支援promise則模擬實現一個,這就稱之為 polyfill (polyfill/ˈpɒli fɪl/ 膩子指令碼)。

window.Promise = (function(window){
    if(window.Promise){
        return window.Promise
    }else{
        window.Promise = function(){  } // 相容程式碼,模擬實現
    }
})(window)

於是各種各樣的polyfill就出現了,為了統一規範和管理,於是出現了 babel

2.2、什麼是babel?

babel 是一個針對ECMScript語言相容性處理的工具鏈,(babel /ˈbeɪbl/ 巴別塔,一座通往天堂的高塔,來自聖經的故事),將ES2015+的程式碼轉譯為向後相容的JavaScript程式碼。其核心功能就是轉譯程式碼,轉譯過程簡單來說,先對JS程式碼進行詞法、語法分析抽象為語法樹,然後對語法樹進行變換和程式碼生成。第二步就有很多babel的工具鏈外掛參與了,用於不同型別程式碼的轉換生成。

image.png

babel能幹什麼?

  • 語法轉換,如let、const、箭頭函式等新的語法。
  • polyfill程式碼,如非同步promise、map、新API方法等。需引入外掛,如@babel/polyfill,由於存在全域性汙染+重複程式碼問題,被廢棄;@babel/plugin-transform-runtime 代替
  • 其他程式碼轉換,如TypeScript、JSX。

大量的冗餘程式碼怎麼辦?

使用babel,可以在程式碼編譯的時候就解決所有的JS相容性問題。但問題是冗餘JS程式碼會比較多,有些客戶的瀏覽器比較先進,並不需要polyfill(或只需要少量即可),也要載入這麼多JS。於是有兩個解決方法:

  • 靜態按需引入:在編譯時指定需要相容的瀏覽器及版本,按需引入polyfill,如@babel/preset-env外掛,useBuiltIns 引數設定需相容的瀏覽器。
  • 動態按需引入:把polyfill程式碼放到伺服器上,客戶端動態的判斷瀏覽器的情況再請求polyfill程式碼,如@polyfill.io方案。

❓怎麼使用?簡單瞭解下

  1. 安裝babel核心庫,@babel/core
  2. 安裝外掛babel的工具鏈外掛/預設(preset預設的外掛集合)
  3. 透過@babel/cli指令,或者webpackvue-cli來執行babel編譯轉換。

2.3、Vue-cli中的babel

vue-cli中使用了@vue/babel-preset-app預設,包含了babel-preset-env、JSX 支援以及為最小化包體積最佳化過的配置,可以透過 babel.config.js 進行配置。


03、webpack速覽

vue-cli 是建立在webpack基礎之上的,簡化了繁瑣的webpack配置和使用,先初步瞭解下webpack基本原理和流程。

image.png

3.1、webpack是幹什麼的?

webpack 是一個強大的前端構建工具,也是基於Node.js開發和執行,作用就是把開發態的各種程式碼編譯(構建、打包)為瀏覽器可(更好)執行的程式碼。webpack配置靈活,包含豐富的擴充套件外掛,webpack的各項能力也都是透過這些外掛來完成的。

image.png

✔️核心作用:提高開發效率!

  • ✅程式碼編譯:提高寫Bug效率,可以愉快的利用模組化、現代的ES6語法,及高階的CSS。
    • CSS程式碼編譯:less、sass的轉換,CSS相容性補全等。
    • JS程式碼編譯:ES6語法的相容性轉,利用babel/polyfill相關外掛
    • 程式碼校驗:對CSS、JS程式碼的規範性校驗檢查,ESLint外掛
    • 熱更新:開發態修改程式碼動態更新頁面,實時預覽,方便開發除錯。
  • ✅程式碼最佳化
    • 模組依賴,處理各種第三方元件的依賴,避免重複載入、衝突。
    • 程式碼模組打包:程式碼合併、壓縮,減少體積、網路請求次數。
    • 程式碼混淆:提高程式碼安全性。
    • 資源最佳化,不限於JS、CSS,支援處理各種資源,如小圖最佳化內嵌到程式碼中。

? 在webpack中,每個檔案都是模組,webpack 按照一定規則來載入、編譯這些模組。

image

?webpack 核心概念

  • ?entry 入口 : 從哪裡開始?從一個根檔案入口,如“./src/main.js”。
  • ?output 出口 : 到哪裡去?檔案編譯輸出位置,如“./dist”。
  • ?loader 載入器 : 對原始碼進行轉換,不同型別模組(檔案)採用不同的載入器來編譯轉換。
    • css程式碼:css-loader、less-loader、sass-loader、postcss-loader ... 。
    • 圖片資源:url-loader、file-loader ... 。
    • HTML:html-minify-loader 壓縮。
    • Javscriptbabel-loader轉換ES6檔案到ES5,babel是webpack內建的JS編譯器元件。
    • ...等等。
  • ?plugin 外掛 : 處理載入器完成不了的功能,透過webpack暴露的API和生命週期鉤子來執行各種處理,所以外掛可以在打包的不同階段參與。
    • 打包輸出檔案處理:拆分chunk以控制輸出的檔案,如提取css到一個單獨檔案。
    • vue中複製public到輸出目錄的copy-webpack-plugin
    • 每次打包前清空dist目錄的 clean-webpack-plugin

3.2、構建流程

webpack的構建是一個序列過程,這個過程就是把各個外掛(loader、plugin)串聯起來執行。✏️畫圖圖吧,大概這樣子的:

image

① 初始化?

  • 讀取並組裝配置資訊進行初始化,配置資訊來源包括配置檔案、cli引數、預設配置。
  • 初始化外掛、配置外掛的引數。

② 編譯?

  • entry入口檔案開始(vue中入口檔案預設為“./src/main.js”),遞迴找到所有的依賴模組,呼叫相應的loader編譯處理檔案內容。
  • 產生chunk:chunk(/tʃʌŋk/ 塊)是webpack構建過程中的塊,一個chunk包括等多個模組,為某個入口檔案找到的所有依賴模組。然後webpack根據配置為chunk 生成資源列表(chunk assets),最終輸出到檔案。

image.png

③ 輸出?

根據配置確定輸出的路徑、檔名,輸出到檔案系統。

3.3、安裝使用

npm安裝webpackwebpack-cli兩個元件。

//1.全域性環境安裝webpack
npm install webpack -g
//2.進入專案目錄
npm init -y   //初始化npm,-y忽略詢問
npm install webpack webpack-cli --save-dev   //安裝webpack、webpack-cli 到開發環境
webpack.config.js檔案簡介:
var path = require('path');

module.exports = {
  //模式 開發模式打包的是未壓縮檔案
  mode:"development",
  // 入口檔案,是模組構建的起點,同時每一個入口檔案對應最後生成的一個 chunk。
  entry: './src/main.js',

// 生成檔案,是模組構建的終點,包括輸出檔案與輸出路徑。
output: {
  path: path.resolve(__dirname, 'dist'),
    filename: '[name].js'
},
// 這裡配置了處理各模組的 loader ,包括 css 預處理 loader ,es6 編譯 loader,圖片處理 loader。
module: {
  rules: [
    {
      test: /\.m?js$/,
      exclude: /(node_modules|bower_components)/,
      use: {
        loader: 'babel-loader',
        options: { presets: ['@babel/preset-env'] }
      }
    }
    { test: /\.css$/, use: 'css-loader' },
  { test: /\.ts$/, use: 'ts-loader' }
  ]},
// webpack 各外掛物件,在 webpack 的事件流中執行對應的方法。
plugins: [
  new webpack.HotModuleReplacementPlugin()
]
};

package.json中新增構建指令,就可以執行了:npm run build來編譯程式碼了。

"scripts": {
    "build":"webpack"
},

04、express搭建簡易伺服器

express 是一個基於Node.js 的元件,用於搭建一個WEB伺服器,使用非常簡便、靈活,(express /ɪkˈspres/ 快速、快遞)。有必要了解一下,就可以自己開發服務端API了。

express 是 Node.js 官方推薦的Web開發框架,使用廣泛,除了核心http服務,還有很多功能。如靜態資源服務、模板解析(可用於服務端渲染)、豐富的外掛支援等。如果要建立一個完整的後端專案,可以藉助express的腳手架元件搭建一個更完整的web框架。

①、準備環境:先建立一個專案資料夾 server-express

//1、建立一個專案資料夾 server-express
//2、進入專案目錄
cd ../server-express
//3、初始化npm
npm init -f
//4、安裝express
npm install express -D

image.png

②、編寫服務端程式:建立一個index.js

//引入express模組,注意該程式碼是要基於Node.js執行,需要用Node的模組寫法
let express = require('express');
let path = require('path');
//建立express例項
let server = new express();
//設定靜態資源訪問,就可以直接訪問./static 目錄的靜態資源了
server.use('/static',express.static(path.resolve(__dirname, './static')));
//啟用json解析支援,用於解析body的json資料
server.use(express.json());  
//新增監聽埠
server.listen(3000, err => {
    if (!err)
        console.log('伺服器端啟動成功!地址:http://localhost:3000');
})

//配置API路由:get
server.get('/user/:userId', (req, res) => {
    //req.params 獲取路由動態引數,req.query獲取url上的get引數,同vue-router
    console.log(req.params, req.query);
    //返回響應資料
    res.json({ id: req.params.userId, name: 'sam', age: 30 });
})
//配置API路由:post
server.post('/user/add', (req, res) => {
    //req.body 獲取post資料
    console.log(req.body);
    //返回響應資料
    res.send({ status: 'OK', message: "更新成功" });
})

③、執行node index.js

//啟動服務端
$ node index.js
伺服器端啟動成功!地址:http://localhost:3000

//測試
http://localhost:3000/static/img01.jpg
http://localhost:3000/user/100?type=vip
http://localhost:3000/user/add   // post: {"name": "張三",  "age": 40}

#參考資料


©️版權申明:版權所有@安木夕,本文內容僅供學習,歡迎指正、交流,轉載請註明出處!原文編輯地址-語雀

相關文章