Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(glob): import.meta.glob support alias path #6526

Merged
merged 23 commits into from Mar 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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,
poyoho marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -347,7 +351,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