前天介紹的 Babel,以及昨天介紹的 ES module,處理了一些關於程式碼編譯轉換,以及模組化的概念。
有了它們之後,還需要一個整合性的工具,將這些零散的東西整合起來,今天來討論 Webpack。
我們已經有像是 ES module、CommonJS、AMD 等模組化工具,可以將 js 程式碼切割成多個模組,再透過 import
/ export
之類的語法,將模組組合起來。
不過光有模組還不夠,畢竟除了自己寫的模組,也會需要引用一些從 npm 或 yarn 安裝的外部模組,外部安裝的模組會放在 node_modules
裡面,雖然可以把它們的路徑寫成這樣:
import XXX from './node_modules/xxx/index.js'
這樣其實是相對不方便的,閱讀性也比較差。
同時,還需要處理各種模組工具的差異,比如 ES module 是用 import
/ export
,而 CommonJS 則是用 require
/ module.exports
,需要一個工具能夠整合這些差異。
另外,以上都只討論到純 js 的需求,如果今天想要把 html、css 甚至圖片檔案讀進來 js 裡面使用,都還沒有比較好的方式可以支援。
Webpack 是一個 module bundler,顧名思義就是「將模組打包起來」的工具。
「模組」我們已經知道是透過 ES module 或 CommonJS 產生的,那「打包」呢?Webpack 的「打包」其實包含了很多事情,主要可以透過兩種設定來完成:
Loaders 主要負責的是「將資源轉換為可讀取的模組」,是一種檔案的前處理,比如 html、css、TypeScript 甚至圖片檔案,都有相對應的 loader 可以處理:
module.exports = {
module: {
rules: [
{ test: /\.css$/, use: 'css-loader' },
{ test: /\.ts$/, use: 'ts-loader' },
{ test: /\.html$/, use: 'html-loader' },
],
},
};
甚至針對有處理順序的檔案,也可以安排 bottom-up 的 chain 來處理,比如 sass -> css -> style:
<style>
tag 插入 DOM treemodule.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader", "sass-loader"]
}
]
}
};
更多可以參考官網列出來的 loaders 清單,甚至不夠用還可以自己用 Node.js 寫。
Plugins 負責的是 loaders 做不到的事情,可以參考官網列出來的 plugins 清單。
比如可以做到 Hot Module Replacement(HMR),也就是當我們成功打包過程式碼後,因為開發過程會頻繁去修改某些模組,但又不希望每次改幾行 code 就整個重新打包,這時就需要 HMR plugin 來幫忙,僅有修改到的局部模組重新打包,可以大幅提升開發效率。
另外像是圖片壓縮、程式碼 minify、uglify,以及 css 檔案分離等,都可以用 plugins 做到。
Webpack 功能之多,也導致 config 設定檔相對困難,要寫出一個打包流程「不多不少剛剛好」的設定檔,往往需要一些時間嘗試,或者一開始就用 create-react-app 等建構工具自動完成。建議一開始就好好將 Webpack 設定檔寫好。
只要是使用模組化方式開發的程式碼,都非常適合使用 Webpack,基本上想不太到什麼不使用的理由,畢竟以現在複雜的程式環境來說,常常混雜了許多不同的資源,透過 Webpack 這樣的打包工具,能夠讓專注力更加集中在開發上面!
Webpack 做掉的事情之多,可能需要一次鐵人賽 30 天的時間才講得完吧XD 實在很難在一天之內寫完,不過起碼抓住最核心的一些應用,以及為什麼使用 Webpack 的理由,我想只有在掌握了這一點之後,再循序漸進去理解每個 loader 與 plugin,才會更加事半功倍!