[Tools] 模組化打包 About Webpack

[Tools] 模組化打包 About Webpack

前言

先前有介紹一篇關於gulp的用法,當中有比較gulp和webpack兩者之間的優缺點,若還沒看過可先看這一篇 前端自動化管理 About Gulp 4.0,本篇的話會來整理webpack的觀念和基礎用法。

用Webpack要做什麼?

也是用來把來源 編譯、壓縮打包 輸出成瀏覽器可以讀懂的或是效能更好的檔案。

Webpack 基礎安裝

安裝前,因為是基於Node.js開發,當然先需要Node.js,這邊就不詳細介紹。npm管理工具會隨著node.js一起安裝好,接著我們可以用npm安裝webpack

專案初始化生成package.json
npm init

安裝 webpack webpack-cli
npm install webpack webpack-cli --save-dev

  • 使用–save會把模組加到dependencies執行專案時用,–save-dev則會添加到devDependencies給開發專案時使用。

  • 安裝webpack的過程中,有遇到zsh: command not found: webpack的問題,因為我的終端機是使用zsh,這邊需要下面這些步驟來解決路徑問題

echo 'export PATH="./node_modules/.bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

設定 Entry & Output

這邊會需要先建立webpack的設定檔 webpack.config.js

entry 輸入端: 資料來源,一般就是從src資料夾
output 輸出端: 資料輸出的放置位置,

1
2
3
4
5
6
7
8
9
const path = require('path');

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

要打包輸出就直接輸入webpack即可開始運行。
也可在package.json中的script添加run的名稱,例如build去執行webpack這個指令 “build”: “webpack”

npm run build

也可依照專案需求去設定指令。這邊參照mike大的教學
watch : 修改程式碼就同步編譯執行,設定成 development 版本。
start : 執行一次性編譯,設定成 development 版本。
deploy : 執行一次性編譯,設定成 production 版本。

1
2
3
4
5
"scripts": {
"watch": "webpack --mode development --watch",
"start": "webpack --mode development",
"deploy": "webpack --mode production"
},

常用的loaders

要用webpack來編譯什麼,就會使用不同的loaders來實現,像是編譯ES6的babel-loader,編譯Sass的sass-loader,有非常多種,從下面連結可以查詢。

接下來會介紹比較常用的,基本用法都蠻類似的
掛載在module內的loaders是從下往上讀取

Webpack + BABEL 轉譯ES6語法

這邊會先安裝 babel-loader 這個套件

npm install -D babel-loader @babel/core @babel/preset-env

在webpack.config.js中添加babel loader的設定,一般loaders都是掛載在module下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const path = require('path');

module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.bundle.js',
},
module: { //loaders放置在module
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [['@babel/preset-env', { targets: 'defaults' }]],
},
},
},
],
},
};

Webpack 模組化

要把各個模組的js統合成一個最終js檔案,可以解決js loading的先後順序問題。
主要就是利用export和import,經過webpack就會統整成最終js。

在組件的js(ex Menu.js)做export

1
2
3
export default function Menu() {
console.log('menu');
}

在要統整的主檔案js(ex index.js)做import

1
2
3
4
import Menu from './menu.js'
window.onload = function() {
Menu();
}

Webpack + SASS 編譯

編譯sass同時也編譯css,這邊會先安裝 css-loader、sass-loader和style-loader,載入到header中的style,css webpack預設編譯成js

npm install css-loader style-loader --save-dev
npm install sass-loader node-sass --save-dev

一樣是在webpack.config.js中加入module

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.s[ac]ss$/i,
use: [
// Creates `style` nodes from JS strings
'style-loader',
// Translates CSS into CommonJS
'css-loader',
// Compiles Sass to CSS
'sass-loader',
],
},
],
},

在統合的js中import要編譯的scss檔

1
import './all.scss';

Plugins

與loaders的差異:loaders用在處理單一js檔案,在bundle之前或是正在bundle的階段。而Plugins是在bundle或是chunk的階段,通常是在bundle產生的最後階段。

Plugins有兩種,built-in plugins,在webpack就可以使用和第三方開發的plugins,用npm install安裝上去,可以補強一些Webpack的功能,像是uglify、minify、移除未使用的CSS(PurgeCSS)等。

mini-css extract plugins

若是想把css額外輸出成一個.css的檔案,則需用mini-css extract plugins,
上面所提到的css-loader 和 style-loader是 將 CSS 樣式注入到 HTML 的 style 標籤裡面。

npm install mini-css-extract-plugin --save-dev
npm install css-loader --save-dev

webpack.config.js中設定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
};

在統合的js中import要編譯的css檔

1
import './style.css';

還可以修改生成路徑,例如css資料夾底下

1
2
3
4
5
6
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[name].css',
}),
],

Chunk

更深入去了解Webpack,可能會接觸到這個名字Chunk,這邊我先把目前能夠理解的列出來,更深入可以到這邊慢慢研究

Chunk是Webpack打包過程中,一堆module的集合。Webpack的打包是從一個入口文件開始,也可以說是入口模塊,入口模塊引用這其他模塊,模塊再引用模塊。Webpack通過引用關係逐個打包模塊,這些module就形成了一個Chunk。
如果我們有多個入口文件,可能會產出多條打包路徑,一條路徑就會形成一個Chunk。Chunk是過程中的代碼塊,Bundle是結果的代碼塊。

…待續

參考資料

[Tools] 模組化打包 About Webpack

https://kaiyuncheng.github.io/2020/12/12/webpack/

Author

KaiYun Cheng

Posted on

2020-12-12

Updated on

2020-12-26

Licensed under

Comments

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×