项目中需要搭建一个多页面的环境,包括本地路由服务和分页面打包。本节介绍开发部署时,实现热加载和页面刷新。

# webpack 插件

# Express 和 Webpack

Express本质是一系列middleware的集合,因此,适合Expresswebpack开发工具是webpack-dev-middlewarewebpack-hot-middleware。 详细例子说明也可参考《Express 结合 Webpack 的全栈自动刷新》 (opens new window)

# webpack-dev-middleware (opens new window)

webpack-dev-middleware是一个处理静态资源的middleware

有时候我们无需使用到Express,我们常常使用webpack-dev-server开启动服务。 webpack-dev-server实际上是一个小型Express服务器,它也是用webpack-dev-middleware来处理webpack编译后的输出。

# webpack-hot-middleware (opens new window)

webpack-hot-middleware是一个结合webpack-dev-middleware使用的middleware,它可以实现浏览器的无刷新更新(hot reload)。 这也是webpack文档里常说的 HMR(Hot Module Replacement)。

# 实现热加载和页面刷新

其实如果将热加载定义为文件变动时重新编译的话,其实我们上一节已经完成了。 但热加载的功能,不搭配页面自动刷新的话,其实就不完整了呢。

需要调整三个地方:

  1. 每个页面入口需要添加webpack-hot-middleware/client?reload=true
  2. 在 webpack 配置中添加 plugin 插件new webpack.HotModuleReplacementPlugin()
  3. Express实例中添加中间件'webpack-hot-middleware'

故我们的代码为:

// build/dev-server.js
// dev-server.js
var path = require("path");
var express = require("express");
var utils = require("./utils");
var webpack = require("webpack");
var webpackConfig = require("./webpack.config");
var HtmlWebpackPlugin = require("html-webpack-plugin");
var WebpackDevMiddleware = require("webpack-dev-middleware");
var WebpackHotMiddleware = require("webpack-hot-middleware");

// Express实例
var app = express();

// 获取页面目录
var entries = utils.entries;
// entry中添加HotUpdate地址
var hotMiddlewareScript = "webpack-hot-middleware/client?reload=true";

// 重置入口entry
webpackConfig.entry = {};
// 设置output为每个页面[name].js
webpackConfig.output.filename = "[name].js";
webpackConfig.output.path = path.join(__dirname, "dist");

Object.keys(entries).forEach(function(name) {
  // 每个页面生成一个entry
  // 这里修改entry实现HotUpdate
  webpackConfig.entry[name] = [entries[name], hotMiddlewareScript];

  // 每个页面生成一个[name].html
  var plugin = new HtmlWebpackPlugin({
    // 生成出来的html文件名
    filename: name + ".html",
    // 每个html的模版,这里多个页面使用同一个模版
    template: "./index.html",
    // 自动将引用插入html
    inject: true,
    // 每个html引用的js模块,也可以在这里加上vendor等公用模块
    chunks: [name]
  });
  webpackConfig.plugins.push(plugin);
});

webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());

// webpack编译器
var compiler = webpack(webpackConfig);

// webpack-dev-server中间件
app.use(
  WebpackDevMiddleware(compiler, {
    publicPath: "/",
    stats: {
      colors: true,
      chunks: false
    },
    progress: true,
    inline: true,
    hot: true
  })
);

app.use(WebpackHotMiddleware(compiler));

// 路由
app.get("/:pagename?", function(req, res, next) {
  var pagename = req.params.pagename
    ? req.params.pagename + ".html"
    : "index.html";

  var filepath = path.join(compiler.outputPath, pagename);

  // 使用webpack提供的outputFileSystem
  compiler.outputFileSystem.readFile(filepath, function(err, result) {
    if (err) {
      // something error
      return next(
        "输入路径无效,请输入目录名作为路径,有效路径有:\n/" +
          Object.keys(entries).join("\n/")
      );
    }
    // 发送获取到的页面
    res.set("content-type", "text/html");
    res.send(result);
    res.end();
  });
});

module.exports = app.listen(8080, function(err) {
  if (err) {
    // do something
    return;
  }

  console.log("Listening at http://localhost:8080\n");
});

这样,我们就实现了代码的热加载以及页面自动刷新了。

# 结束语

本节我们讲述了在 webpack 中添加代码热加载和页面自动刷新的功能,主要使用了webpack-dev-middlewarewebpack-hot-middleware两个插件工具。
可参考代码github-vue-multi-pages (opens new window),主要是这套环境使用在 vue 上的 demo。

部分文章中使用了一些网站的截图,如果涉及侵权,请告诉我删一下谢谢~
温馨提示喵