如何使用Webpack工具構建專案

2023-04-21 12:01:19

起步

webpack 用於編譯 JavaScript 模組。一旦完成 安裝,你就可以通過 webpack CLI 或 API 與其配合互動。如果你還不熟悉 webpack,請閱讀 核心概念 和 對比,瞭解為什麼要使用 webpack,而不是社群中的其他工具。

執行 webpack 5 的 Node.js 最低版本是 10.13.0 (LTS)。

基本安裝

首先我們建立一個目錄,初始化 npm,然後 在本地安裝 webpack,接著安裝 webpack-cli(此工具用於在命令列中執行 webpack):

mkdir webpack-demo
cd webpack-demo
npm init -y
npm install webpack webpack-cli --save-dev

在整個指南中,我們將使用 diff 塊,來展示對目錄、檔案和程式碼所做的修改。例如:

 this is a new line you shall copy into your code
 and this is a line to be removed from your code
  and this is a line not to touch.

現在,我們將建立以下目錄結構、檔案和內容:

project

webpack-demo
  |- package.json
  |- package-lock.json
 |- index.html
 |- /src
   |- index.js

src/index.js

function component() {
  const element = document.createElement('div');

  // lodash(目前通過一個 script 引入)對於執行這一行是必需的
  element.innerHTML = _.join(['Hello', 'webpack'], ' ');

  return element;
}

document.body.appendChild(component());

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>起步</title>
    <script src="https://unpkg.com/[email protected]"></script>
  </head>
  <body>
    <script src="./src/index.js"></script>
  </body>
</html>

我們還需要調整 package.json 檔案,以便確保我們安裝包是 private(私有的),並且移除 main 入口。這可以防止意外發布你的程式碼。

package.json

 {
   "name": "webpack-demo",
   "version": "1.0.0",
   "description": "",
  "main": "index.js",
  "private": true,
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1"
   },
   "keywords": [],
   "author": "",
   "license": "MIT",
   "devDependencies": {
     "webpack": "^5.38.1",
     "webpack-cli": "^4.7.2"
   }
 }

在此範例中,<script> 標籤之間存在隱式依賴關係。在 index.js 檔案執行之前,還需要在頁面中先引入 lodash。這是因為 index.js 並未顯式宣告它需要 lodash,假定推測已經存在一個全域性變數 _

使用這種方式去管理 JavaScript 專案會有一些問題:

  • 無法直接體現,指令碼的執行依賴於外部庫。
  • 如果依賴不存在,或者引入順序錯誤,應用程式將無法正常執行。
  • 如果依賴被引入但是並沒有使用,瀏覽器將被迫下載無用程式碼。

讓我們使用 webpack 來管理這些指令碼。

建立一個 bundle

首先,我們稍微調整下目錄結構,建立分發程式碼(./dist)資料夾用於存放分發程式碼,原始碼(./src)資料夾仍存放原始碼。原始碼是指用於書寫和編輯的程式碼。分發程式碼是指在構建過程中,經過最小化和優化後產生的輸出結果,最終將在瀏覽器中載入。調整後目錄結構如下:

project

 

 webpack-demo
  |- package.json
  |- package-lock.json
 |- /dist
   |- index.html
 |- index.html
  |- /src
    |- index.js

要在 index.js 中打包 lodash 依賴,我們需要在本地安裝 library:

 

 

現在,在我們的 script 中 import lodash

src/index.js

import _ from 'lodash';

 function component() {
   const element = document.createElement('div');

  // lodash(目前通過一個 script 引入)對於執行這一行是必需的
  // lodash 在當前 script 中使用 import 引入
   element.innerHTML = _.join(['Hello', 'webpack'], ' ');

   return element;
 }

 document.body.appendChild(component());

現在,我們將會打包所有指令碼,我們必須更新 index.html 檔案。由於現在是通過 import 引入 lodash,所以要將 lodash <script> 刪除,然後修改另一個 <script> 標籤來載入 bundle,而不是原始的 ./src 檔案:

dist/index.html

 <!DOCTYPE html>
 <html>
   <head>
     <meta charset="utf-8" />
     <title>起步</title>
    <script src="https://unpkg.com/[email protected]"></script>
   </head>
   <body>
    <script src="./src/index.js"></script>
    <script src="main.js"></script>
   </body>
 </html>

在這個設定中,index.js 顯式要求引入的 lodash 必須存在,然後將它繫結為 _(沒有全域性作用域汙染)。通過宣告模組所需的依賴,webpack 能夠利用這些資訊去構建依賴圖,然後使用圖生成一個優化過的 bundle,並且會以正確順序執行。

