html文件如何也同步到dist目錄?bundle.js文件修改了,萬一被瀏覽器緩存了怎么辦?如何為導出的文件加md5?如何把js引用自動添加到html?非業務代碼和業務代碼如何分開打包?如何搭建開發環境?如何實現開發環境的熱更新?
(1)安裝html-webpack-plugin:
npm install --save-dev html-webpack-plugin
(2)在webpack.prod.conf.js中配置plugins屬性。
const merge = require('webpack-merge'); const baseWebpackConfig = require('./webpack.base.conf.js'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = merge(baseWebpackConfig, { mode: 'production', plugins: [ new HtmlWebpackPlugin({ template: 'public/index.html', inject: 'body', minify: { removeComments: true, collapseWhitespace: true, removeAttributeQuotes: true }, }) ] });
(3)刪除index.html中手動引入的script標簽
index.html的代碼應該是這樣的:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>從零開始搭建react工程</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
(4)重新執行編譯
npm run build
查看dist文件夾,index.html也被加載進來了,並且已經自動加上了script標簽。
添加文件hash的方法很簡單,只要修改 output.filename 屬性即可,這里我們做一個小小的優化,把導出的文件存放在js目錄下,並且直接使用name+chunkhash的方式來命名。
filename: "js/[name].[chunkhash:16].js"
其中,name就是模塊名稱,我們在entry中進行過配置,chunkhash是文件內容的hash,webpack默認采用md5的方式對文件進行hash。16是hash的長度,如果不設置,webpack會設置默認值為20。
現在,你的webpack.prod.conf.js文件看起來應該是這樣:
const merge = require('webpack-merge'); const baseWebpackConfig = require('./webpack.base.conf.js'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = merge(baseWebpackConfig, { mode: 'production', output: { filename: "js/[name].[chunkhash:16].js", }, plugins: [ new HtmlWebpackPlugin({ template: 'public/index.html', inject: 'body', minify: { removeComments: true, collapseWhitespace: true, removeAttributeQuotes: true }, }) ] });
(1)安裝clean-webpack-plugin
npm install --save-dev clean-webpack-plugin
(2)修改webpack.prod.conf.js,使用clean-webpack-plugin
const merge = require('webpack-merge'); const baseWebpackConfig = require('./webpack.base.js'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin'); module.exports = merge(baseWebpackConfig, { mode: 'production', output: { filename: "js/[name].[chunkhash:16].js", }, plugins: [ new HtmlWebpackPlugin({ template: 'public/index.html', inject: 'body', minify: { removeComments: true, collapseWhitespace: true, removeAttributeQuotes: true }, }), new CleanWebpackPlugin(['../dist'], { allowExternal: true }) ] });
(3)執行試試看
npm run build
編譯過程,注意查看控制台輸出,你會發現webpack刪除了dist目錄。
隨着我們業務代碼的增加,這個包將會越來越大。
你每次發布,這個文件都會被重新下載。你的代碼有修改,用戶需要重新下載無可厚非。可是,你別忘了這個app.js內還包含了很多不變的代碼,比如react,react-dom。我們需要把這些不變的代碼分開打包。
在webpack.base.conf.js,我們添加一個入口配置。entry有2個入口。
entry: { app: './app/index.js', framework:['react','react-dom'], },
重新執行npm run build,再看看。
的確,react和react-dom 被編譯成framework.js。可是,你會發現,app.js並沒有減少,還是96.9KB。因為我們還缺少一步,就是抽離app.js中公共的代碼。
webpack3版本是通過配置CommonsChunkPlugin插件來抽離公共的模塊。webpack4版本,官方廢棄了CommonsChunkPlugin,而是改用配置optimization.splitChunks的方式,更加方便。
在webpack.prod.conf.js增加如下代碼:
optimization: { splitChunks: { chunks: "all", minChunks: 1, minSize: 0, cacheGroups: { framework: { test: "framework", name: "framework", enforce: true } } } }
cacheGroups對象,定義了需要被抽離的模塊,其中test屬性是比較關鍵的一個值,他可以是一個字符串,也可以是正則表達式,還可以是函數。如果定義的是字符串,會匹配入口模塊名稱,會從其他模塊中把包含這個模塊的抽離出來。name是抽離后生成的名字,和入口文件模塊名稱相同,這樣抽離出來的新生成的framework模塊會覆蓋被抽離的framework模塊,雖然他們都叫framework。
重新執行npm run build你看到app.js的體積變小了 才1kb。

注意查看生成的文件的hash,接下去我們隨意修改app/index.js的代碼。重新執行npm run build編譯。看看編譯后的結果:

看到了嗎,app的hash發生了改變(它不能被瀏覽器緩存),而framework沒有改變(它會被瀏覽器緩存),這達到了我們預期的結果。
(1)安裝uglifyjs-webpack-plugin
npm install --save-dev uglifyjs-webpack-plugin
(2)在webpack.prod.conf.js頁面上引入
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
(3)optimization內配置minimizer參數
minimizer: [ new UglifyJSPlugin() ],
你的optimization參數現在應該是這樣:
optimization: { minimizer: [ new UglifyJSPlugin() ], splitChunks: { chunks: "all", minChunks: 1, cacheGroups: { framework: { priority: 200, test: "framework", name: "framework", enforce: true, reuseExistingChunk: true }, vendor: { priority: 10, test: /node_modules/, name: "vendor", enforce: true, reuseExistingChunk: true } } } }
(4)重新執行npm run build
npm run build
webpack-dev-server這個模塊提供了開發服務的支持,通過在webpack.dev.conf.js文件配置devServer可以方便地整合webpack-dev-server。
(1)安裝webpack-dev-server
npm install --save-dev webpack-dev-server
(2)在build中添加webpack.dev.conf.js文件
const path = require('path'); const merge = require('webpack-merge'); const baseWebpackConfig = require('./webpack.base.conf.js'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const webpack = require('webpack'); module.exports = merge(baseWebpackConfig, { mode: 'development', output: { filename: "js/[name].[hash:16].js", }, plugins: [ new HtmlWebpackPlugin({ template: 'public/index.html', inject: 'body', minify: { html5: true }, hash: false }), new webpack.HotModuleReplacementPlugin() ], devServer: { port: '8080', contentBase: path.join(__dirname, '../public'), compress: true, historyApiFallback: true, hot: true, https: false, noInfo: true, open: true, proxy: {} } });
HotModuleReplacementPlugin是webpack熱更新的插件,設置devServer.hot為true,並且在plugins中引入HotModuleReplacementPlugin插件即可。
還需要注意的是我們開啟了hot,那么導出不能使用chunkhash,需要替換為hash。
(3)在package.json增加一個npm scripts
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
(4)執行dev命令
npm run dev
打開 http://localhost:8080 查看,你可以嘗試改動index.js的代碼,瀏覽器自動更新了,說明整合webpack-dev-server成功。
你可能注意到,對於css相關的技術棧,我只字未提,別急,下一節我們會詳細針對css相關的技術棧進行整合。
