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

SA
2d ago
+34-2

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:

  • vitest run src/cli/utils/preview/hot-reloading — 24 passed (includes the existing alias and alias-fallback graph tests from #3422)
  • biome check — clean

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.