Vue.js 具有热模块替换 (HMR) 的延迟加载路由

Vue.js Lazy Loaded Routes with Hot Module Replacement (HMR)

我正在尝试 lazily load 我的 Vue.js 路由使用 vue-router 和 Webpack 动态 import 语句,如下所示:

const routes = [
  {
    component: () => import("./components/home.vue"),
    name: "home",
    path: "/",
  },
  {
    component: () => import("./components/child.vue"),
    name: "child",
    path: "/child",
  }
};

这正确地导致 Webpack 按路径拆分我的 JavaScript 包,我最终得到 main.js 和一系列 0.js1.js 文件。我还注意到 Chrome 开发工具中要求这些。

但是,我似乎无法让它与热模块更换 (HMR) 一起使用。我在服务器端使用 ASP.NET Core。当我的页面加载时,我只看到一个空白页面。将 Vuex 与 HMR 一起使用时,我必须遵循 this 文档才能重新加载 Vuex 存储。对于延迟加载的路线,我需要做类似的事情吗?如果有帮助,这是我的 webpack.config.js 文件:

import * as BrotliPlugin from "brotli-webpack-plugin";
import * as CompressionPlugin from "compression-webpack-plugin";
import * as ExtractTextPlugin from "extract-text-webpack-plugin";
import * as ForkTsCheckerWebpackPlugin from "fork-ts-checker-webpack-plugin";
import * as path from "path";
import * as StyleLintPlugin from "stylelint-webpack-plugin";
import * as SpriteLoaderPlugin from "svg-sprite-loader/plugin";
import * as webpack from "webpack";
import { BundleAnalyzerPlugin } from "webpack-bundle-analyzer";

const configurationBuilder = (env) => {
  const isDevBuild = !(env && env.prod);

  const cssDirectoryName = "css";
  const jsDirectoryName = "js";

  const wwwRootDirectory = "./wwwroot";
  const jsDirectory = `./wwwroot/${jsDirectoryName}`;

  const configuration = {
    stats: { modules: false },
    context: __dirname,
    resolve: {
      extensions: [".js", ".ts", ".vue"],
      alias: {
        vue$: "vue/dist/vue.common.js",
      },
    },
    entry: { main: "./ClientApp/Boot.ts" },
    module: {
      rules: [
        {
          test: /\.vue$/,
          include: /ClientApp/,
          loader: "vue-loader",
          options: {
            preserveWhitespace: isDevBuild, // Ignore white space in HTML
          },
        },
        {
          test: /\.ts$/,
          include: /ClientApp/,
          loader: "ts-loader",
          options: {
            appendTsSuffixTo: [/\.vue$/],
            silent: true,
            transpileOnly: true,
          },
        },
        {
          test: /\.scss$/,
          use: isDevBuild ? getSassLoaders() : ExtractTextPlugin.extract({ use: getSassLoaders() }),
        },
        {
          test: /\.svg$/,
          oneOf: [
            {
              resourceQuery: /inline/,
              use: getSvgUrlLoaders(),
            },
            {
              use: getSvgSpriteLoaders(),
            },
          ],
        },
        {
          test: /\.(png|jpg|jpeg|gif)$/,
          loader: "url-loader",
          options: {
            limit: 25000,
          },
        },
      ],
    },
    output: {
      path: path.join(__dirname, wwwRootDirectory),
      filename: "js/[name].js",
      chunkFilename: "js/[name].js",
      publicPath: `${jsDirectoryName}/`, // Needs a trailing slash for hot module replacement to work
    },
    plugins: [
      new ForkTsCheckerWebpackPlugin({
        tslint: true,
        vue: true,
      }),
      new webpack.DefinePlugin({
        "process.env": {
          NODE_ENV: JSON.stringify(isDevBuild ? "development" : "production"),
        },
      }),
      new StyleLintPlugin({
        configFile: ".stylelintrc.json",
        files: ["ClientApp/css/**/*.scss"],
      }),
      new SpriteLoaderPlugin(),
      new webpack.DllReferencePlugin({
        context: __dirname,
        manifest: require(`${jsDirectory}/vendor-manifest.json`),
      }),
    ].concat(isDevBuild ? [
      new webpack.SourceMapDevToolPlugin({
        filename: "[file].map",
        moduleFilenameTemplate: path.relative(jsDirectory, "[resourcePath]"),
      }),
    ] : [
        // Plugins that apply in production builds only
        new webpack.optimize.UglifyJsPlugin({
          comments: false,
        }),
        new ExtractTextPlugin(
          `${cssDirectoryName}/[name].css`),
        new CompressionPlugin({
          minRatio: 0.9,
          test: /\.(css|js|json|svg)$/,
        }),
        new BrotliPlugin({
          minRatio: 0.9,
          test: /\.(css|js|json|svg)$/,
        }),
        new BundleAnalyzerPlugin({
          analyzerMode: "static",
          openAnalyzer: false,
          reportFilename: "../bin/main-webpack-bundle-report.html",
        }),
      ]),
  };
  return configuration;
};

export default configurationBuilder;

您需要将这两个插件添加到您的 "dev"* 插件中 + 将 devServer 选项设置为 "hot" = true 或者在 [=41= 时使用 --hot 参数] 你的 webpack 命令。

new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(), 

为什么使用 NamedModulesPlugin?

NamedModulesPlugin to make it easier to see which dependencies are

being patched

更多信息:

* HMR is not intended for use in production, meaning it should only be used > in development. See the building for production guide for more information.

在您的导入中包含一个 webpack 指令,以指示该组件位于哪个块中。我正在做的正是这是一个大型项目,并且工作正常。

import(/* webpackMode: "lazy", webpackChunkName: "/js/modules" */ 'modules/users')

我在我的 webpack 配置中设置了别名,说我的块有有意义的名称而不是 0.js、1.js 等