Skip to content

Circular imports in HMR #16580

Open
Open
@n9

Description

Description

As a developer migrating to Vite I want HMR to work with circular imports.

HMR currently fallbacks to full-reload when an exception is thrown during import:

if (isWithinCircularImport) {
importPromise.catch(() => {
console.info(
`[hmr] ${acceptedPath} failed to apply HMR as it's within a circular import. Reloading page to reset the execution order. ` +
`To debug and break the circular import, you can run \`vite --debug hmr\` to log the circular dependency path if a file change triggered it.`,
)
pageReload()
})
}

This happens when modules with the isWithinCircularImport flag are imported in a different than the original order.

Example:

  • Main imports Links
  • Links imports PageA, PageB, ...
  • PageA imports Links
  • PageB imports Links
  • ...

Simplified content of the Links module:

import PageA from "./PageA";
import PageB from "./PageB";

export const pageA = defineLink(PageA);
export const pageB = defineLink(PageB);
...

Modules PageA, PageB, ... define pages with their parameters and render links to other pages.

When Links is changed, HMR posts js-update with Links, which is fine.
However, when PageA is changed, HMR posts js-update with PageA, which fails with ReferenceError: Cannot access 'UsersPage' before initialization. (The exception is thrown because PageA imports the invalidated module Links, which references to PageA that has not yet been initialized.)

Suggested solution

The solution is to change HMR so that it imports modules in the same order as they were initially imported.

For the example above:

When PageA is changed, send js-update with Links instead of PageA.

Alternative

No response

Additional context

I found the following PRs that attempts to address HMR issues with circular imports:

And the following issues:

Validations

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions