Numeric module ids in 4 shifted when a module was added, which changed the content of every chunk after it and invalidated caches for files that had not changed.
optimization: {
moduleIds: 'deterministic', // the default in production, in 5
chunkIds: 'deterministic',
runtimeChunk: 'single',
}
// add one module, rebuild:
// webpack 4: 11 of 14 chunk hashes changed
// webpack 5: 2 of 14
Deterministic ids are derived from the module path rather than from an ordinal, so adding a file changes only the chunks that contain it. runtimeChunk: 'single' is the other half: the module map lives in its own small file, so application changes do not invalidate the vendor bundle. Together they are what makes long-term caching actually work, and neither has any downside beyond a slightly larger runtime.