diff --git a/playground/TestAlias.vue b/playground/TestAlias.vue
index e75fd2492cb1c1..dac3663318149a 100644
--- a/playground/TestAlias.vue
+++ b/playground/TestAlias.vue
@@ -3,18 +3,21 @@
{{ msg }}
{{ dirMsg }}
{{ dirIndexMsg }}
+ {{ importOutsideMsg }}
diff --git a/playground/aliased-dir-import.js b/playground/aliased-dir-import.js
new file mode 100644
index 00000000000000..e9b82fdd714f20
--- /dev/null
+++ b/playground/aliased-dir-import.js
@@ -0,0 +1 @@
+export const msg = 'directory aliased internal import outside works'
diff --git a/playground/aliased-dir/importOutside.js b/playground/aliased-dir/importOutside.js
new file mode 100644
index 00000000000000..8e6b6ffb6dddd1
--- /dev/null
+++ b/playground/aliased-dir/importOutside.js
@@ -0,0 +1 @@
+export { msg } from '../aliased-dir-import'
diff --git a/src/node/resolver.ts b/src/node/resolver.ts
index 9285cd4d6533a2..4469c758e168bb 100644
--- a/src/node/resolver.ts
+++ b/src/node/resolver.ts
@@ -30,6 +30,10 @@ export interface InternalResolver {
fileToRequest(filePath: string): string
normalizePublicPath(publicPath: string): string
alias(id: string): string | undefined
+ resolveRelativeRequest(
+ publicPath: string,
+ relativePublicPath: string
+ ): { pathname: string; query: string }
}
export const supportedExts = ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json']
@@ -118,6 +122,7 @@ export function createResolver(
): InternalResolver {
resolvers = [...resolvers]
const literalAlias: Record = {}
+ const literalDirAlias: Record = {}
const resolveAlias = (alias: Record) => {
for (const key in alias) {
@@ -143,6 +148,7 @@ export function createResolver(
}
}
})
+ literalDirAlias[key] = target
} else {
literalAlias[key] = target
}
@@ -281,6 +287,25 @@ export function createResolver(
return aliased
}
}
+ },
+
+ resolveRelativeRequest(publicPath: string, relativePublicPath: string) {
+ let dirname = path.dirname(publicPath)
+ for (const alias in literalDirAlias) {
+ if (publicPath.startsWith(alias)) {
+ dirname = path.join('/', path.relative(root, literalDirAlias[alias]))
+ break
+ }
+ }
+
+ const resolved = slash(path.posix.resolve(dirname, relativePublicPath))
+ const queryMatch = relativePublicPath.match(queryRE)
+ return {
+ // path resovle strips ending / which should be preserved
+ pathname:
+ cleanUrl(resolved) + (relativePublicPath.endsWith('/') ? '/' : ''),
+ query: queryMatch ? queryMatch[0] : ''
+ }
}
}
diff --git a/src/node/server/serverPluginModuleRewrite.ts b/src/node/server/serverPluginModuleRewrite.ts
index 9cf6069f1ce890..0804fa5ef2db66 100644
--- a/src/node/server/serverPluginModuleRewrite.ts
+++ b/src/node/server/serverPluginModuleRewrite.ts
@@ -22,12 +22,7 @@ import {
hmrDirtyFilesMap,
latestVersionsMap
} from './serverPluginHmr'
-import {
- readBody,
- cleanUrl,
- isExternalUrl,
- resolveRelativeRequest
-} from '../utils'
+import { readBody, cleanUrl, isExternalUrl } from '../utils'
import chalk from 'chalk'
import { isCSSRequest } from '../utils/cssUtils'
@@ -252,7 +247,7 @@ export const resolveImport = (
} else {
// 1. relative to absolute
// ./foo -> /some/path/foo
- let { pathname, query } = resolveRelativeRequest(importer, id)
+ let { pathname, query } = resolver.resolveRelativeRequest(importer, id)
// 2. resolve dir index and extensions.
pathname = resolver.normalizePublicPath(pathname)
diff --git a/src/node/utils/pathUtils.ts b/src/node/utils/pathUtils.ts
index 27e8b154d5fdba..e7afabb86d527c 100644
--- a/src/node/utils/pathUtils.ts
+++ b/src/node/utils/pathUtils.ts
@@ -1,4 +1,3 @@
-import path from 'path'
import slash from 'slash'
import qs, { ParsedUrlQuery } from 'querystring'
import resolve from 'resolve'
@@ -19,16 +18,6 @@ export const hashRE = /#.*$/
export const cleanUrl = (url: string) =>
url.replace(hashRE, '').replace(queryRE, '')
-export const resolveRelativeRequest = (importer: string, id: string) => {
- const resolved = slash(path.posix.resolve(path.dirname(importer), id))
- const queryMatch = id.match(queryRE)
- return {
- // path resovle strips ending / which should be preserved
- pathname: cleanUrl(resolved) + (id.endsWith('/') ? '/' : ''),
- query: queryMatch ? queryMatch[0] : ''
- }
-}
-
export const parseWithQuery = (
id: string
): {
diff --git a/test/test.js b/test/test.js
index 3917d7a5f22c4b..8de7a21bedee34 100644
--- a/test/test.js
+++ b/test/test.js
@@ -470,11 +470,15 @@ describe('vite', () => {
expect(await getText('.dir-alias-index')).toMatch(
'directory alias index works'
)
+ expect(await getText('.dir-alias-import-outside')).toMatch(
+ 'directory aliased internal import outside works'
+ )
if (!isBuild) {
await updateFile('aliased/index.js', (c) =>
c.replace('works', 'hmr works')
)
await expectByPolling(() => getText('.alias'), 'alias hmr works')
+
await updateFile('aliased-dir/named.js', (c) =>
c.replace('works', 'hmr works')
)
@@ -482,6 +486,7 @@ describe('vite', () => {
() => getText('.dir-alias'),
'directory alias hmr works'
)
+
await updateFile('aliased-dir/index.js', (c) =>
c.replace('works', 'hmr works')
)
@@ -489,6 +494,14 @@ describe('vite', () => {
() => getText('.dir-alias-index'),
'directory alias index hmr works'
)
+
+ await updateFile('aliased-dir-import.js', (c) =>
+ c.replace('works', 'hmr works')
+ )
+ await expectByPolling(
+ () => getText('.dir-alias-import-outside'),
+ 'directory aliased internal import outside hmr works'
+ )
}
})