Andy
Andy

Reputation: 351

Webpack Code Splitting / Lazy Loading: Two files generated for one dynamic import() of an npm package

I have an Angular 12 app which I bundle with Webpack 5 and I'm facing some problems implementing Webpack Code Splitting / Lazy Loading.

In my package.json I have the following dependency:

"crypto-js": "4.1.1"

So far, in my Angular code I have used:

const CryptoJS = require('crypto-js');

When bundling with Webpack the ~200kb source code of crypto-js is included in my vendor.js. But this vendor.js now has grown so huge in size that I want to split my code and lazy load crypto-js (and others, but for now I just use crypto-js as an example). I only need that third-party library at a certain point in my app, so I started to use:

import(/* webpackChunkName: 'crypto' */ 'crypto-js').then(CryptoJS => { ... });

where I need it. Actually this works (the crypto-js is not in vendor.js anymore and it is lazy loaded where I need it), but with a very ugly behaviour: Webpack generates two files: The file crypto.js (as defined with magic comment "webpackChunkName") and the file 480.js. The file with the number contains the crypto-js source code and the crypto.js contains the following:

(self["webpackChunkclassroom"] = self["webpackChunkclassroom"] || []).push([[634],{

/***/ 42480:
/***/ (() => {

/* (ignored) */

/***/ })

}]);

When testing lazy loading both files are loaded from the server, that's why everything works. But instead of one request I have two, which is totally unnecessary and very ugly. In addition, I lose track of everything.

As a side mark:

When I copy the crypto-js.js from the node-modules folder to an assets folder in my web app and import this file:

import(/* webpackChunkName: 'crypto' */ '../../assets/crypto-js.js').then(CryptoJS => { ... });

then everything behaves exactly as I want. Only one file "crypto.js" is created and lazy loaded.

But I don't want to have JavaScript files in my assets folder (so that I have to keep them up-to-date by my own). I wanna use package.json and the benefits of NPM to keep my third-party libraries up-to-date.

Can somebody help me to solve my problem? What am I doing wrong?

Upvotes: 3

Views: 1310

Answers (1)

Andy
Andy

Reputation: 351

I succeeded to make it work.

In the Webpack config I added the following splitChunks configuration:

   optimization: {
       splitChunks: {
            cacheGroups: {
                defaultVendors: {
                    test: /[\\/]node_modules[\\/](?!crypto-js)/,
                    name: 'vendor',
                    chunks: 'all'
                }
            }
        }
    }

IMPORTANT:

  • I exclude the NPM package crypto-js in the test regex
  • The cachedGroup must be named defaultVendors (everything else will fail)

Upvotes: 3

Related Questions