webpack 4 numbered modules in resolution order, so adding one import renumbered everything after it and changed the vendor chunk hash.
optimization: {
moduleIds: 'deterministic', // hashed from the module path
chunkIds: 'deterministic',
runtimeChunk: 'single', // the map lives here, and
// it changes every build
}
// before: every deploy invalidated vendor.js for every
// returning visitor — about 900 KB, needlessly
// after: vendor.js changes when a dependency changes
Separating the runtime is the other half: it holds the module map, so it changes on every build, and leaving it inside the vendor chunk means the vendor hash still moves. Together they are the difference between a returning visitor downloading nothing and downloading the whole bundle after every deploy. Both are defaults in webpack 5 production mode, which is one of the better reasons to upgrade.