Identifying memory leak in webpack build

Viewed 3561

I was wondering if someone could point me in the right direction here.

When I run my development server, and some times even the production server the build crashes sporadically saying the javascript heap is out of memory. I've tried attaching a debugger to webpack and as far as I can see it fails on parsing the less-files, but I've also seen it happen running at different stages as well.

I have absolutely no clue how to proceed in fixing this issue, but something tells me I have to fix the issue, as compared to the standard "just increase node's --max-old-space-size". I've already doubled the heap space twice and still experience the error some times. At the moment I've set it to use 8gb of ram, but it still fails.

I've attached a screenshot of debugger from when the debugger halted on a potential out of memory crash. As you probably guessed, I am fairly new to Webpack and would appreciate any hint on how I can get to the root of this problem as it is really impacting my workflow.

webpack.config.js

// Path to the output folder
const rootFolder = "wwwroot";
const bundleFolder = `${rootFolder}/bundle`;

const customers = [
    // ### Removed
];

let entry = {
  load: "./ClientApp/load.ts",
  main: "./ClientApp/main.ts",
};
customers.forEach((e) => {
  entry[e] = `./ClientApp/www_files/${e}/${e}.ts`;
});

module.exports = (env, args) => {
  const devMode = args.mode !== "production";

  return {
    entry: entry,
    output: {
      path: path.resolve(__dirname, bundleFolder),
      publicPath: " ### Removed",
      filename: "[name].js",
      chunkFilename: "[id].[name].[chunkhash].js",
    },
    module: {
      rules: [
        {
          test: /\.vue$/,
          loader: "vue-loader",
        },
        {
          test: /\.js$/,
          loader: "babel-loader",
          query: {
            presets: ["es2015"],
            compact: devMode,
          },
        },
        {
          test: /\.ts?$/,
          use: [
            {
              loader: "awesome-typescript-loader",
            },
          ],
        },
        {
          test: /\.css$/,
          use: [
            devMode ? "vue-style-loader" : MiniCssExtractPlugin.loader,
            "css-loader",
          ],
        },
        {
          test: /\.scss$/,
          use: [
            devMode ? "vue-style-loader" : MiniCssExtractPlugin.loader,
            "css-loader",
            "sass-loader",
          ],
        },
        {
          test: /\.less$/,
          use: [
            devMode ? "vue-style-loader" : MiniCssExtractPlugin.loader,
            "css-loader",
            "less-loader",
          ],
        },
        {
          test: /\.(png|jpg|gif|svg)$/,
          loader: "file-loader",
          options: {
            name: "[name].[ext]?[hash]",
          },
        },
        {
          test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
          loader: "file-loader",
        },
        {
          test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
          loader: "file-loader",
        },
        {
          test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
          loader: "file-loader",
        },
        {
          test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
          loader: "file-loader",
        },
        {
          test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
          loader: "file-loader",
        },
        {
          test: /\.(html)$/,
          use: {
            loader: "html-loader",
            options: {
              attrs: [":data-src"],
            },
          },
        },
        {
          resourceQuery: /blockType=i18n/,
          type: "javascript/auto",
          loader: "@kazupon/vue-i18n-loader",
        },
      ],
    },
    resolve: {
      extensions: [".ts", ".js", ".vue", ".json"],
      alias: {
        vue$: "vue/dist/vue.esm.js",
      },
    },
    devServer: {
      contentBase: bundleFolder,
      // Added because of bug: https://github.com/webpack/webpack-dev-server/issues/1604
      disableHostCheck: true,
      hot: true,
      overlay: true,
      headers: {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Methods":
          "GET, POST, PUT, DELETE, PATCH, OPTIONS",
        "Access-Control-Allow-Headers":
          "X-Requested-With, content-type, Authorization",
      },
      port: 8080,
    },
    optimization: {
      minimizer: [
        new TerserPlugin(),
        new OptimizeCssAssetsPlugin({}),
      ],
    },
    plugins: [
      new CleanWebpackPlugin([bundleFolder]),
      new webpack.HotModuleReplacementPlugin(),
      new VueLoaderPlugin(),
      new CheckerPlugin(),
      new MiniCssExtractPlugin({
        filename: "[name].css",
        chunkFilename: "[id].[name].[chunkhash].css",
      }),
      new HardSourceWebpackPlugin(),
      new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
    ],
  };
};
1 Answers

I experience the same issue, although my setup is a bit different.

While I'm not sure how you could exactly debug it, a part of commenting out some not critical parts and see if it's going any better.

What you could try to do is:

  1. If it's not the build for production skip the optimizations you've there in the optimization object.
  2. I assume that your project is quite big, you might want to consider migrating to Vite: https://vitejs.dev/ Vite is supposed to scale very nicely without even adding more time to your build since there's no bundling.

While it might be nice to cut down some resources or time with Webpack, I think it'll be much better to migrate to Vite, the Developer experience would improve a lot, and you could save a lot of time. We're going to do the same in the short term future.

Good luck :-)

Related