Skip to content

fix(react-email): resolve aliased dynamic import directories on Windows - #3799

Open
sachinkr7368 wants to merge 1 commit into
resend:canaryfrom
sachinkr7368:fix/windows-aliased-dynamic-import-reload
Open

sachinkr7368 wants to merge 1 commit into
resend:canaryfrom
sachinkr7368:fix/windows-aliased-dynamic-import-reload

Conversation

@sachinkr7368

@sachinkr7368 sachinkr7368 commented Oct 23, 2026 •

Copy link
Copy Markdown

Summary

Fixes #3796.

resolveDynamicImportDirectory normalizes the template literal prefix with path.normalize(). On Windows that rewrites "@/locales/" as "@\\locales\\", and the trimmed prefix is then handed to tsconfig-paths' matchPath. Patterns like "@/*" only match forward slashes, so the lookup returns undefined, the aliased directory is never added to dynamicDependencyDirectories, and edits inside it emit no reload.

This restores import specifier separators before matching the configured paths. Relative prefixes are unaffected, since they still go through path.resolve().

Verification

Added resolveAliasedDirectoryPrefix() accepts platform-normalized separators, which covers both separators explicitly:

resolveAliasedDirectoryPrefix("@/locales", sourceDirectory);   // -> src/locales
resolveAliasedDirectoryPrefix("@\\locales", sourceDirectory);  // -> src/locales

Without the fix the Windows-shaped call returns undefined:

AssertionError: expected undefined to deeply equal .../src/locales

Passing with the fix:

The wider package suite in this checkout fails to resolve unbuilt workspace packages (@react-email/render), which is unrelated to this change.

Credit

The reproduction and root-cause analysis in #3796 are from @MokiMeow. I have only applied the one-line separator normalization and added the regression test they described.


Prepared with AI assistance (OpenCode).


Summary by cubic

Fixes preview hot-reloading on Windows so edits to files inside tsconfig-path-aliased directories trigger a reload.

On Windows, path.normalize() converts import specifier separators to backslashes (@/locales/ becomes @\locales\), and tsconfig-paths patterns like "@/*" only match forward slashes, so the aliased directory was never added to the watched set. The prefix separators are now restored to forward slashes before matching, with a regression test covering both separator forms.

Written for commit 1546a19. Summary will update on new commits.

View guided diff

resolveDynamicImportDirectory normalized the template literal prefix with path.normalize(), which on Windows rewrites '@/locales/' as '@\locales\'. That prefix then reaches tsconfig-paths' matchPath, whose '@/*' patterns only match forward slashes, so the lookup returned undefined and the aliased directory was never watched.

Restore import specifier separators before matching the tsconfig paths.
@changeset-bot

changeset-bot Bot commented Oct 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 1546a19

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
react-email Patch
@react-email/editor Patch
@react-email/ui Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

@sachinkr7368 is attempting to deploy a commit to the resend Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions Bot added the linear-synced PR has been synced to Linear label Oct 24, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

linear-synced PR has been synced to Linear

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows: preview watcher misses aliased dynamic-import directories

1 participant