webpack之HTML热更新

这是个小众场景,因为现在webpack大多是和react配合使用,react并不需要在html中添加过多内容,所以可能关注不是很多,我之前研究webpack,希望可以配合jQuery做基础的前端技术栈的打包,所以希望可以热更新HTML。

首先我们需要理解的是webpack所有文件皆是JS模块,我们在entry里定义了某些入口文件,通过webpack处理这些入口文件内部的依赖,最后打包到output里的目录中去。按照这个思路,我们可以把html文件也当成一个js模块,在js入口文件中引入,这样webpack的HRM就可以监听到这个html模块了,自然就可以做到热更新!

通过这个思路,我们需要一个转义html文件的插件:raw-loader

首先我们安装raw-loader

1
npm install --save-dev raw-loader

webpack配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// webpack.config.dev.js
var path = require('path')
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
devtool: 'cheap-eval-source-map',
entry: [
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/dev-server',
'./src/index'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html'
})
],
module: {
loaders: [{
test: /\.css$/,
loaders: ['style', 'css']
}, {
test: /\.html$/,
loader: "raw-loader" // loaders: ['raw-loader'] is also perfectly acceptable.
}]
},
devServer: {
contentBase: './dist',
hot: true
}
}

这样我们在入口文件引入html文件:

1
2
// index.js
require('./index.html')

现在就可以做到热更新了,但是我们还需要区分一下本地和生产环境,不然生产环境会把html打包进去。配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// webpack.config.prod.js
var path = require('path')
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
devtool: 'source-map',
entry: ['./src/index'],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
compressor: {
warnings: false,
},
}),
new webpack.optimize.OccurenceOrderPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
})
],
module: {
loaders: [{
test: /\.css$/,
loaders: ['style', 'css']
}]
}
}
1
2
3
4
//index.js
if (process.env.NODE_ENV !== 'production') {
require('./index.html')
}

参考:
https://github.com/AriaFallah/WebpackTutorial/tree/master/part1/html-reload