Skip to content

Commit

Permalink
feat(glob): import.meta.glob support alias path (#6526)
Browse files Browse the repository at this point in the history
  • Loading branch information
poyoho committed Mar 4, 2022
1 parent 6cb0647 commit 86882ad
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 31 deletions.
13 changes: 13 additions & 0 deletions packages/playground/glob-import/__tests__/glob-import.spec.ts
Expand Up @@ -7,6 +7,9 @@ import {
} from '../../testUtils'

const filteredResult = {
'./alias.js': {
default: 'hi'
},
'./foo.js': {
msg: 'foo'
}
Expand All @@ -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': {
Expand Down Expand Up @@ -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
Expand All @@ -102,6 +114,7 @@ if (!isBuild) {
},
...allResult,
'/dir/index.js': {
...allResult['/dir/index.js'],
modules: {
'./a.js': {
msg: 'a'
Expand Down
1 change: 1 addition & 0 deletions packages/playground/glob-import/dir/alias.js
@@ -0,0 +1 @@
export default 'hi'
3 changes: 2 additions & 1 deletion 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 }
10 changes: 10 additions & 0 deletions 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/')
}
}
})
70 changes: 51 additions & 19 deletions packages/vite/src/node/importGlob.ts
Expand Up @@ -12,23 +12,46 @@ 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,
importer: string,
importIndex: number,
root: string,
normalizeUrl?: (url: string, pos: number) => Promise<[string, string]>,
resolve?: (url: string, importer?: string) => Promise<string | undefined>,
preload = true
): Promise<{
importsString: string
Expand All @@ -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
Expand Down
31 changes: 22 additions & 9 deletions packages/vite/src/node/optimizer/scan.ts
Expand Up @@ -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
)
}
}

Expand Down Expand Up @@ -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,
Expand All @@ -458,7 +468,8 @@ async function transformGlob(
source: string,
importer: string,
root: string,
loader: Loader
loader: Loader,
resolve: (url: string, importer?: string) => Promise<string | undefined>
) {
// transform the content first since es-module-lexer can't handle non-js
if (loader !== 'js') {
Expand All @@ -478,7 +489,9 @@ async function transformGlob(
start,
normalizePath(importer),
index,
root
root,
undefined,
resolve
)
s.prepend(importsString)
s.overwrite(expStart, endIndex, exp)
Expand Down
9 changes: 7 additions & 2 deletions packages/vite/src/node/plugins/importAnalysis.ts
Expand Up @@ -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

Expand Down Expand Up @@ -351,7 +355,8 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
importer,
index,
root,
normalizeUrl
normalizeUrl,
resolve
)
str().prepend(importsString)
str().overwrite(expStart, endIndex, exp)
Expand Down
6 changes: 6 additions & 0 deletions packages/vite/src/node/plugins/importAnalysisBuild.ts
Expand Up @@ -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',
Expand Down Expand Up @@ -154,6 +159,7 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
index,
config.root,
undefined,
resolve,
insertPreload
)
str().prepend(importsString)
Expand Down

0 comments on commit 86882ad

Please sign in to comment.