Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When emitting runtimeChunk, entry chunks use chunkFilename instead of filename #6598

Closed
nirazul opened this issue Feb 27, 2018 · 27 comments
Closed
Milestone

Comments

@nirazul
Copy link

@nirazul nirazul commented Feb 27, 2018

Do you want to request a feature or report a bug?
Bug (?)

What is the current behavior?
When defining options.runtimeChunk with true or another value, my entry modules are being written with the chunkFilename option instead of the filename option. However, the runtime doesn't seem to load my entry modules. When I add a script tag for the entry file, the page loads normally.

Which modules do I need to write script tags for? I'm automatically injecting all files that are in the directory controlled by the filename property.

If the current behavior is a bug, please provide the steps to reproduce.

const config = {
    entry: {
        app: [
            path.join(myCwd, 'app/main/index.js'),
            path.join(myCwd, 'app/main/hmr.js'),
        ],
    },
    mode: isDist ? 'production' : 'development',
    optimization: {
        namedModules: true,
        noEmitOnErrors: !isDist,
        runtimeChunk: true,
        splitChunks: false,
    },
    output: {
        path: destPath,
        filename: 'entry/[name]/index.js',
        chunkFilename: 'chunks/[name]/index.[chunkhash].js',
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
    ],
    resolve: {
        modules: [
            'node_modules',
            path.resolve(myCwd, 'app'),
        ],
    },
}

What is the expected behavior?
Entry chunks are emitted using the filename property.

Please mention other relevant information such as the browser version, Node.js version, webpack version, and Operating System.

  • webpack v4.0.1
  • node v8.9
@sokra
Copy link
Member

@sokra sokra commented Feb 27, 2018

The Stats has a entrypoints property which contains information about which files you need to add script tags for.

Loading

@nirazul
Copy link
Author

@nirazul nirazul commented Feb 27, 2018

@sokra
Thanks for your answer. I've tried it out and see that one entrypoint is the runtime and the other one is a chunk:

Entrypoint app = entry/runtime~app/index.js entry/runtime~app/index.js.map chunks/app/index.49dde4511aa9907b6bef.js chunks/app/index.49dde4511aa9907b6bef.js.map

Is there any way to programmatically separate the entry files from the chunks?
I need to implement two differen caching strategies (serverside for script tags, and webpack hashes for chunks). For automatic script tag injection, I need to know after compilation, which files I need to add. In webpack 3 I could separate them by folder name.

Loading

@sokra
Copy link
Member

@sokra sokra commented Feb 27, 2018

I need to implement two differen caching strategies

try to always use hashes. filename: "[chunkhash].js"

For automatic script tag injection, I need to know after compilation, which files I need to add.

see entrypoints property and include all js files in the list. You don't need folders

Is there any way to programmatically separate the entry files from the chunks?

All chunks are equal, technically a chunk used at entry time could also used on-demand for another entry. Only the runtime chunks is different, because it includes the runtime.

Loading

@nirazul
Copy link
Author

@nirazul nirazul commented Feb 27, 2018

@sokra
Thanks for your help, I really appreciate it!
I have a bit of a complicated setup. Unfortunately, when I'm using a chunkhash, the filenames would change every time I edit the file. This would lead to me checking in an ever changing HTML file to our git.

So I guess the way forward for me is to consume the entrypoints property. Unfortunately, I can't directly implement a chunk with a chunkhash attached due to the above mentioned redundant git commits.

I don't see any usable upgrade path for us, except disabling the runtimeChunk :/

Loading

@davidmerrique
Copy link

@davidmerrique davidmerrique commented Feb 27, 2018

@nirazul I'm also running into this, with a similar config to yours.

If I omit the output.chunkFilename option, entry chunks properly use filename.
However I then can't customize chunkFilename.

@sokra I think this is a bug, using output.chunkFilename shouldn't change output.filename.

Another thing I noticed, including runtimeChunk: 'single' also breaks output.filename

Take a look at these outputs:

/**
 * This is what I want:
 * runtime.js
 * pages/home.js
 * pages/contact.js
 * chunks/0.591536ba90b5d040ff6c.js
 * chunks/...
 * chunks/...
 */

const config = {
  entry: {
    'pages/home': 'app/pages/home.js',
    'pages/contact': 'app/pages/contact.js'
  },
  output: {
    filename: '[name].js',
    chunkFilename: 'chunks/[id].[chunkhash].js'
  },
  optimization: {
    runtimeChunk: 'single'
  }
};
/**
 * Output:
 * runtime.js
 * /pages/home.db984bf047928e400396.js <- entry points are not using output.filename properly
 * /pages/contact.c1abdbedcfe99819cca7.js
 * 0.591536ba90b5d040ff6c.js <- chunks are not in chunks/ folder
 * 1.ac4d619bda6ddfd7c91a.js
 */

