Skip to content

HMR: inferring script source from moduleId is not reliable and don't work with [hash]/[fullhash] #444

Open
@jsnajdr

Description

@jsnajdr

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 a src attribute, but is an inline script. Then the HMR code will crash with TypeError: Cannot read property 'some' of null

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions