模块热替换 (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 就可以运行了.
来源: http://www.jianshu.com/p/fa4e9bef0681