const config = {
  entry: {
    'pages/home': 'app/pages/home.js',
    'pages/contact': 'app/pages/contact.js'
  },
  output: {
    filename: '[name].js',
    // chunkFilename: 'chunks/[id].[chunkhash].js' <- Remove this option
  },
  optimization: {
    runtimeChunk: 'single'
  }
};
/**
 * Output:
 * runtime.js
 * /pages/home.js <- this is correct now
 * /pages/contact.js
 * 0.js <- I can't use output.chunkFilename
 * 1.js
 */

const config = {
  entry: {
    'pages/home': 'app/pages/home.js',
    'pages/contact': 'app/pages/contact.js'
  },
  output: {
    filename: '[name].js',
    chunkFilename: 'chunks/[id].[chunkhash].js'
  },
  // optimization: {
  //   runtimeChunk: 'single' <- Remove this option
  // }
};
/**
 * Output:
 * ______ <- I want a single runtime chunk
 * /pages/home.js <- this is correct
 * /pages/contact.js
 * 0.591536ba90b5d040ff6c.js <- This is wrong, should be in chunks/ folder
 * 1.ac4d619bda6ddfd7c91a.js
 */

Loading

@sokra sokra added this to the webpack 4 milestone Feb 28, 2018
@jconroy
Copy link

@jconroy jconroy commented Mar 1, 2018

I think I too and hitting a similar issues https://gist.github.com/jconroy/b8f5e31ddfc040faf69a37fad3acb065

Loading

@glen-84
Copy link

@glen-84 glen-84 commented Apr 11, 2018

I've also experienced the issues described by @davidmerrique, and there is another related issue:

I'm getting this error:

ERROR in chunk scripts/runtime [entry]
[name]-[chunkhash].js
Cannot use [chunkhash] or [contenthash] for chunk in '[name]-[chunkhash].js' (use [hash] instead)

There's no option in optimization.runtimeChunk to set the file name, so it's using output.filename, which includes [chunkhash]. The only way to avoid this is to remove the [chunkhash] from output.filename, which I don't want to do.

@sokra These issues seem to be quite serious – will you be able to look into them soon?

Loading

@volodalexey
Copy link

@volodalexey volodalexey commented Apr 18, 2018

runtimeChunk name works for me (strange combination + filename) webpack 4.5.0:

module.exports = {
  ...
  output: {
    filename: '[name].bundle.js',
    chunkFilename: '[name].chunk.js',
    ...
  },
  optimization: {
    runtimeChunk: {
      name: 'manifest'
    }
    ...
  },
  ...
}

Output in my case:

      app.chunk.js   27.4 KiB       app  [emitted]  app
manifest.bundle.js   4.93 KiB  manifest  [emitted]  manifest
   vendor.chunk.js   2.95 MiB    vendor  [emitted]  vendor

Loading

@nirazul
Copy link
Author

@nirazul nirazul commented Apr 18, 2018

@volodalexey The issue isn't the runtimeChunk generation, but using it together with chunkhash

Loading

@MhMadHamster
Copy link
Contributor

@MhMadHamster MhMadHamster commented Apr 22, 2018

I've made a small plugin which allows you to rename chunks, or use your output.filename option for initial chunks with entry and without runtime. Should help with this issue: npm link.

Loading

@nirazul
Copy link
Author

@nirazul nirazul commented Apr 23, 2018

@MhMadHamster
I've tried out your plugin and it works like a charm! Thank you very much!

Would be nice to introduce the functionality into wepback core as the documentation states that by default, entry chunks should use the filename template.

Loading

@flibustier7seas
Copy link

@flibustier7seas flibustier7seas commented Jun 1, 2018

@glen-84
I was also getting this error:

ERROR in chunk runtime [entry]
[name].[chunkhash].js
Cannot use [chunkhash] or [contenthash] for chunk in '[name].[chunkhash].js' (use [hash] instead)

I think it has something to do with HotModuleReplacementPlugin, because without It everything works well.

Solution for me - overload output configuration for dev build:

    output: {
        path: path.join(__dirname, "dist"),
        filename: "[name].js",
    },

Loading

@sokra sokra removed this from the webpack 4 milestone Jun 21, 2018
@sokra sokra added this to the webpack 4.x milestone Jun 21, 2018
@glen-84
Copy link

@glen-84 glen-84 commented Jun 23, 2018

@flibustier7seas Ya, I was doing something like: filename: (isDev ? "[name].js" : "[name]-[chunkhash].js").

Edit: Now using filename: (isHot ? "[name].js" : "[name]-[contenthash:8].js").

Loading

@timneutkens
Copy link
Contributor

@timneutkens timneutkens commented Jun 27, 2018

Looks like @SevInf is working on a fix 🎉

We're running into this issue with Next.js, as entries don't have chunk hashes right now, but dynamic imports do.

Loading

@glen-84
Copy link

@glen-84 glen-84 commented Jun 27, 2018

@timneutkens The fix will only be in webpack 5 from what I can tell ... #7401.

Loading

