先说一下写这篇博客的背景,以及如标题所说 Express 结合 WebPack 实现 Vue项目热更新
的应用场景在哪?
之前在阅读 vuex
源码时,看到 examples
目录下都是对 vuex
的使用示例demo,其实现方式就如这边文章所述,当然,这边文档都是参考 vuex/examples
中的代码。
这里还主要用到两个 Express
中间件。
是 WebPack 的一个中间件。它用于在 Express 中分发需要通过 WebPack 编译的文件。单独使用它也可以完成代码的热重载功能。
原理是通过订阅 WebPack 的编译更新,之后通过执行 WebPack 的 HMR api 将这些代码模块的更新重新推送给浏览器端。
结合 vuex
的项目来说, 在 Vue
中提供一些具体示例,需要使用单文件组件和更高级的语法。所以配置一份可以将这些文件都打包成 HTML
、CSS
、Js
文件模块的WebPack
配置。
webpack.config.js
const fs = require("fs")
const path = require("path")
const webpack = require("webpack")
const VueLoaderPlugin = require("vue-loader/lib/plugin")
module.exports = {
mode: "development",
entry: fs.readdirSync(__dirname).reduce((entries, dir) => {
const fullDir = path.join(__dirname, dir)
const entry = path.join(fullDir, "app.js")
if (fs.statSync(fullDir).isDirectory() && fs.existsSync(entry)) {
console.log(dir);
entries[dir] = [entry, "webpack-hot-middleware/client"]
}
return entries
}, {}),
output: {
path: path.join(__dirname, "__build__"),
filename: "[name].js",
chunkFilename: "[id].chunk.js",
publicPath: "/__build__/"
},
module: {
rules: [
{ test: /\.js$/, exclude: /node_modules/, use: ["babel-loader"] },
{ test: /\.vue$/, use: ["vue-loader"] },
{ test: /\.css$/, use: ["vue-style-loader", "css-loader"] }
]
},
resolve: {
alias: {
"web-model": path.resolve(__dirname, "../src/Model.js")
},
},
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
name: "shared",
filename: "shared.js",
chunks: "initial"
}
}
}
},
plugins: [
new VueLoaderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new webpack.DefinePlugin({
__DEV__: JSON.stringify(true),
"process.env": {
NODE_ENV: JSON.stringify(process.env.NODE_ENV)
}
})
]
}
最主要的还是 entry
这个多入口配置。因为 examples 目录下不止有一个示例,每个示例都会单独创建一个文件夹,并且每个文件夹下都提供一个 入口文件
。即可打包成多页面应用。
最基本的 WebPack 配置好了之后,接下来由 WebPack 这个模块函数进行编译,生成一个编译器对象。
结合最上面的 基本思路图 会让我们很清晰。
const express = require("express")
const webpack = require("webpack")
const WebpackConfig = require("./webpack.config")
const app = express()
// compiler 实例
const compiler = webpack(WebpackConfig)
WebPack 可以作为函数调用,需要传入一个 WebPack 配置对象,如 webpack.config.js
导出的配置对象。会得到一个 WebPack 的 Compiler 实例。可以通过它手动触发 WebPack 执行器,或者是让它执行构建并监听变更。
接下来会将 Compiler 实例传递给 webpack-dev-middleware
和 webpack-hot-middleware
中间件。
注册 webpack-dev-middleware 中间件
app.use(require("webpack-dev-middleware")(compiler, {
publicPath: WebpackConfig.output.publicPath,
noInfo: true
}))
注册 webpack-hot-middleware中间件
app.use(require("webpack-hot-middleware")(compiler))
然后使用使用 express 内置中间件 static
,它提供静态文件,并且基于 serve-static。
app.use(express.static(__dirname))
const port = process.env.PORT || 8080
module.exports = app.listen(port, () => {
console.log(`Server listening on http://localhost:${port}, Ctrl+C to stop`)
})
并且使用 express 开启一个 8080
端口的服务器,访问 http://localhost:8080
即可访问 Vue
+ Vuex
多页面应用。
这篇博客为个人总结篇,具体代码请查看 vuex
或 web-model
项目,这两个项目中的 examples
都是基于这样的技术组合实现。