神奇的HMR

作者: snow_in | 来源:发表于2018-12-05 19:33 被阅读0次

    模块热替换(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就可以运行了。

    相关文章

      网友评论

        本文标题:神奇的HMR

        本文链接:https://www.haomeiwen.com/subject/tyowcqtx.html