神奇的HMR
2018-12-05 本文已影响0人
snow_in
模块热替换(Hot Module Replacement 简称HMR),就是当对代码做了修改并保存后,修改结果会直接反应在应用中而不用刷新浏览器。这个过程包括了两个步骤,一是保存后webpack重新打包;二是浏览器进行新老模块的替换,将新的结果反应在浏览器上。
两个过程对应着两个webpack插件的使用:webpack-dev-middleware和 webpack-hot-middleware,我们就来看一下如何利用这两个插件实现HMR。
假设已经创建了webpack.dev.conf.js配置文件.
build/setup-dev-server.js:
const path = require('path');
const webpack = require('webpack');
const webpackConfig = require('./webpack.dev.conf');
const DevMiddleware = require('webpack-dev-middleware');
const hotMiddleware = require('webpack-hot-middleware');
module.exports = function setupDevServer (app, opts) {
webpackConfig.entry.app = ['webpack-hot-middleware/client', webpackConfig.entry.app]; // 入口文件添加'webpack-hot-middleware/client',服务端能够和客户端通信的关键
webpackConfig.output.filename = '[name].js';
webpackConfig.plugins.push(
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
);
const compiler = webpack(webpackConfig); // 以webpack.dev.conf.js文件为基础,创建一个用来传给webpack-dev-middleware的对象
const devMiddleware = DevMiddleware(compiler, {
publicPath: webpackConfig.output.publicPath, // 必传参数,和webpack.dev.conf.js文件里面的publicPath一致
stats: { colors: true, chunks: false }
});
app.use(devMiddleware); // 添加中间件,告诉express使用webpack-dev-middleware插件
compiler.plugin('done', () => { // 钩子函数被调用时客户端检查模块更新
const fs = devMiddleware.fileSystem;
const filePath = path.join(webpackConfig.output.path, 'index.html');
if (fs.existsSync(filePath)) {
const template = fs.readFileSync(filePath, 'utf-8');
opts.templateUpdated(template);
}
});
app.use(hotMiddleware(compiler));
}
server.js:
const express = require('express');
const app = express();
const noDevelop = process.env.NODE_ENV !== 'develop';
const resolve = file => path.resolve(__dirname, file);
let tempHTML;
//...其他代码
if (!noDevelop) {
const setupDevServer = require('./build/setup-dev-server');
setupDevServer(app, {
templateUpdated: (template) => {
tempHTML = template;
}
});
} else {
tempHTML = fs.readFileSync(resolve('./dist/index.html'));
}
app.get('*', (req, res, next) => {
res.end(tempHTML);
next();
})
app.listen('7777', function () {
});
然后在package.json的scripts添加一条命令:
"dev": "cross-env NODE_ENV=develop node server.js"
执行npm run dev就可以运行了。