Express 结合 WebPack 实现 Vue项目热更新

先说一下写这篇博客的背景,以及如标题所说 Express 结合 WebPack 实现 Vue项目热更新 的应用场景在哪?

背景和应用场景

之前在阅读 vuex 源码时,看到 examples 目录下都是对 vuex 的使用示例demo,其实现方式就如这边文章所述,当然,这边文档都是参考 vuex/examples 中的代码。

这里还主要用到两个 Express 中间件。

  • webpack-dev-middleware

是 WebPack 的一个中间件。它用于在 Express 中分发需要通过 WebPack 编译的文件。单独使用它也可以完成代码的热重载功能。

  • webpack-hot-middleware

原理是通过订阅 WebPack 的编译更新,之后通过执行 WebPack 的 HMR api 将这些代码模块的更新重新推送给浏览器端。

基本思路

具体实现

WebPack 基础配置

结合 vuex 的项目来说, 在 Vue 中提供一些具体示例,需要使用单文件组件和更高级的语法。所以配置一份可以将这些文件都打包成 HTMLCSSJs 文件模块的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 目录下不止有一个示例,每个示例都会单独创建一个文件夹,并且每个文件夹下都提供一个 入口文件。即可打包成多页面应用。

Express 结合 WebPack 实现 Vue项目热更新_第1张图片

最基本的 WebPack 配置好了之后,接下来由 WebPack 这个模块函数进行编译,生成一个编译器对象。

server.js

结合最上面的 基本思路图 会让我们很清晰。

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-middlewarewebpack-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 多页面应用。

Express 结合 WebPack 实现 Vue项目热更新_第2张图片

后记

这篇博客为个人总结篇,具体代码请查看 vuexweb-model 项目,这两个项目中的 examples 都是基于这样的技术组合实现。

  • vuex
  • web-model

你可能感兴趣的:(vue系列)