项目中需要搭建一个多页面的环境,包括本地路由服务和分页面打包。本节介绍开发部署时,实现热加载和页面刷新。
# webpack 插件
# Express 和 Webpack
Express
本质是一系列middleware
的集合,因此,适合Express
的webpack
开发工具是webpack-dev-middleware
和webpack-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)。
# 实现热加载和页面刷新
其实如果将热加载定义为文件变动时重新编译的话,其实我们上一节已经完成了。 但热加载的功能,不搭配页面自动刷新的话,其实就不完整了呢。
需要调整三个地方:
- 每个页面入口需要添加
webpack-hot-middleware/client?reload=true
。 - 在 webpack 配置中添加 plugin 插件
new webpack.HotModuleReplacementPlugin()
。 - 在
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-middleware
和webpack-hot-middleware
两个插件工具。
可参考代码github-vue-multi-pages (opens new window),主要是这套环境使用在 vue 上的 demo。