From 86882add0d85b9af390e4fd2bc5a978174124eff Mon Sep 17 00:00:00 2001 From: yoho <907415276@qq.com> Date: Sat, 5 Mar 2022 05:28:07 +0800 Subject: [PATCH] feat(glob): import.meta.glob support alias path (#6526) --- .../glob-import/__tests__/glob-import.spec.ts | 13 ++++ packages/playground/glob-import/dir/alias.js | 1 + packages/playground/glob-import/dir/index.js | 3 +- .../playground/glob-import/vite.config.ts | 10 +++ packages/vite/src/node/importGlob.ts | 70 ++++++++++++++----- packages/vite/src/node/optimizer/scan.ts | 31 +++++--- .../vite/src/node/plugins/importAnalysis.ts | 9 ++- .../src/node/plugins/importAnalysisBuild.ts | 6 ++ 8 files changed, 112 insertions(+), 31 deletions(-) create mode 100644 packages/playground/glob-import/dir/alias.js create mode 100644 packages/playground/glob-import/vite.config.ts diff --git a/packages/playground/glob-import/__tests__/glob-import.spec.ts b/packages/playground/glob-import/__tests__/glob-import.spec.ts index 3a2425736548ea..fff8d9fe202ebc 100644 --- a/packages/playground/glob-import/__tests__/glob-import.spec.ts +++ b/packages/playground/glob-import/__tests__/glob-import.spec.ts @@ -7,6 +7,9 @@ import { } from '../../testUtils' const filteredResult = { + './alias.js': { + default: 'hi' + }, './foo.js': { msg: 'foo' } @@ -30,11 +33,19 @@ const json = isBuild const allResult = { // JSON file should be properly transformed + '/dir/alias.js': { + default: 'hi' + }, '/dir/baz.json': json, '/dir/foo.js': { msg: 'foo' }, '/dir/index.js': { + globWithAlias: { + './alias.js': { + default: 'hi' + } + }, modules: filteredResult }, '/dir/nested/bar.js': { @@ -80,6 +91,7 @@ if (!isBuild) { '/dir/a.js': {}, ...allResult, '/dir/index.js': { + ...allResult['/dir/index.js'], modules: { './a.js': {}, ...allResult['/dir/index.js'].modules @@ -102,6 +114,7 @@ if (!isBuild) { }, ...allResult, '/dir/index.js': { + ...allResult['/dir/index.js'], modules: { './a.js': { msg: 'a' diff --git a/packages/playground/glob-import/dir/alias.js b/packages/playground/glob-import/dir/alias.js new file mode 100644 index 00000000000000..9c533d93b9a98a --- /dev/null +++ b/packages/playground/glob-import/dir/alias.js @@ -0,0 +1 @@ +export default 'hi' diff --git a/packages/playground/glob-import/dir/index.js b/packages/playground/glob-import/dir/index.js index d13d470e2b2b80..fb87f69f0f3a61 100644 --- a/packages/playground/glob-import/dir/index.js +++ b/packages/playground/glob-import/dir/index.js @@ -1,3 +1,4 @@ const modules = import.meta.globEager('./*.(js|ts)') +const globWithAlias = import.meta.globEager('@dir/al*.js') -export { modules } +export { modules, globWithAlias } diff --git a/packages/playground/glob-import/vite.config.ts b/packages/playground/glob-import/vite.config.ts new file mode 100644 index 00000000000000..abc75b51656503 --- /dev/null +++ b/packages/playground/glob-import/vite.config.ts @@ -0,0 +1,10 @@ +import path from 'path' +import { defineConfig } from 'vite' + +export default defineConfig({ + resolve: { + alias: { + '@dir': path.resolve(__dirname, './dir/') + } + } +}) diff --git a/packages/vite/src/node/importGlob.ts b/packages/vite/src/node/importGlob.ts index 41bbb90a1f8a37..1247d60f1284d9 100644 --- a/packages/vite/src/node/importGlob.ts +++ b/packages/vite/src/node/importGlob.ts @@ -12,16 +12,38 @@ import { cleanUrl, singlelineCommentsRE, multilineCommentsRE, - blankReplacer + blankReplacer, + normalizePath } from './utils' import type { RollupError } from 'rollup' +interface GlobParams { + base: string + pattern: string + parentDepth: number + isAbsolute: boolean +} + export interface AssertOptions { assert?: { type: string } } +function formatGlobRelativePattern(base: string, pattern: string): GlobParams { + let parentDepth = 0 + while (pattern.startsWith('../')) { + pattern = pattern.slice(3) + base = path.resolve(base, '../') + parentDepth++ + } + if (pattern.startsWith('./')) { + pattern = pattern.slice(2) + } + + return { base, pattern, parentDepth, isAbsolute: false } +} + export async function transformImportGlob( source: string, pos: number, @@ -29,6 +51,7 @@ export async function transformImportGlob( importIndex: number, root: string, normalizeUrl?: (url: string, pos: number) => Promise<[string, string]>, + resolve?: (url: string, importer?: string) => Promise, preload = true ): Promise<{ importsString: string @@ -52,27 +75,36 @@ export async function transformImportGlob( importer = cleanUrl(importer) const importerBasename = path.basename(importer) - let [pattern, assertion, endIndex] = lexGlobPattern(source, pos) - if (!pattern.startsWith('.') && !pattern.startsWith('/')) { - throw err(`pattern must start with "." or "/" (relative to project root)`) - } - let base: string - let parentDepth = 0 - const isAbsolute = pattern.startsWith('/') - if (isAbsolute) { - base = path.resolve(root) - pattern = pattern.slice(1) - } else { - base = path.dirname(importer) - while (pattern.startsWith('../')) { - pattern = pattern.slice(3) - base = path.resolve(base, '../') - parentDepth++ + const [userPattern, assertion, endIndex] = lexGlobPattern(source, pos) + + let globParams: GlobParams | null = null + if (userPattern.startsWith('/')) { + globParams = { + isAbsolute: true, + base: path.resolve(root), + pattern: userPattern.slice(1), + parentDepth: 0 } - if (pattern.startsWith('./')) { - pattern = pattern.slice(2) + } else if (userPattern.startsWith('.')) { + globParams = formatGlobRelativePattern(path.dirname(importer), userPattern) + } else if (resolve) { + const resolvedId = await resolve(userPattern, importer) + if (resolvedId) { + const importerDirname = path.dirname(importer) + globParams = formatGlobRelativePattern( + importerDirname, + normalizePath(path.relative(importerDirname, resolvedId)) + ) } } + + if (!globParams) { + throw err( + `pattern must start with "." or "/" (relative to project root) or alias path` + ) + } + const { base, parentDepth, isAbsolute, pattern } = globParams + const files = glob.sync(pattern, { cwd: base, // Ignore node_modules by default unless explicitly indicated in the pattern diff --git a/packages/vite/src/node/optimizer/scan.ts b/packages/vite/src/node/optimizer/scan.ts index b0f5f7985b0f78..f1112bd38db423 100644 --- a/packages/vite/src/node/optimizer/scan.ts +++ b/packages/vite/src/node/optimizer/scan.ts @@ -319,7 +319,13 @@ function esbuildScanPlugin( return { // transformGlob already transforms to js loader: 'js', - contents: await transformGlob(js, path, config.root, loader) + contents: await transformGlob( + js, + path, + config.root, + loader, + resolve + ) } } @@ -438,12 +444,16 @@ function esbuildScanPlugin( } if (contents.includes('import.meta.glob')) { - return transformGlob(contents, id, config.root, ext as Loader).then( - (contents) => ({ - loader: ext as Loader, - contents - }) - ) + return transformGlob( + contents, + id, + config.root, + ext as Loader, + resolve + ).then((contents) => ({ + loader: ext as Loader, + contents + })) } return { loader: ext as Loader, @@ -458,7 +468,8 @@ async function transformGlob( source: string, importer: string, root: string, - loader: Loader + loader: Loader, + resolve: (url: string, importer?: string) => Promise ) { // transform the content first since es-module-lexer can't handle non-js if (loader !== 'js') { @@ -478,7 +489,9 @@ async function transformGlob( start, normalizePath(importer), index, - root + root, + undefined, + resolve ) s.prepend(importsString) s.overwrite(expStart, endIndex, exp) diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index 76dfe77a8cfe96..939764c7a7a53c 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -105,7 +105,11 @@ function markExplicitImport(url: string) { export function importAnalysisPlugin(config: ResolvedConfig): Plugin { const { root, base } = config const clientPublicPath = path.posix.join(base, CLIENT_PUBLIC_PATH) - + const resolve = config.createResolver({ + preferRelative: true, + tryIndex: false, + extensions: [] + }) let server: ViteDevServer let isOptimizedDepUrl: (url: string) => boolean @@ -351,7 +355,8 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { importer, index, root, - normalizeUrl + normalizeUrl, + resolve ) str().prepend(importsString) str().overwrite(expStart, endIndex, exp) diff --git a/packages/vite/src/node/plugins/importAnalysisBuild.ts b/packages/vite/src/node/plugins/importAnalysisBuild.ts index 41d9671a853cdd..2e2b116572752e 100644 --- a/packages/vite/src/node/plugins/importAnalysisBuild.ts +++ b/packages/vite/src/node/plugins/importAnalysisBuild.ts @@ -91,6 +91,11 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { ? `'modulepreload'` : `(${detectScriptRel.toString()})()` const preloadCode = `const scriptRel = ${scriptRel};const seen = {};const base = '${preloadBaseMarker}';export const ${preloadMethod} = ${preload.toString()}` + const resolve = config.createResolver({ + preferRelative: true, + tryIndex: false, + extensions: [] + }) return { name: 'vite:build-import-analysis', @@ -154,6 +159,7 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { index, config.root, undefined, + resolve, insertPreload ) str().prepend(importsString)