Mini-css-extract-plugin: using `[name].[contenthash].css` for `filename` is not deterministic

Created on 16 Feb 2021  路  5Comments  路  Source: webpack-contrib/mini-css-extract-plugin

  • Operating System: macOS BigSur 11.1
  • Node Version: 12.18.2
  • NPM Version: 7.5.2
  • webpack Version: 5.22.0
  • mini-css-extract-plugin Version: 1.3.7

Expected Behavior

contentHash to be stable and deterministic

Actual Behavior

Building same project without making changes between build will "randomly" result in different contentHash sometimes

Code

I don't have minimal reproduction, but I did bit of a code dive so hopefully following explanation could replace reproduction setup.

In https://github.com/webpack-contrib/mini-css-extract-plugin/blob/6009bd27374bbc10530a2dbeed2f6c54bcfb8da1/src/index.js#L532-L556 for webpack@5 chunkGraph is used. chunkGraph.getChunkModulesIterableBySourceType(chunk, MODULE_TYPE); return SortedSet of modules, however they are actually not sorted. Per https://github.com/webpack/webpack/blob/911ec1aa67011e25aa1449610f5b0b557edd5459/test/SortableSet.unittest.js it seems SortedSet means that it exposes .sort() method to get the Set sorted.

Later on m.updateHash(hash, { chunkGraph }); is called in order of modules in the SortedSet (which actually isn't sorted, and order of modules actually seem that can change between builds). Finally this result in contentHash that is generated not to be stable/deterministic.

For part about getChunkModulesIterableBySourceType returning unsorted modules I find minor mention in https://github.com/webpack/webpack/projects/6 :

Should getChunkModulesIterableBySourceType be sorted in general?

And following code for that method ( https://github.com/webpack/webpack/blob/05768d9029b9024d9a8d5f1aa56e649d9b963f57/lib/ChunkGraph.js#L538-L549 for entry), we can see that SortedSet is used (in modulesBySourceType implementation), but .sort() or .sortWith() is not called on it resulting in preserving order of module creation (?) which itself is probably not deterministic due to lot of async execution.

How Do We Reproduce?

As mentioned above - I don't have minimal reproduction for this problem, but I hope my research and description explain the issue well?

Most helpful comment

Yes identifier is a good choice. There are a few comparators in webpack.utils.comparators that you can/should use.

All 5 comments

There is a ordered method called getOrderedChunkModulesIterableBySourceType for this use case.

There is a ordered method called getOrderedChunkModulesIterableBySourceType for this use case.

What would be good thing to use in comparator to ensure deterministic order? <Module>.identifier()? (I'm pretty clueless when it comes to inner machinery of webpack :( )

Yes identifier is a good choice. There are a few comparators in webpack.utils.comparators that you can/should use.

I'll open PR changing from getChunkModulesIterableBySourceType to getOrderedChunkModulesIterableBySourceType (but most likely sometime in the upcomming weekend, unless someone beat me to it).

But looking through existing issues and PRs I noticed https://github.com/webpack-contrib/mini-css-extract-plugin/issues/454 / https://github.com/webpack-contrib/mini-css-extract-plugin/pull/482 which is somewhat related (just "reverse" problem) and thinking if changing order here will not make that issue worse.

I also found now closed similar issue https://github.com/webpack-contrib/mini-css-extract-plugin/issues/512 which pretty much sounds like same thing I described and was marked as solved (was the issue re-introduced or was it never actually fixed?)

Lastly - I do wonder how I could add reliable tests for this - it seems to me to ensure that things are tested I would have to construct chunkGraph artifically and changing order of inserted modules between runs and asserting that resulting contentHash remain stable?

@pieh We will fix it today (I think), I think https://github.com/webpack-contrib/mini-css-extract-plugin/issues/454 can be related, I will check it

Was this page helpful?
0 / 5 - 0 ratings