聲明:所有的文章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~~
(完)