webpack.js.org icon indicating copy to clipboard operation
webpack.js.org copied to clipboard

Document webpack change: add full Semantic Versioning for Shared Modules

Open webpack-bot opened this issue 5 years ago • 0 comments

A pull request by @sokra was merged and maintainers requested a documentation change.

See pull request: https://github.com/webpack/webpack/pull/11105


  • change storage format in the share scope
    • We have to lift the limitation of having only one version per version position, as complex ranges could select lower versions
    • Instead we walk through all version available while consuming to find the highest in range
    • In the share scope we now store it this way: shareScope[shareKey][version] = { get, loaded, from }
      • from is now the uniqueName. When providing to the shareScope implementations should now override a version when from is equal or higher.
  • choose shared module deterministic from the same origin
    • output.uniqueName is used as second criteria if multiple builds provide the same version
    • This improves long term caching as used shared module do no longer depend on a race condition
  • remove array syntax from version and requiredVersion in schema
    • The new format is internal and should not be exposed to the user or API
    • And we want to have the option to change this later

Version are encoding this way:

1.2.3 => [1,2,3]
1.2.3-beta.42 => [1,2,3,,"beta",42]
1.2.3.4.5+55.66 => [1,2,3,4,5,[],55,66]
1.alternative-beta.42+55.66 => [1,"alternative",,"beta",42,[],55,66]

This format allows easy walking and decision based on typeof item. The duplicate ,, is intentional and creates a hole, which is typeof undefined, but very short to print^^

The format is SemVer compatible but less restrictive. We allow more and less version numbers. We allow strings as version numbers (might be useful for a/b tests). We do not apply additional restrictions on the possible chars.

Ranges are encoding this way:

Simple ranges
1.2.3, v1.2.3, =1.2.3 => [4,1,2,3] (4 fixed positions, 1,2,3 is the version
>=1.2.3 => [0,1,2,3]
^1.2.3 => [1,1,2,3]
^0.2.3 => [2,0,2,3]
^0.0.3 => [3,0,0,3]
<1.2.3 => [-1,1,2,3] (negative changes direction)
5, 5.x, 5.*, 5.X, 5.x.x, ... => [1,5]
9.8, 9.8.*, ... => [2,9,8]

Complex ranges
(They compile to a little program, executing simple ranges and operations on a stack)
(Complex ranges are identified by starting with a hole (!(0 in range)))
^4 || ^5 => [,[1,5],[1,4],1] (1 is the operation for OR)
>=2 <3 => [,[-1,3],[0,2],2] (2 is the operation for AND)
>1.2.3 => (>=1.2.3 not(1.2.3)) => [,[4,1,2,3],0,[0,1,2,3],2] (0 is the operation of NOT)
<=1.2.3 => [,[4,1,2,3],[-1,1,2,3],1]
1.2.3 - 3.2.1 => (>=1.2.3 <=3.2.1) => [,[4,3,2,1],[-1,3,2,1],1,[0,1,2,3],2]

The version and range encoding is only used webpack internal.

Sadly all this additional logic increases the bundle size by about 750b. The most logic is on the consuming shared modules side. But as the needed logic depends on the consumed shared version ranges in the application, there is improvement possible in future PRs. If only simple ranges (without prerelease/build tag) are used we could use a reduced satisfy version. In production we could omit rangeToString and use JSON.stringify instead. This would decrease the quality of errors/warnings, but might make sense for production.

What kind of change does this PR introduce? feature

Did you add tests for your changes? yes

Does this PR introduce a breaking change? yes (containers are not compatible to previous beta versions)

What needs to be documented once your changes are merged? The semver limitation can be removed.

webpack-bot avatar Jul 06 '20 21:07 webpack-bot