可以這樣說,執行 npx webpack,會將我們的指令碼 src/index.js 作為 入口起點,也會生成 dist/main.js 作為 輸出。Node 8.2/npm 5.2.0 以上版本提供的 npx 命令,可以執行在初次安裝的 webpack package 中的 webpack 二進位制檔案(即 ./node_modules/.bin/webpack):

$ npx webpack
[webpack-cli] Compilation finished
asset main.js 69.3 KiB [emitted] [minimized] (name: main) 1 related asset
runtime modules 1000 bytes 5 modules
cacheable modules 530 KiB
  ./src/index.js 257 bytes [built] [code generated]
  ./node_modules/lodash/lodash.js 530 KiB [built] [code generated]
webpack 5.4.0 compiled successfully in 1851 ms

在瀏覽器中開啟 dist 目錄下的 index.html,如果一切正常,你應該能看到以下文字:'Hello webpack'

模組

ES2015 中的 import 和 export 語句已經被標準化。雖然大多數瀏覽器還無法支援它們,但是 webpack 卻能夠提供開箱即用般的支援。

事實上,webpack 在幕後會將程式碼 「轉譯」,以便舊版本瀏覽器可以執行。如果你檢查 dist/main.js,你可以看到 webpack 具體如何實現,這是獨創精巧的設計!除了 import 和 export,webpack 還能夠很好地支援多種其他模組語法,更多資訊請檢視 模組 API

注意,webpack 不會更改程式碼中除 import 和 export 語句以外的部分。如果你在使用其它 ES2015 特性,請確保你在 webpack loader 系統 中使用了一個像是 Babel 的 transpiler(轉譯器)

使用一個組態檔

在 webpack v4 中,可以無須任何設定,然而大多數專案會需要很複雜的設定,這就是為什麼 webpack 仍然要支援 組態檔。這比在 terminal(終端) 中手動輸入大量命令要高效的多,所以讓我們建立一個組態檔:

project

  webpack-demo
  |- package.json
  |- package-lock.json
 |- webpack.config.js
  |- /dist
    |- index.html
  |- /src
    |- index.js

webpack.config.js

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist'),
  },
};

現在,讓我們通過新的組態檔再次執行構建:

$ npx webpack --config webpack.config.js
[webpack-cli] Compilation finished
asset main.js 69.3 KiB [compared for emit] [minimized] (name: main) 1 related asset
runtime modules 1000 bytes 5 modules
cacheable modules 530 KiB
  ./src/index.js 257 bytes [built] [code generated]
  ./node_modules/lodash/lodash.js 530 KiB [built] [code generated]
webpack 5.4.0 compiled successfully in 1934 ms

比起 CLI 這種簡單直接的使用方式,組態檔具有更多的靈活性。我們可以通過設定方式指定 loader 規則(loader rule)、plugin(外掛)、resolve 選項,以及許多其他增強功能。更多詳細資訊請檢視 設定檔案

npm scripts

考慮到用 CLI 這種方式來執行原生的 webpack 副本並不是特別方便,我們可以設定一個快捷方式。調整 package.json 檔案,新增一個 npm script

package.json

 {
   "name": "webpack-demo",
   "version": "1.0.0",
   "description": "",
   "private": true,
   "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
   },
   "keywords": [],
   "author": "",
   "license": "ISC",
   "devDependencies": {
     "webpack": "^5.4.0",
     "webpack-cli": "^4.2.0"
   },
   "dependencies": {
     "lodash": "^4.17.20"
   }
 }

現在,可以使用 npm run build 命令,來替代我們之前使用的 npx 命令。注意,使用 npm scripts,我們可以像使用 npx 那樣通過模組名參照本地安裝的 npm packages。這是大多數基於 npm 的專案遵循的標準,因為它允許所有貢獻者使用同一組通用指令碼。

現在執行以下命令,然後看看你的指令碼別名是否正常執行:

$ npm run build

...

[webpack-cli] Compilation finished
asset main.js 69.3 KiB [compared for emit] [minimized] (name: main) 1 related asset
runtime modules 1000 bytes 5 modules
cacheable modules 530 KiB
  ./src/index.js 257 bytes [built] [code generated]
  ./node_modules/lodash/lodash.js 530 KiB [built] [code generated]
webpack 5.4.0 compiled successfully in 1940 ms

結論

現在,你已經有了一個基礎構建設定,你應該移至下一章節 資源管理 指南,以瞭解如何通過 webpack 來管理資源,例如 images、fonts。此刻你的專案看起來應該如下:

project

webpack-demo
|- package.json
|- package-lock.json
|- webpack.config.js
|- /dist
  |- main.js
  |- index.html
|- /src
  |- index.js
|- /node_modules