24 thoughts on “dynamic import() chunk name

  1. The ES6 spec doesn’t support this and webpacks System.import implemenation should be comply to the spec.

    Why do you need a chunk name?

  2. The chunk name can be really useful for debugging to figure out the filename that an error is being thrown from, for example.

    I understand that this would be non-spec based on the current whatwg loader spec.

  3. @sokra @kesne I agree webpack should not deviate from the loader spec. Given we only need the chunk name at build time, what about using configuration comments (magic comments) to achieve the same thing?

    /* webpack chunk-name bar */
    System.import('./foo')

    Obviously, you can’t dynamically name chunks but AFAIK that wasn’t supported in Webpack 1 either.

  4. I also worry about assets caching. Given a name has a pattern of [chunkhash].[name].js, we get something like f4621a974f1f255ce2bf.0.js, which has greater chances of name collision with another chunk in the future than, say, f4621a974f1f255ce2bf.foo.js. Do my words make sense?

  5. It would be really great to have a proper way to name the chunks, it would help a lot debugging things and also knowing what needs to be improved right from the webpack output.
    Right now.. We just see that the chunk 0, 1, 2, 3 have a filesize of X :/ No idea why I need to change to improve the file size for example (without further investigation on what are the chunks obviously).

  6. Is it possible to use several import() calls with the same webpackChunkName to bundle them in the same chunk?

    yes

  7. @romulof @sokra

    Is it possible to use several import() calls with the same webpackChunkName to bundle them in the same chunk?

    yes

    Can anyone provide a working example of this? I cannot get a common chunk created with multiple files using the same webpackChunkName value.

    Promise.all([
        import('path/1/file1' /* webpackChunkName:"subload" */), //appears in subload.js
        import('path/2/file2')                     //appears in [id].js
    ])
    Promise.all([
        import('path/1/file1' /* webpackChunkName:"subload" */), //appears in [id].js
        import('path/2/file2' /* webpackChunkName:"subload" */) //appears in subload.js
    ])

    Is it a problem to have the source files at different paths?

  8. @chrisdeely this is working for me:

    async function loadIntl() {
      await import(/* webpackChunkName: "polyfill-intl" */ 'intl');
      await import(/* webpackChunkName: "polyfill-intl" */ 'intl/locale-data/jsonp/en.js');
      warning(false, 'Intl polyfill enabled');
    }
  9. Thanks @romulof working now. In my webpack.config.js I had to add a chunkFilename value to the output option.

    output: {
      filename: '[name].[chunkhash].js',
      chunkFilename: '[name].[chunkhash].js'
    }
  10. Could it be possible to have a dynamic chunk name for a dynamic import? E.g.

    (relativeModulePath, chunkName) =>
    import(
      /* webpackChunkName: `chunk-${chunkName}` */ `./${relativeModulePath}`
    )

    Hardcoded chunk names limit dynamic chunking abilities.

  11. Use NamedChunksPlugin can custom your dynamic import chunk name

    ...
    // used by code below;
    paths.assets = 'path/to/project/resource/assets';
    new webpack.NamedChunksPlugin(function(chunk) {
        // if it have name, and return name
        if (chunk.name) {
            return chunk.name;
        }
       
        const regex = new RegExp(`${paths.assets}/pages`);
    
        // every chunk have _modules, and iterate it.
        for (var m of chunk._modules) {
            // module context is the module path of webpack resolve for you.
            // such as require('react')
            // context will be /path/to/project/node_modules/react
            // because I want to locate the dynamic import url rather than other module.
            // and I know the dynamic import path have the prefix like /path/to/project/`resource/assets/pages`
            // so I can locate it use regex.
            if (regex.test(m.context)) {
                // return whatever name you defined
                return path
                    .relative(paths.assets, m.context)
                    .split('/')
                    .slice(1)
                    .join('_');
            }
        }
    
        return null;
    })
  12. @monkindey Thank you. One thing for future people using that to note is that path.assets should be the path to your source and you would need to bring in both webpack and path modules for this to work.

    const webpack = require('webpack');
    const path = require('path');
    

    If your src is one directory up from your webpack config:

    const paths = {
      assets: path.resolve(__dirname, '..', 'src')
    }
    
  13. As a follow up to my dynamic chunk name request, looks like there have been dynamic placeholders since 2.6:

    webpackChunkName: A name for the new chunk. Since webpack 2.6.0, the placeholders [index] and [request] are supported within the given string to an incremented number or the actual resolved filename respectively.

    https://webpack.js.org/api/module-methods/#import-

    I have yet to try it, and don’t know if it can be composed with other strings, but guessing it would look something like this:

    (relativeModulePath) =>
    import(
      /* webpackChunkName: "chunk-[request][index]" */ `./${relativeModulePath}`
    )
  14. Yes. Due to different environments between development and production, the chunk’s object emitted in production has a new property labeled issuer. That issuer will typically have a valid id to discern the chunk’s file name whereas other imports will not.

    I found this to work in production even with happy pack and various other plugins.

    // Valid for production only!
    const webpack = require('webpack');
    const regex = new RegExp(`${sourcePath}`);
    
    new webpack.NamedChunksPlugin(function(chunk) {
      if (chunk.name) return chunk.name;
      for (let m of chunk._modules) {
        if (regex.test(m.context)) {
          if (m.issuer && m.issuer.id) {
            return path.basename(m.issuer.rawRequest);
          } else {
            return path.basename(m.rawRequest);
          }
        }
      }
    })
    

    The logic above will solve problems for those who are tired of including the chunkname string to their dynamic imports.

    const Page1 = import(/* webpackChunkName: "Page1"*/ './Page1') 
    

    The dynamic import above will also solve the problem because these files/chunks will emit their own chunk name without the need to write a naming chunk plugin but it can be very tedious. It is a more secure fallback though.

  15. @simshanith Just note that you need quotes around the value passed to webpackChunkName. Took me a while to get your example working and that was the issue!

    (relativeModulePath) =>
      import(
        /* webpackChunkName: "chunk-[request][index]" */ 
        `./${relativeModulePath}`
      )

Comments are closed.