Webpack3.X升級到4.X多頁面實戰和構建優化

rickchen發表於2018-10-24

Webpack3.X升級到4.X多頁面實戰和構建優化

Webpack4.x出來也有一段時間了,網上已經有很多關於Webpack4.x原理和新特性的介紹,比如零配置等,這邊就不重複了。

最近將之前基於Webpack3.x寫的一個多頁面專案升級到4.x,記錄和總結Webpack3.x升級到4.x遇到的問題以及解決方案。

Webpack3.X升級到4.X多頁面實戰和構建優化

專案預覽gif:

Webpack3.X升級到4.X多頁面實戰和構建優化
線上檢視: 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,

分別對應開發環境和生產環境,否則會報警告:

Webpack3.X升級到4.X多頁面實戰和構建優化

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即可

Webpack3.X升級到4.X多頁面實戰和構建優化

3. 需要安裝webpack-cli

4.x需要安裝webpack-cli,不然執行不起來

npm install webpack-cli --save
複製程式碼

Webpack3.X升級到4.X多頁面實戰和構建優化

4. TypeScript ts-loader版本太低

在webpack3.x中typescript使用正常,升級到webpack4.x之後就用不了typescript了,因為版本太低 修改typescript版本,我的事5.2.2,在package.json中修改ts-loader版本號,或者刪掉,重新執行 npm install ts-loader即可

Webpack3.X升級到4.X多頁面實戰和構建優化

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',
複製程式碼

Webpack3.X升級到4.X多頁面實戰和構建優化

5. text-webpack-plugin版本太低,構建失敗

Webpack3.X升級到4.X多頁面實戰和構建優化

在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.jsbuild/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
複製程式碼

相關文章