Webpack原理與實(shí)踐:webpack如何利用插件機(jī)制橫向擴(kuò)展構(gòu)建能力?
寫在前面
webpack插件機(jī)制的目的是:為了增強(qiáng)webpack在項(xiàng)目自動(dòng)化構(gòu)建方面的能力。插件最常見的應(yīng)用場(chǎng)景是:
- 實(shí)現(xiàn)自動(dòng)在打包之前清除dist目錄(上次打包的結(jié)果)
- 自動(dòng)生成應(yīng)用所需的html文件
- 根據(jù)不同環(huán)境為代碼注入類似API地址這種可能變化的部分
- 拷貝不需要參與打包的資源文件到輸出目錄
- 壓縮webpack打包完成后輸出的文件
- 自動(dòng)發(fā)布打包結(jié)果到服務(wù)器實(shí)現(xiàn)自動(dòng)部署
插件機(jī)制
webpack每次打包的結(jié)果都是直接覆蓋到dist目錄,打包前,dist目錄中可能已經(jīng)存在上一次打包操作時(shí)遺留的文件,再次打包時(shí),只能覆蓋掉同名文件,已經(jīng)移除的資源文件會(huì)一直累積在里面,最終導(dǎo)致部署上線時(shí)出現(xiàn)多余文件。很明顯這是不合理的。
更好的做法當(dāng)然是:在每次完整打包淺,自動(dòng)明清理dist目錄,每次打包過后,dist目錄中就只會(huì)存在那些必要的文件。我們可以依賴第三方npm包:clean-webpack-plugin。安裝后回到webpack的配置文件中,導(dǎo)入clean-webpack-plugin插件,該插件模塊導(dǎo)出CleanWebpackPlugin。
- //webpack.config.js
- const path = require("path")
- const {CleanWebpackPlugin} = require("clean-webpack-plugin")
- module.exports = {
- entry:"./src/index.js",
- output:{
- filename:"bundle.js",
- },
- mode:"none",
- plugins:[
- new CleanWebpackPlugin()
- ]
- }
- // src/index.js
- console.log("nihao nihao");
打包壓縮后的代碼:
- /******/ (() => { // webpackBootstrap
- var __webpack_exports__ = {};
- console.log("nihao nihao");
- /******/ })()
- ;
我們知道html文件一般都是通過硬編碼的方式,單獨(dú)存放在項(xiàng)目的根目錄下,這種方式有兩個(gè)問題:
- 項(xiàng)目發(fā)布時(shí),我們需要同時(shí)發(fā)布根目錄下的html文件和dist目錄中所有打包的打包結(jié)果,非常麻煩,而且上線后還要確保html代碼中的資源文件正確
- 如果打包結(jié)果輸出的目錄或文件名發(fā)生變化,那么html代碼中對(duì)應(yīng)的script標(biāo)簽需要我們手動(dòng)修改路徑
為此webpack也有相關(guān)的插件自動(dòng)生成html,相對(duì)于之前寫死html文件的方式,自動(dòng)生成html的優(yōu)勢(shì)在于:
- html也輸出到dist目錄中,上線時(shí)只需要把dist目錄發(fā)布出去
- html中的script標(biāo)簽是自動(dòng)引入的,所以可以確保資源文件的路徑是正常的
安裝后回到配置文件,載入此模塊,相對(duì)于clean-webpack-plugin需要解構(gòu)內(nèi)部成員所不同,html-webpack-olugin插件默認(rèn)導(dǎo)出的就是插件類型。
對(duì)于生成的html文件,頁面的title需要修改,許多時(shí)候還需要我們自定義頁面的一些meta標(biāo)簽和基礎(chǔ)dom結(jié)構(gòu)。
- const path = require("path")
- const {CleanWebpackPlugin} = require("clean-webpack-plugin")
- const HtmlWebpackPlugin = require("html-webpack-plugin")
- module.exports = {
- entry:"./src/index.js",
- output:{
- filename:"bundle.js",
- },
- mode:"none",
- plugins:[
- new CleanWebpackPlugin(),
- new HtmlWebpackPlugin({
- title:"hello webpack",
- template:"./src/index.html"
- })
- ]
- }
指定要打包的html文件:
- <!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><%= htmlWebpackPlugin.options.title %></title>
- </head>
- <body>
- <div class="container">
- <h1>頁面結(jié)構(gòu)</h1>
- <div id="root"></div>
- </div>
- </body>
- </html>
這樣就自動(dòng)生成了一個(gè)html文件:
- <!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>hello webpack</title>
- <script defer src="bundle.js"></script></head>
- <body>
- <div class="container">
- <h1>頁面結(jié)構(gòu)</h1>
- <div id="root"></div>
- </div>
- </body>
- </html>
html-webpack-olugin除了可以自定義輸出文件內(nèi)容,同時(shí)還可以輸出多個(gè)html文件,通過HtmlWebpackPlugin創(chuàng)建的對(duì)象是用于生成index.html文件的,玩去哪可以再創(chuàng)建一個(gè)新的實(shí)例對(duì)象,用于創(chuàng)建額外的html文件。
對(duì)于項(xiàng)目中一些不需要參與構(gòu)建的靜態(tài)文件如:網(wǎng)站的favicon、robots.txt文件等,但是需要發(fā)布在線上。那么可以將這類文件統(tǒng)一放在根目錄下的public或static目錄中,希望webpack在打包時(shí)一并將這個(gè)目錄下所有的文件復(fù)制到輸出目錄,這種需求可以使用copy-webpack-plugin插件的實(shí)現(xiàn)。
- plugins:[
- new CleanWebpackPlugin(),
- new HtmlWebpackPlugin({
- title:"hello webpack",
- template:"./src/index.html"
- }),
- new CopyWebpackPlugin([
- "public"//需要拷貝的目錄或者路徑
- ])
- ]
參考文章
- 《webpack原理與實(shí)踐》
- 《webpack中文文檔》
寫在最后
簡單了解了幾個(gè)常用的插件,一般適合用于任何類型的項(xiàng)目,不管是否使用了框架。webpack為每個(gè)工作環(huán)節(jié)都預(yù)留了合適的鉤子,擴(kuò)展時(shí)只需要找到合適的時(shí)機(jī)去做合適的事情。