写在前面
- 使用webpack-dev-server
- 开启很简单,但是会有程序书写错误,导致热替换失败
一.基本使用HMR(hot module replacement)
1.webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');
module.exports = {
entry: {
app: './src/index.js',
// 去掉print.js,因为此时此文件正在被index.js使用
// print: './src/print.js'
},
// 使用source map,用于定位错误代码
devtool: 'inline-source-map',
// 使用webpack-dev-server
devServer: {
contentBase: './dist',
// 设置热加载
hot: true
},
// 使用插件
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'OutPut Management'
}),
// 另外需要使用webpack的两个插件
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin()
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/'
}
}
2.index.js
import _ from 'lodash';
/*import './style.css'; // 应该使用相对路径,否则不能找到模块
import loginImg from './login.jpg';
import Data from './data.xml';*/
import printMe from './print.js';
function component(){
var element = document.createElement('div');
element.innerHTML = _.join(['你好','申玉超'],'');
/*element.classList.add('hello');
var img = new Image();
img.src = loginImg;
element.appendChild(img);
console.log(Data);*/
var btn = document.createElement('button');
btn.innerHTML = 'Click me and check the console!';
btn.onclick = printMe;
element.appendChild(btn);
return element;
}
let element = component();
document.body.appendChild(element);
// 热加载
if(module.hot){
module.hot.accept('./print.js',function () {
console.log('Accepting the updated printMe module!');
// printMe();
document.body.removeChild(element);
element = component();
document.body.appendChild(element);
});
}
3.运行 npm start,可以观察热替换和热加载,但是会发现修改了print.js的console的内容,在控制台并不会被打印出来,打印的还是原来的内容,这不是webpack-dev-server的问题,而是程序写的问题.
二.使用Node.js API热加载
1.新增dev-server.js
const webpackDevServer = require('webpack-dev-server');
const webpack = require('webpack');
const config = require('./webpack.config.js');
const options = {
contentPath: './dist',
hot: true,
host: 'localhost'
}
// webpackDevServer自己的addDevServerEntrypoints方法,有些许类似express的使用
webpackDevServer.addDevServerEntrypoints(config,options);
const compiler = webpack(config);
const server = new webpackDevServer(compiler,options);
server.listen(5000,'localhost',function () {
console.log('dev server listening on port 5000');
});
2.package.js
{
"name": "webpack-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"watch": "webpack --watch",
"start": "webpack-dev-server --open",
// 使用Node.js API启动热加载和热替换
"server":"node server.js",
"build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"clean-webpack-plugin": "^0.1.18",
"css-loader": "^0.28.9",
"csv-loader": "^2.1.1",
"express": "^4.16.2",
"file-loader": "^1.1.6",
"html-webpack-plugin": "^2.30.1",
"style-loader": "^0.20.1",
"webpack": "^3.10.0",
"webpack-dev-middleware": "^2.0.4",
"webpack-dev-server": "^2.11.1",
"xml-loader": "^1.2.1"
},
"dependencies": {
"lodash": "^4.17.5"
}
}
3.运行 npm run server即可,同样的,也会出现上述的问题,程序需要做修改
4.修改程序
import _ from 'lodash';
/*import './style.css'; // 应该使用相对路径,否则不能找到模块
import loginImg from './login.jpg';
import Data from './data.xml';*/
import printMe from './print.js';
function component(){
var element = document.createElement('div');
element.innerHTML = _.join(['你好','申玉超'],'');
/*element.classList.add('hello');
var img = new Image();
img.src = loginImg;
element.appendChild(img);
console.log(Data);*/
var btn = document.createElement('button');
btn.innerHTML = 'Click me and check the console!';
btn.onclick = printMe;
element.appendChild(btn);
return element;
}
/**
出现问题的原因是之前document.body.appendChild(component())中,printMe作为一个函数,已经被绑定到了btn上,热替换后,并没有吧这个已经绑定的事件改掉,so,出现问题
解决:可以使用如下方式解决:
*/
let element = component();
document.body.appendChild(element);
if(module.hot){
module.hot.accept('./print.js',function () {
console.log('Accepting the updated printMe module!');
// printMe();
document.body.removeChild(element);
element = component();
document.body.appendChild(element);
});
}