Webpack4.x出來也有一段時間了,網上已經有很多關於Webpack4.x原理和新特性的介紹,比如零配置等,這邊就不重複了。
最近將之前基於Webpack3.x寫的一個多頁面專案升級到4.x,記錄和總結Webpack3.x升級到4.x遇到的問題以及解決方案。
專案預覽gif:
線上檢視: webpack.czero.cn區分3.x和4.x不同之外,也對Webpack進行了構建優化,並分別配置了Webpack3.x和Webpack4.x的基礎配置檔案託管在Github,可以用在專案中,減少配置的時間。
Webpack3.x:github.com/czero1995/w…
Webpack4.x:github.com/czero1995/w…
專案中Webpack實現功能:
- 多頁面入口配置
- 使用Ejs模板實現元件化功能(共用頭部和底部)
- 提取公共CSS檔案
- 使用HappyPack做多執行緒打包
- 引入最新Babel編譯,可編譯ES7,ES8(裝飾圈@等)
- devServer,儲存自動重新整理
- 引入Less處理器
- 配置TypeScript
- 每次Build都先刪除掉原先Build出來的檔案
區分開發環境和生產環境
開發環境: npm run dev
生產環境: npm run build
複製程式碼
區分開發環境可以提高Webpack打包效率,比如
-
開發環境中:
配置除錯模式devtool:cheap-source-map
配置devServer:儲存自動重新整理
-
生產環境:
配置除錯模式devtool:inline-source-map
載入提取CSS元件
載入PostCss外掛(瀏覽器字首,提高相容性)
新增每次Build時先刪除之前Build的檔案
壓縮程式碼
清空程式碼註釋和空格
載入PostCss外掛
Webpack3.x和Webpack4.x的幾個明顯的區別和問題
1. 執行webpack要加引數
從4.0開始:執行webpack一定要加引數
-- mode development 或者 --mode production,
分別對應開發環境和生產環境,否則會報警告:
3.x (package.json)
"scripts": {
"build": "webpack --optimize-minimize",
"dev": "webpack-dev-server --config webpack.dev.config.js"
},
複製程式碼
4.x (package.json)
"scripts": {
"build": "webpack --optimize-minimize --mode production",
"dev": "webpack-dev-server --config webpack.dev.config.js --mode development"
},
複製程式碼
2. 移除loaders,必須使用rules
在Webpack3.x中還保留之前版本的loaders,與rules並存都可以使用,在新版中完全移除了loaders,必須使用rules。否則會報錯,將module下面的loaders改為rules即可
3. 需要安裝webpack-cli
4.x需要安裝webpack-cli,不然執行不起來
npm install webpack-cli --save
複製程式碼
4. TypeScript ts-loader版本太低
在webpack3.x中typescript使用正常,升級到webpack4.x之後就用不了typescript了,因為版本太低 修改typescript版本,我的事5.2.2,在package.json中修改ts-loader版本號,或者刪掉,重新執行 npm install ts-loader即可
5. Ejs無法使用
Webpack結合Ejs可以做到元件化開發,共用HTML程式碼,比如多個頁面的頭部和底部,用元件引入的方式,方面後面的開發和維護。
3.x中正常使用,4.x會報ejsRenderLoder of undefined,需要修改htmlplugin的配置。 3.x為:
template: 'ejs-render-loader!pages/index.ejs',
複製程式碼
4.x為
template: 'ejs-loader!pages/index.ejs',
複製程式碼
5. text-webpack-plugin版本太低,構建失敗
在package.json中修改extract-text-webpack-plugin版本號
"extract-text-webpack-plugin": "^v4.0.0-alpha.0",
複製程式碼
Webpack構建優化
區分開發環境和生產環境
- 開發環境不需要去壓縮程式碼
- 指定除錯模式devtool模式
壓縮程式碼用ParalleUglifyPlugin代替自帶的UglifyJsPlugin外掛
自帶的js壓縮外掛是單執行緒執行的,而webpack-parallel-uglify-plugin可以並行的執行 開發環境不做無意義的操作
很多配置,在開發階段是不需要去做的,我們可以區分出開發和線上的兩套配置,這樣在需要上線的時候再全量編譯即可,比如程式碼壓縮,目錄內容清理,計算檔案hash,提取css檔案等
babel-loader開啟快取
babel-loader在執行的時候,可能會產生一些執行期間重複的公共檔案,造成程式碼體積大多餘,同時也會減慢編譯效率
可以加上cacheDirectory引數或使用transform-runtime外掛試試
// webpack.config.js
use: [{
loader: 'babel-loader',
options: {
cacheDirectory: true
}]
// .bablerc
{
"presets": [
"env",
"react"
],
"plugins": ["transform-runtime"]
}
複製程式碼
使用happypack來加速構建
happypack會採用多程式去打包構建
複製程式碼
優化構建時的搜尋路徑alias
使用noParse
webpack打包的時候,有時不需要解析某些模組的載入(這些模組並沒有依賴,或者並根本沒有模組化),我們可以直接加上這個引數,直接跳過這種解析
module:{
noParse: /node_modules\/(jquery.js)
}
複製程式碼
啟用DllPlugin和DllReferencePlugin預編譯庫檔案
這是最複雜也是提升效果最明顯的一步,原理是將第三方庫檔案單獨打包一次,以後的編譯都不需要在編譯打包第三方庫
拷貝靜態資原始檔,引入DllPlugin和DllReferencePlugin來提前構建一些第三方庫,來優化Webpack阿寶。
而在生產環境時,就需要將提前構建好的包同步到dist中
對於commonChunkPlugin,webpack每次打包實際還是需要去處理這些第三方庫,只是打包完之後,能把第三方庫和我們自己的程式碼分開。 而DllPlugin則是能把第三方程式碼完全分離開,即每次只打包專案自身的程式碼。 在build/資料夾下新建webpack.dll.config.js檔案,複製一下程式碼:
const path = require("path")
const webpack = require("webpack")
module.exports = {
// 你想要打包的模組的陣列
entry: {
vendor: ['vue/dist/vue.esm.js', 'axios', 'vue-router', 'vuex']
},
output: {
path: path.join(__dirname, '../static/js'), // 打包後檔案輸出的位置
filename: '[name].dll.js',
library: '[name]_library'
},
plugins: [
new webpack.DllPlugin({
path: path.join(__dirname, '.', '[name]-manifest.json'),
name: '[name]_library',
context: __dirname
}),
// 壓縮打包的檔案
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
]
}
複製程式碼
在build/webpack.dev.config.js和build/webpack.prod.config.js中新增plugins
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./vendor-manifest.json')
}),
複製程式碼
在根目錄下的index.html下引入預編譯的庫
<script src="./static/js/vendor.dll.js"></script>
複製程式碼
在package.json/scripts下中新增dll命令
"dll": "webpack --config ./build/webpack.dll.config.js"
複製程式碼
執行:
npm run dll
複製程式碼
然後再
npm run dev或npm run build
複製程式碼
提取公共程式碼 使用CommonsChunkplugin提取公共的模組,可以減少檔案體積,也有助於瀏覽器層的檔案快取
npm run dll
npm run dev 或npm run build
複製程式碼