宣告:所有的文章demo都在我的倉庫裡
程式碼分離
程式碼分離的有點在於:
- 切割程式碼,生成不同的打包檔案,按需載入這些檔案。
- 每個bundle的體積更小
- 控制外部資源的載入順序
常用的方法有:
- 入口起點:使用入口
entry
手動分離 - 防止重複:使用
SplitChunksPlugin
去重和分離chunk
- 動態匯入:通過模組的行內函數呼叫分離的程式碼
入口起點
新增另一個檔案another-module.js
檔案,並在webpack.config.js
中進行配置。
entry:{//打包入口
index:'./src/index.js',
another:'./src/another-module.js'
},
進行打包後,結果正常。
優點:常用常規的寫法。
缺點:1.如果有相同的模組,不會去重,還是會在每個bundle中被重複的引用。2.不能將核心程式碼進行分割
防止重複
入口依賴
配置dependOn
選項,可以在多個chunk之間進行共享模組。
SplitChunkPlugin
為了解決多個bundle引入相同模組的問題,引入這個模組進行去重。
SplitChunkPlugin
將公共的模組引入到已有的入口中,或者提取到新的chunk。
相關配置如下:
//webpack.config.js
optimization:{
splitChunks:{
chunks:'all'
}
},
SplitChunkPlugin建立了新的chunk,如下圖所示,shared.bundle.js。將我其他頁面所使用的js引入的lodash模組引入這個檔案中。
*** 以上程式碼在webpack-demo5
中
快取
通常部署檔案是將webpack打包出來的/dist
檔案,部署到server
上,客戶端通過訪問server
的網站及資源。
由於客戶端訪問server
時,非常耗時和耗流量,於是瀏覽器採用快取技術,可以直接從快取中獲取相關的內容,降低了請求的速度和流量。但是這也有一個缺點:如果檔名跟之前的一致,瀏覽器會認為這個檔案沒有做修改,還是會從快取中獲取相關內容。
我們想要的現象是:檔案沒做修改時,瀏覽器從快取中獲取,檔案修改了,重新獲取。
輸出檔案的檔名
webpack提供了一個substitution
(可替換的模版字串)的方式,通過帶括號字串來模版化檔名。其中的[contenthash]
是根據資源內容建立唯一的hash
。當資源內容變化時,[contenthash]
也會發生變化。
相關配置如下:
entry:'./src/index.js',
output:{//打包出口
filename:"[name].[contenthash].js",//打包後的檔名稱
path:path.resolve(__dirname,'dist')//路徑
},
使用contenthash,將內容變化直接反應打包輸出檔案的變化。
檔案不做修改,再次執行npm run build時,文件描述如下:
在我的實際操作中,我的打包檔案是不變的。
第一次:
第二次:
可能跟webpack版本的關係所致。。。
模組的概念
runtime:每個模組的載入和模組的解析邏輯。
manifest:解析和對映模組之間的聯絡
提取引導模版
將runtime
程式碼,提取到一個單獨的chunk中。optimization.runtimeChunk:'single'
表示為所有的chunk建立一個runtime bundle
。
程式碼如下:
optimization:{
runtimeChunk:'single'
},
將所有的第三方庫,如lodash/react
等提取到單獨的vendor chunk
檔案中。由於這些第三方庫不會去頻繁的修改原始碼,所以可以讓更少的向server
發請求。
配置如下:
const path=require('path');
const {CleanWebpackPlugin}=require('clean-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')
module.exports={
mode:'development',
entry:'./src/index.js',
output:{//打包出口
filename:"[name].[contenthash].js",//打包後的檔名稱
path:path.resolve(__dirname,'dist')//路徑
},
devtool: 'inline-source-map',
devServer:{
contentBase:'./dist'
},
optimization:{
runtimeChunk:'single',
splitChunks:{
cacheGroups:{
vendor:{
test:/[\\/]node_modules[\\/]/,
name:'vendor',
chunks:'all'
}
}
}
},
plugins:[
new CleanWebpackPlugin({
cleanStaleWebpackAssets:false
}),
new HtmlWebpackPlugin({
title:'管理輸出'
})
]
}
結果會出現一個帶有vendor
的檔案。
在main
檔案裡,不再含有來自node_module
的vendor
程式碼,而且體積也減少了。
模組識別符號
新增print模組,並在index中進行引入,最終打包的結果跟之前比較結果如下:
我本地打包只有main的檔案進行了變化----符合預期
然而官網上展示的例子是不一樣,引出了需要引入optimization.moduleIds:'hashed'
---苦笑不得
*** 以上程式碼在webpack-demo6
中
環境變數
可以在package.json
中配置相關的命令列,可以快速的執行開發環境
和生產環境
。
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"start": "webpack serve --env development"
},
表示執行development
環境。
模組熱替換(HMR)
模組熱替換(HMR--hot module replacement):在程式執行過程中,若有替換/新增/刪除模組,只更新修改的部分,不需要更新整個頁面。
此功能暫不支援生產環境。
程式碼配置如下:
devServer:{
contentBase:'./dist',
hot:true
},
在index頁面加入程式碼
if(module.hot){
module.hot.accept('./print.js',function(){
console.log('update the module1');
Print()
})
}
注意:執行時使用npm run start
,啟動服務,可檢視熱更替。
*** 以上程式碼在webpack-demo7
中
模組熱更替跟熱更新是兩回事。模組熱更新是指修改了某個部分程式碼,不會重新整理頁面,而是在頁面更新這個模組。熱更新是指及時重新整理頁面。
Tree shaking
概念
是指在打包的時候,剔除沒有用到的程式碼。
但是隻支援ES module的import和export用法。
實踐
打包過程分成3部分:
import
會被打包成/* harmony import */
做字首,表明這段是import
進來的export
會被打包成/* harmony export */
做字首,表明這段是export
的- 純函式,會被打包成
/*#__PURE__*/
,表明這個函式是純函式,可以被tree shaking
掉
程式碼如下:
package.json
"name": "webpack-demo8",
"sideEffects":false,
webpack.config.js
optimization:{
usedExports:true
}
*** 以上程式碼在webpack-demo8
中
我的倉庫地址,github,歡迎star~~
(完)