Skip to content

How to identify all chunks required for a module with webpack plugin? #8847

@tranvansang

Description

@tranvansang

I posted my question in Stackoverflow and webpack Gitter 2 weeks ago. But it looks like there is no expert there who can help me.

I am struggle with a code splitting lib which should identify all chunks required for dynamic imported modules to be loaded in server side, named react-loadable

It has bug and does not allow submit issue in github. Here is the final place which I can post for any help because this is seriously breaking my app.

I have Login component, it imports Login.scss module.
They are emitted to different chunks with id 24 and 26.

To be able to render Login, react-loadable's webpack plugin should load both 2 chunks. However, it only loads the first chunk with id 24.

Original code

    const Login = loadable({
      loader: () => import( './Login'),
      loading: BackDropLoading
    })

is compiled to

    var Login = react_loadable__WEBPACK_IMPORTED_MODULE_4___default()({
      loader: function loader() {
        return Promise.all(/*! import() */[__webpack_require__.e(24), __webpack_require__.e(26)]).then(__webpack_require__.bind(null, /*! ./Login */ "e4e16af1e58ef872f736"));
      },
      modules: ['./Login'],
      webpack: function webpack() {
        return [/*require.resolve*/(/*! ./Login */ "e4e16af1e58ef872f736")];
      },
      loading: _containers_BackDrop__WEBPACK_IMPORTED_MODULE_5__["BackDropLoading"]
    });

Is there anyway I can identify the above 24 and 26 numbers giving a rawRequest import('./Login') in a webpack plugin? How does webpack/babel find out these 2 magic numbers?

This is the portion of code in react-loadable webpack plugin, which identifies chunks for dynamic import statements.

    function buildManifest(compiler, compilation) {
      var context = compiler.options.context;
      var manifest = {};
    
      compilation.chunks.forEach(function (chunk) {
        const m = []
        for(const mm of chunk.modulesIterable) m.push(mm.rawRequest)
        console.log(chunk.id, m, chunk.files)
        chunk.files.forEach(function (file) {
          chunk.forEachModule(function (module) {
            var id = module.id;
            var name = typeof module.libIdent === 'function' ? module.libIdent({ context: context }) : null;
            var publicPath = url.resolve(compilation.outputOptions.publicPath || '', file);
    
            var currentModule = module;
            if (module.constructor.name === 'ConcatenatedModule') {
              currentModule = module.rootModule;
            }
            if (!manifest[currentModule.rawRequest]) {
              manifest[currentModule.rawRequest] = [];
            }
    
            manifest[currentModule.rawRequest].push({ id: id, name: name, file: file, publicPath: publicPath });
          });
        });
      });
    
      return manifest;
    }

Output manifest is (partial):

      "./Login": [
        {
          "id": "e4e16af1e58ef872f736",
          "name": "./src/client/components/auth/Login.js",
          "file": "26.js",
          "publicPath": "http://127.0.0.1:8080/bundles/26.js"
        },
        {
          "id": "e4e16af1e58ef872f736",
          "name": "./src/client/components/auth/Login.js",
          "file": "26.js.map",
          "publicPath": "http://127.0.0.1:8080/bundles/26.js.map"
        }
      ],

and other portion in the output manifest

      "./Login.scss": [
        {
          "id": "61dac8f85433b72d4f5b",
          "name": "./src/client/components/auth/Login.scss",
          "file": "24.css",
          "publicPath": "http://127.0.0.1:8080/bundles/24.css"
        },
        {
          "id": "61dac8f85433b72d4f5b",
          "name": "./src/client/components/auth/Login.scss",
          "file": "24.js",
          "publicPath": "http://127.0.0.1:8080/bundles/24.js"
        },
        {
          "id": "61dac8f85433b72d4f5b",
          "name": "./src/client/components/auth/Login.scss",
          "file": "24.css.map",
          "publicPath": "http://127.0.0.1:8080/bundles/24.css.map"
        },
        {
          "id": "61dac8f85433b72d4f5b",
          "name": "./src/client/components/auth/Login.scss",
          "file": "24.js.map",
          "publicPath": "http://127.0.0.1:8080/bundles/24.js.map"
        },
        {
          "id": "61dac8f85433b72d4f5b",
          "name": "./src/client/components/auth/Login.scss",
          "file": "28.css",
          "publicPath": "http://127.0.0.1:8080/bundles/28.css"
        },
        {
          "id": "61dac8f85433b72d4f5b",
          "name": "./src/client/components/auth/Login.scss",
          "file": "28.js",
          "publicPath": "http://127.0.0.1:8080/bundles/28.js"
        },
        {
          "id": "61dac8f85433b72d4f5b",
          "name": "./src/client/components/auth/Login.scss",
          "file": "28.css.map",
          "publicPath": "http://127.0.0.1:8080/bundles/28.css.map"
        },
        {
          "id": "61dac8f85433b72d4f5b",
          "name": "./src/client/components/auth/Login.scss",
          "file": "28.js.map",
          "publicPath": "http://127.0.0.1:8080/bundles/28.js.map"
        }
      ],

Here is my webpack splitchunk configuration. There is mostly irrelevant setting, I just paste here for reference.

      optimization: {
        runtimeChunk: "single",
        splitChunks: {
          chunks: ({name}) => !['polyfill', 'assets', 'polyfill-modern', 'ja', 'en'].includes(name),
          cacheGroups: {
            vendors: {
              test: /\/node_modules\//,
              priority: -10
            },
            assets: {
              test: /\.(svg|ttf|otf|eot|woff2?|bmp|cur|gif|icns|ico|jpe?g|png|psd|tiff|webp|dds)$/,
              priority: -10
            }
          },
        },
      },

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions