Skip to content

RealContentHashPlugin watch rebuild can keep stale runtime chunk filename hashes #20710

@davidmurdoch

Description

@davidmurdoch

Bug report

When using watch mode with cache: { type: "memory" }, optimization.runtimeChunk: "single", and splitChunks forcing a named shared chunk, the second compilation can fail in RealContentHashPlugin after a source edit.

RealContentHashPlugin is only where the stale reference gets detected. The stale hash appears to be baked into the runtime chunk before the changed initial chunk has been re-hashed.

Minimal reproduction

async-entry.js

import("./sync-entry.js");

sync-entry.js

import "./large-shared.js";
export const syncValue = "__SYNC__";
console.log(syncValue);

large-shared.js

const bigTextBlob = `a VERY big string here to force chunking. like.... HUUGGGEEEEE. to reproduce you'll need to embed some long string here. I tested with the whole text of lodash`;
export const sharedValue = "__SHARED__";
console.log(sharedValue, bigTextBlob.length);

webpack.config.js

const path = require("path");

module.exports = {
  mode: "production",
  context: __dirname,
  cache: {
    type: "memory"
  },
  entry: {
    async: "./async-entry.js",
    sync: "./sync-entry.js",
    light: "./sync-entry.js"
  },
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "[contenthash].js"
  },
  optimization: {
    runtimeChunk: "single",
    splitChunks: {
      chunks: "all",
      name: "js"
    }
  }
};

Rebuild sequence:

  1. Start compiler.watch(...)
  2. Wait for the first successful build
  3. Rewrite large-shared.js, changing __SHARED__ to __SHARED__CHANGED
  4. Wait for the second build

Observed result:

ERROR in RealContentHashPlugin
Some kind of unexpected caching problem occurred.
An asset was cached with a reference to another asset (...) that's not in the compilation anymore.

Expected result:

The second watch build should succeed.

Suspected cause

In lib/Compilation.js, createHash() includes this comment:

all non-runtime chunks need to be hashes first, since runtime chunk might use their hashes.

But the implementation currently hashes chunks in this order:

  1. async chunks
  2. runtime chunks
  3. initial chunks

That seems backwards for runtime modules like GetChunkFilenameRuntimeModule, which are marked dependentHash and can embed initial chunk hashes. On rebuild, the runtime chunk can therefore keep a stale intermediate hash for a changed initial chunk, and RealContentHashPlugin later reports that stale reference.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions