Search code examples
reactjscode-splittingwebpack-5

Webpack 5 DependOn only works when the entry depends on only one dependency


To give you some context, I'm working on a .NET core app, and in one of the cshtml I'm injecting a react mini app like this:

<div id="workshop" data-id=@Model></div>

<script src="~/bundles/js/workshop-bundle.js"></script>

It was working well, but when I compile with webpack, the workshop bundle was too big (800kb) and I was receiving a warning. The workshop-bundle was including some dependencies, like axios, highcharts-react-official and highcharts/highmaps. So I tried to split the bundles.

On the webpack.config.js I'm trying to use DependOn in one of the entries. In this case, the workshop depends on axios, highcharts-react-official and highcharts/highmaps, so based on the webpack doc I tried this:

webpack.config.js

entry: {
    workshop: {
      import: "./wwwroot/component/WorkshopApp.tsx",
      dependOn: ["axios", "highmaps", "highchartreact"],
    },
    highchartreact: "highcharts-react-official",
    highmaps: "highcharts/highmaps",
    axios: "axios",
  },

.cshtml:

<div id="workshop" data-id=@Model></div>
<script src="~/bundles/js/axios-bundle.js"></script>
<script src="~/bundles/js/highchartreact-bundle.js"></script>
<script src="~/bundles/js/highmaps-bundle.js"></script>
<script src="~/bundles/js/workshop-bundle.js"></script>

It generates the 4 bundles, but the app is not displayed and I'm not getting any error.

However, if I put the dependencies in one entry, it works well:

webpack.config.js

entry: {
    workshop: {
      import: "./wwwroot/component/WorkshopApp.tsx",
      dependOn: ["workshopVendor"],
    },
    workshopVendor: [
      "axios",
      "highcharts-react-official",
      "highcharts/highmaps",
    ],
  },

.cshtml:

<div id="workshop" data-id=@Model></div>
<script src="~/bundles/js/workshopVendor-bundle.js"></script>
<script src="~/bundles/js/workshop-bundle.js"></script>

This is not a solution, because I want the dependencies in separate bundles, any idea? Thanks in advance!


Solution

  • Defining vendor bundles as separate entry points is no longer recommended. I think you're running into some dependency graph errors. Webpack should be able to fix this automatically using optimization.splitChunks. Something like this should work:

    module.exports = {
      //...
      optimization: {
        splitChunks: {
          cacheGroups: {
            axios: {
              test: /[\\/]node_modules[\\/]axios[\\/]/,
              name: 'axios',
              chunks: 'all',
            },
           'highcharts-react-official': {
              test: /[\\/]node_modules[\\/]highcharts-react-official[\\/]/,
              name: 'highcharts-react-official',
              chunks: 'all',
            },
           'highcharts/highmaps': {
              test: /[\\/]node_modules[\\/]highcharts[\\/]highmaps[\\/]/,
              name: 'highcharts/highmaps',
              chunks: 'all',
            },
          },
        },
      },
    };
    

    Per the docs:

    Tip

    In webpack version < 4 it was common to add vendors as a separate entry point to compile it as a separate file (in combination with the CommonsChunkPlugin).

    This is discouraged in webpack 4. Instead, the optimization.splitChunks option takes care of separating vendors and app modules and creating a separate file. Do not create an entry for vendors or other stuff that is not the starting point of execution.