带热模块更换的Vue.js懒惰加载路由(HMR)

时间:2018-01-10 11:43:16

标签: webpack asp.net-core vue.js vue-router hot-module-replacement

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

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;

2 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:0)

您需要将这两个插件添加到“dev”*插件中+使用devServer设置"hot" = true选项或在运行webpack命令时使用--hot参数。

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

为什么选择NamedModulesPlugin?

  

NamedModulesPlugin,以便更容易查看哪些依赖项

     

正在修补

更多信息:

  

* HMR不适用于生产,这意味着它只能用于>开发中。有关详细信息,请参阅建筑物中的生产指南。