Description
The HMR code needs to do some magic to convert the moduleId
of the updated module to the URLs of the CSS chunks that contain the module. These URLs then need to be reloaded.
Trying to enable it in Calypso revealed at least three bugs:
Doesn't work with async-loaded chunks
getCurrentScriptUrl
relies on document.currentScript
, which works when the chunk is loaded with script
tag, but not when a chunk is loaded asynchronously. Then the module is evaluated in a Promise.then
handler and document.currentScript
is null
. No hot reload.
Is not reliable with shared chunks
With shared async chunks optimized by SplitChunksPlugin
, it commonly happens that a module code is duplicated in multiple chunks. To reliably hot-reload their CSS, we need to reload all the CSS chunks where the module is bundled. That doesn't happen at this moment. Only the chunk that was used to actually execute the module is reloaded.
Fallback to "last script
tag" almost never works
When getCurrentScriptUrl
can't find document.currentScript
, it falls back to using the src
attribute of the last script
tag in the document. That works for very simple apps that load a single JS bundle, but fails in cases like:
- there are shared chunks that together form a chunk group. There's not reason why the last chunk should contain the updated
moduleId
- the last
script
tag is not owned by webpack, but loads something else. For example, analytics from a 3rd party source - the last
script
doesn't have asrc
attribute, but is an inline script. Then the HMR code will crash withTypeError: Cannot read property 'some' of null