@timneutkens
Copy link
Contributor

@timneutkens timneutkens commented Jun 29, 2018

As we needed this for Next.js I spent some time writing a plugin that applies the fix @SevInf wrote:

export default class ChunkNamesPlugin {
  apply (compiler) {
    compiler.hooks.compilation.tap('NextJsChunkNamesPlugin', (compilation) => {
      compilation.chunkTemplate.hooks.renderManifest.intercept({
        register(tapInfo) {
          if(tapInfo.name === 'JavascriptModulesPlugin') {
            const originalMethod = tapInfo.fn
            tapInfo.fn = (result, options) => {
              let filenameTemplate;
              const chunk = options.chunk;
              const outputOptions = options.outputOptions;
              if (chunk.filenameTemplate) {
                filenameTemplate = chunk.filenameTemplate;
              } else if (chunk.hasEntryModule()) {
                filenameTemplate = outputOptions.filename;
              } else {
                filenameTemplate = outputOptions.chunkFilename;
              }

              options.chunk.filenameTemplate = filenameTemplate
              return originalMethod(result, options)
            }
          }
          return tapInfo
        }
      })
    })
  }
}

Loading

@AlexMost
Copy link

@AlexMost AlexMost commented Oct 5, 2018

Is there any progress on this ticket? I have also met this trouble. if I set runtimeChunk, the chunkFilename format is applied instead of the filename.

Loading

@vv314
Copy link

@vv314 vv314 commented Oct 25, 2018

So, will this be fixed in webpack 4.x?

Loading

@hisapy
Copy link

@hisapy hisapy commented Dec 20, 2018

I modified @timneutkens's example to add support for .css initial chunks.

class ChunkNamesPlugin {
  apply(compiler) {
    compiler.hooks.compilation.tap('ChunkNamesPlugin', compilation => {
      compilation.chunkTemplate.hooks.renderManifest.intercept({
        register(tapInfo) {
          if (tapInfo.name === 'JavascriptModulesPlugin') {
            const originalFn = tapInfo.fn;

            tapInfo.fn = (result, options) => {
              const chunkName = options.chunk.name;

              // Don't mutate options passed to other plugins
              let customOpts = { ...options };

              if (chunkName === 'main' || chunkName === 'vendors~main') {
                customOpts.outputOptions = {
                  ...options.outputOptions,
                  chunkFilename: 'js/[name].chunk.js',
                };

                const hasCss =
                  result[0] &&
                  result[0].identifier.startsWith('mini-css-extract-plugin');

                if (hasCss) {
                  result[0].filenameTemplate = 'css/[name].chunk.css';
                }
              }

              originalFn(result, customOpts);
            };
          }

          return tapInfo;
        },
      });
    });
  }
}

Actually, I'm using it in our react-scripts fork

Loading

@danielkoch
Copy link

@danielkoch danielkoch commented Jan 11, 2019

Hi @hisapy, thanks for that solution. Did you used this plugin in combination with optimization.runtimeChunk = true and hashed filenames? Looks like the new names for css files are not populated into the runtime file.

Loading

@hisapy
Copy link

@hisapy hisapy commented Jan 11, 2019

According to the webpack.config for CRA, our runtimeChunk is true https://github.com/iporaitech/create-react-app/blob/iporaitech-react-scripts/packages/react-scripts/config/webpack.config.js#L254

However, with our custom build we don't add hashed file names of the initial chunks. We just add them to dynamic chunks. The hashes and manifest for initial chunks, the ones that we put in script and link tags in the HTML are generated by our Elixir Phoenix web application.

I believe the fork is out-of-date though. We haven't received PRs from Backstroke, the service that PRs each time master in upstream is updated.

Loading

@gruckus-gruckus
Copy link

@gruckus-gruckus gruckus-gruckus commented May 29, 2020

So, will this be fixed in webpack 4.x?

So, will this be fixed in webpack 5.x?

Loading

@webpack-bot
Copy link
Contributor

@webpack-bot webpack-bot commented Jan 16, 2021

This issue had no activity for at least three months.

It's subject to automatic issue closing if there is no activity in the next 15 days.

Loading

@webpack-bot
Copy link
Contributor

@webpack-bot webpack-bot commented Jan 31, 2021

Issue was closed because of inactivity.

If you think this is still a valid issue, please file a new issue with additional information.

Loading

@alexander-akait
Copy link
Member

@alexander-akait alexander-akait commented Jan 31, 2021

Let's keep open

Loading

@timneutkens
Copy link
Contributor

@timneutkens timneutkens commented Feb 1, 2021

Overall I think this can be closed. With webpack 5 every entrypoint can have it's own naming template independent of the global options which resolves the initial issue as filename was previously used to configure those entrypoints.

Loading

@sokra
Copy link
Member

@sokra sokra commented Feb 1, 2021

yep, that's "fixed" in webpack 5.

Loading

@sokra sokra closed this Feb 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet