diff --git a/.changeset/windows-aliased-dynamic-import-reload.md b/.changeset/windows-aliased-dynamic-import-reload.md new file mode 100644 index 0000000000..efbe4226ba --- /dev/null +++ b/.changeset/windows-aliased-dynamic-import-reload.md @@ -0,0 +1,5 @@ +--- +'react-email': patch +--- + +Resolve tsconfig path aliases in dynamic import template literals on Windows, so editing a file inside an aliased directory reloads the preview. diff --git a/packages/react-email/src/cli/utils/preview/hot-reloading/resolve-path-aliases.spec.ts b/packages/react-email/src/cli/utils/preview/hot-reloading/resolve-path-aliases.spec.ts index be7635ec86..2dc68b9eb1 100644 --- a/packages/react-email/src/cli/utils/preview/hot-reloading/resolve-path-aliases.spec.ts +++ b/packages/react-email/src/cli/utils/preview/hot-reloading/resolve-path-aliases.spec.ts @@ -1,5 +1,8 @@ import path from 'node:path'; -import { resolvePathAliases } from './resolve-path-aliases.js'; +import { + resolveAliasedDirectoryPrefix, + resolvePathAliases, +} from './resolve-path-aliases.js'; test('resolveImports()', async () => { expect( @@ -9,3 +12,21 @@ test('resolveImports()', async () => { ), ).toEqual(['./some-file']); }); + +test('resolveAliasedDirectoryPrefix() accepts platform-normalized separators', () => { + const sourceDirectory = path.resolve( + import.meta.dirname, + './test/aliased-import-graph/src', + ); + const localesDirectory = path.join(sourceDirectory, 'locales'); + + expect(resolveAliasedDirectoryPrefix('@/locales', sourceDirectory)).toEqual( + localesDirectory, + ); + + // On Windows, `path.normalize()` turns the specifier's forward slashes into + // backslashes before the prefix reaches this function. + expect(resolveAliasedDirectoryPrefix('@\\locales', sourceDirectory)).toEqual( + localesDirectory, + ); +}); diff --git a/packages/react-email/src/cli/utils/preview/hot-reloading/resolve-path-aliases.ts b/packages/react-email/src/cli/utils/preview/hot-reloading/resolve-path-aliases.ts index 9eb0ab0022..fde8427f41 100644 --- a/packages/react-email/src/cli/utils/preview/hot-reloading/resolve-path-aliases.ts +++ b/packages/react-email/src/cli/utils/preview/hot-reloading/resolve-path-aliases.ts @@ -51,7 +51,13 @@ export const resolveAliasedDirectoryPrefix = ( configLoadResult.absoluteBaseUrl, configLoadResult.paths, ); - const resolved = matchPath(prefix, undefined, isExistingDirectory, [ + + // `paths` patterns are always written with forward slashes, but the prefix may + // have been normalized with the platform separator (backslashes on Windows) by + // `path.normalize()`. Restore import specifier separators so patterns match. + const importPrefix = prefix.replace(/\\/g, '/'); + + const resolved = matchPath(importPrefix, undefined, isExistingDirectory, [ '.tsx', '.ts', '.js',