From 9bbf3dd0880e0d44be090d1bf8737d70ae6841f0 Mon Sep 17 00:00:00 2001 From: yoho Date: Fri, 15 Apr 2022 23:20:57 +0800 Subject: [PATCH 01/30] feat: re-implement dynamicImportVars --- .../playground/dynamic-import/nested/index.js | 8 + packages/vite/src/node/build.ts | 4 +- packages/vite/src/node/importGlob.ts | 179 ++++++++++++++---- .../src/node/plugins/dynamicImportVars.ts | 113 +++++++++++ packages/vite/types/shims.d.ts | 2 + 5 files changed, 271 insertions(+), 35 deletions(-) create mode 100644 packages/vite/src/node/plugins/dynamicImportVars.ts diff --git a/packages/playground/dynamic-import/nested/index.js b/packages/playground/dynamic-import/nested/index.js index 5518c56a35a2cc..aa65d1f557d53b 100644 --- a/packages/playground/dynamic-import/nested/index.js +++ b/packages/playground/dynamic-import/nested/index.js @@ -73,3 +73,11 @@ document.querySelector('.css').addEventListener('click', async () => { function text(el, text) { document.querySelector(el).textContent = text } + +const variable = 'mxd' +const mod = import(`../${variable}.js?raw`) +console.log(mod) + +const base = '' +const glob = import.meta.glob(`./*.js`, { as: 'raw' }) +console.log(glob) diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts index ff03352a20d7a7..71bad8bd14b530 100644 --- a/packages/vite/src/node/build.ts +++ b/packages/vite/src/node/build.ts @@ -26,7 +26,7 @@ import { copyDir, emptyDir, lookupFile, normalizePath } from './utils' import { manifestPlugin } from './plugins/manifest' import commonjsPlugin from '@rollup/plugin-commonjs' import type { RollupCommonJSOptions } from 'types/commonjs' -import dynamicImportVars from '@rollup/plugin-dynamic-import-vars' +import { dynamicImportVars } from './plugins/dynamicImportVars' import type { RollupDynamicImportVarsOptions } from 'types/dynamicImportVars' import type { Logger } from './logger' import type { TransformOptions } from 'esbuild' @@ -313,7 +313,7 @@ export function resolveBuildPlugins(config: ResolvedConfig): { watchPackageDataPlugin(config), commonjsPlugin(options.commonjsOptions), dataURIPlugin(), - dynamicImportVars(options.dynamicImportVarsOptions), + dynamicImportVars(config), assetImportMetaUrlPlugin(config), ...(options.rollupOptions.plugins ? (options.rollupOptions.plugins.filter(Boolean) as Plugin[]) diff --git a/packages/vite/src/node/importGlob.ts b/packages/vite/src/node/importGlob.ts index a759bee2b5fa59..7d1ec3a699557a 100644 --- a/packages/vite/src/node/importGlob.ts +++ b/packages/vite/src/node/importGlob.ts @@ -13,11 +13,13 @@ import { singlelineCommentsRE, multilineCommentsRE, blankReplacer, - normalizePath + normalizePath, + parseRequest } from './utils' -import type { RollupError } from 'rollup' +import type { RollupError, TransformPluginContext } from 'rollup' import type { Logger } from '.' import colors from 'picocolors' +import { dynamicImportToGlob } from '@rollup/plugin-dynamic-import-vars' interface GlobParams { base: string @@ -36,6 +38,10 @@ interface GlobOptions { } } +interface DynamicImportRequest { + raw?: boolean +} + function formatGlobRelativePattern(base: string, pattern: string): GlobParams { let parentDepth = 0 while (pattern.startsWith('../')) { @@ -50,13 +56,15 @@ function formatGlobRelativePattern(base: string, pattern: string): GlobParams { return { base, pattern, parentDepth, isAbsolute: false } } -export async function transformImportGlob( +export async function transformGlob( source: string, pos: number, importer: string, importIndex: number, + importEndIndex: number, + query: DynamicImportRequest, + userPattern: string, root: string, - logger: Logger, normalizeUrl?: (url: string, pos: number) => Promise<[string, string]>, resolve?: (url: string, importer?: string) => Promise, preload = true @@ -69,21 +77,9 @@ export async function transformImportGlob( pattern: string base: string }> { - const isEager = source.slice(pos, pos + 21) === 'import.meta.globEager' - const isEagerDefault = - isEager && source.slice(pos + 21, pos + 28) === 'Default' - - const err = (msg: string) => { - const e = new Error(`Invalid glob import syntax: ${msg}`) - ;(e as any).pos = pos - return e - } - importer = cleanUrl(importer) const importerBasename = path.basename(importer) - const [userPattern, options, endIndex] = lexGlobPattern(source, pos) - let globParams: GlobParams | null = null if (userPattern.startsWith('/')) { globParams = { @@ -106,9 +102,7 @@ export async function transformImportGlob( } if (!globParams) { - throw err( - `pattern must start with "." or "/" (relative to project root) or alias path` - ) + throw `pattern must start with "." or "/" (relative to project root) or alias path` } const { base, parentDepth, isAbsolute, pattern } = globParams @@ -117,6 +111,8 @@ export async function transformImportGlob( // Ignore node_modules by default unless explicitly indicated in the pattern ignore: /(^|\/)node_modules\//.test(pattern) ? [] : ['**/node_modules/**'] }) + + const isEager = source.slice(pos, pos + 21) === 'import.meta.globEager' const imports: string[] = [] let importsString = `` let entries = `` @@ -133,23 +129,13 @@ export async function transformImportGlob( ;[importee] = await normalizeUrl(file, pos) } imports.push(importee) - // TODO remove assert syntax for the Vite 3.0 release. - const isRawAssert = options?.assert?.type === 'raw' - const isRawType = options?.as === 'raw' - if (isRawType || isRawAssert) { - if (isRawAssert) { - logger.warn( - colors.yellow( - colors.bold( - "(!) import.meta.glob('...', { assert: { type: 'raw' }}) is deprecated. Use import.meta.glob('...', { as: 'raw' }) instead." - ) - ) - ) - } + if (query.raw) { entries += ` ${JSON.stringify(file)}: ${JSON.stringify( await fsp.readFile(path.join(base, files[i]), 'utf-8') )},` } else { + const isEagerDefault = + isEager && source.slice(pos + 21, pos + 28) === 'Default' const importeeUrl = isCSSRequest(importee) ? `${importee}?used` : importee if (isEager) { const identifier = `__glob_${importIndex}_${i}` @@ -175,13 +161,140 @@ export async function transformImportGlob( imports, importsString, exp: `{${entries}}`, - endIndex, + endIndex: importEndIndex, isEager, pattern, base } } +export async function transformImportGlob( + source: string, + pos: number, + importer: string, + importIndex: number, + root: string, + logger: Logger, + normalizeUrl?: (url: string, pos: number) => Promise<[string, string]>, + resolve?: (url: string, importer?: string) => Promise, + preload = true +): Promise<{ + importsString: string + imports: string[] + exp: string + endIndex: number + isEager: boolean + pattern: string + base: string +}> { + const err = (msg: string) => { + const e = new Error(`Invalid glob import syntax: ${msg}`) + ;(e as any).pos = pos + return e + } + const [userPattern, options, endIndex] = lexGlobPattern(source, pos) + const query: DynamicImportRequest = {} + + // TODO remove assert syntax for the Vite 3.0 release. + const isRawAssert = options?.assert?.type === 'raw' + const isRawType = options?.as === 'raw' + if (isRawType || isRawAssert) { + if (isRawAssert) { + logger.warn( + colors.yellow( + colors.bold( + "(!) import.meta.glob('...', { assert: { type: 'raw' }}) is deprecated. Use import.meta.glob('...', { as: 'raw' }) instead." + ) + ) + ) + } + query.raw = true + } + try { + return transformGlob( + source, + pos, + importer, + importIndex, + endIndex, + query, + userPattern, + root, + normalizeUrl, + resolve, + preload + ) + } catch (error) { + throw err(error) + } +} + +export async function transformDynamicImportGlob( + ctx: TransformPluginContext, + source: string, + expStart: number, + expEnd: number, + importer: string, + start: number, + end: number, + root: string, + normalizeUrl?: (url: string, pos: number) => Promise<[string, string]>, + resolve?: (url: string, importer?: string) => Promise, + preload = false +): Promise<{ + importsString: string + imports: string[] + exp: string + endIndex: number + isEager: boolean + pattern: string + rawPattern: string + base: string +} | null> { + const err = (msg: string) => { + const e = new Error(`Invalid dynamic import syntax: ${msg}`) + ;(e as any).pos = start + return e + } + const original = source.slice(expStart, expEnd) + const filename = source.slice(start + 1, end - 1) + const [rawPattern, _] = filename.split('?') + const rawQuery = parseRequest(filename) + const query: DynamicImportRequest = {} + const ast = (ctx.parse(original) as any).body[0].expression + + const userPattern = dynamicImportToGlob(ast.source, rawPattern) + + if (!userPattern) { + return null + } + + if (rawQuery?.raw) { + query.raw = true + } + + try { + return { + rawPattern, + ...(await transformGlob( + source, + start, + importer, + expStart, + expEnd, + query, + userPattern, + root, + normalizeUrl, + resolve, + preload + )) + } + } catch (error) { + throw err(error) + } +} + const enum LexerState { inCall, inSingleQuoteString, diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts new file mode 100644 index 00000000000000..6afd73cc443933 --- /dev/null +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -0,0 +1,113 @@ +import MagicString from 'magic-string' +import { init, parse as parseImports } from 'es-module-lexer' +import type { ImportSpecifier } from 'es-module-lexer' +import type { Plugin } from '../plugin' +import type { ResolvedConfig } from '../config' +import { transformDynamicImportGlob } from '../importGlob' +import { createFilter } from '@rollup/pluginutils' + +export function dynamicImportVars(config: ResolvedConfig): Plugin { + const resolve = config.createResolver({ + preferRelative: true, + tryIndex: false, + extensions: [] + }) + const { include, exclude, warnOnError } = + config.build.dynamicImportVarsOptions + const filter = createFilter(include, exclude) + + return { + name: 'vite:dynamic-import-vars', + + async transform(source, importer) { + if ( + !filter(importer) || + (importer.includes('node_modules') && + !source.includes('import.meta.glob')) + ) { + return + } + + await init + + let imports: readonly ImportSpecifier[] = [] + try { + imports = parseImports(source)[0] + } catch (e: any) { + this.error(e, e.idx) + } + + if (!imports.length) { + return null + } + + let s: MagicString | undefined + let importIndex = 0 + for (let index = 0; index < imports.length; index++) { + const { + s: start, + e: end, + ss: expStart, + se: expEnd, + d: dynamicIndex + } = imports[index] + + if (dynamicIndex === -1 || source[start] !== '`') { + continue + } + + s ||= new MagicString(source) + let result + try { + result = await transformDynamicImportGlob( + this, + source, + expStart, + expEnd, + importer, + start, + end, + config.root, + undefined, + resolve + ) + } catch (error) { + if (warnOnError) { + this.warn(error) + } else { + this.error(error) + } + } + + if (!result) { + continue + } + + const { rawPattern, exp } = result + + s.prepend(`function __variableDynamicImportRuntime_${importIndex}_(path) { + const glob = ${exp} + + return glob[path] ?? new Promise((resolve, reject) => { + (typeof queueMicrotask === 'function' ? queueMicrotask : setTimeout)( + reject.bind(null, new Error("Unknown variable dynamic import: " + path)) + ); + }) + }\n`) + s.overwrite( + expStart, + expEnd, + `__variableDynamicImportRuntime_${importIndex}_(\`${rawPattern}\`)` + ) + importIndex++ + } + + if (s) { + return { + code: s.toString(), + map: config.build.sourcemap ? s.generateMap({ hires: true }) : null + } + } + } + } +} diff --git a/packages/vite/types/shims.d.ts b/packages/vite/types/shims.d.ts index 68aa799cb6a863..25e0aca7e2bb07 100644 --- a/packages/vite/types/shims.d.ts +++ b/packages/vite/types/shims.d.ts @@ -59,6 +59,7 @@ declare module 'postcss-modules' { declare module '@rollup/plugin-dynamic-import-vars' { import type { Plugin } from 'rollup' + import type { walk } from 'estree-walker' interface Options { include?: string | RegExp | (string | RegExp)[] @@ -68,6 +69,7 @@ declare module '@rollup/plugin-dynamic-import-vars' { const p: (o?: Options) => Plugin export default p + export function dynamicImportToGlob(ast: any, source: string): null | string } declare module 'rollup-plugin-web-worker-loader' { From cc59a3b56a405324411c2432eb6955a751b1d84e Mon Sep 17 00:00:00 2001 From: yoho Date: Fri, 15 Apr 2022 23:30:50 +0800 Subject: [PATCH 02/30] fix: types --- packages/vite/src/node/importGlob.ts | 2 +- packages/vite/types/shims.d.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/vite/src/node/importGlob.ts b/packages/vite/src/node/importGlob.ts index 7d1ec3a699557a..c8c34fcc3c3b91 100644 --- a/packages/vite/src/node/importGlob.ts +++ b/packages/vite/src/node/importGlob.ts @@ -263,7 +263,7 @@ export async function transformDynamicImportGlob( const query: DynamicImportRequest = {} const ast = (ctx.parse(original) as any).body[0].expression - const userPattern = dynamicImportToGlob(ast.source, rawPattern) + const userPattern = dynamicImportToGlob(ast.source, rawPattern as any) if (!userPattern) { return null diff --git a/packages/vite/types/shims.d.ts b/packages/vite/types/shims.d.ts index 25e0aca7e2bb07..8801ddfb4dd99c 100644 --- a/packages/vite/types/shims.d.ts +++ b/packages/vite/types/shims.d.ts @@ -59,7 +59,6 @@ declare module 'postcss-modules' { declare module '@rollup/plugin-dynamic-import-vars' { import type { Plugin } from 'rollup' - import type { walk } from 'estree-walker' interface Options { include?: string | RegExp | (string | RegExp)[] From 6d2ec2cb06c1dccfff949f9a87d64ea7789398d4 Mon Sep 17 00:00:00 2001 From: yoho Date: Tue, 19 Apr 2022 22:35:03 +0800 Subject: [PATCH 03/30] fix: ?raw --- packages/vite/src/node/importGlob.ts | 10 +++++----- packages/vite/src/node/plugins/dynamicImportVars.ts | 6 +----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/packages/vite/src/node/importGlob.ts b/packages/vite/src/node/importGlob.ts index c8c34fcc3c3b91..61509220eb3756 100644 --- a/packages/vite/src/node/importGlob.ts +++ b/packages/vite/src/node/importGlob.ts @@ -258,18 +258,18 @@ export async function transformDynamicImportGlob( } const original = source.slice(expStart, expEnd) const filename = source.slice(start + 1, end - 1) - const [rawPattern, _] = filename.split('?') const rawQuery = parseRequest(filename) const query: DynamicImportRequest = {} const ast = (ctx.parse(original) as any).body[0].expression - const userPattern = dynamicImportToGlob(ast.source, rawPattern as any) - - if (!userPattern) { + const userPatternQuery = dynamicImportToGlob(ast.source, filename) + if (!userPatternQuery) { return null } + const [userPattern] = userPatternQuery.split('?', 2) + const [rawPattern] = filename.split('?', 2) - if (rawQuery?.raw) { + if (rawQuery?.raw !== undefined) { query.raw = true } diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index 6afd73cc443933..fd6c4b975faa4f 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -20,11 +20,7 @@ export function dynamicImportVars(config: ResolvedConfig): Plugin { name: 'vite:dynamic-import-vars', async transform(source, importer) { - if ( - !filter(importer) || - (importer.includes('node_modules') && - !source.includes('import.meta.glob')) - ) { + if (!filter(importer)) { return } From a58c98d29183f17a14eee6c3ef7570de71e601c5 Mon Sep 17 00:00:00 2001 From: yoho Date: Tue, 19 Apr 2022 22:48:34 +0800 Subject: [PATCH 04/30] fix: dynamic import runtime helper --- packages/vite/src/node/plugins/dynamicImportVars.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index fd6c4b975faa4f..9151fb5ec7a190 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -83,8 +83,11 @@ export function dynamicImportVars(config: ResolvedConfig): Plugin { s.prepend(`function __variableDynamicImportRuntime_${importIndex}_(path) { const glob = ${exp} - - return glob[path] ?? new Promise((resolve, reject) => { + const v = glob[path] + if (v) { + return typeof v === 'function' ? v() : v + } + return new Promise((resolve, reject) => { (typeof queueMicrotask === 'function' ? queueMicrotask : setTimeout)( reject.bind(null, new Error("Unknown variable dynamic import: " + path)) ); From 5cbc0a98ea7206b17d4f25a0dcccc1ed31dcd579 Mon Sep 17 00:00:00 2001 From: yoho Date: Tue, 19 Apr 2022 22:57:10 +0800 Subject: [PATCH 05/30] test: error --- packages/vite/src/node/importGlob.ts | 2 +- packages/vite/types/shims.d.ts | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/vite/src/node/importGlob.ts b/packages/vite/src/node/importGlob.ts index 61509220eb3756..5dc6485474fa2c 100644 --- a/packages/vite/src/node/importGlob.ts +++ b/packages/vite/src/node/importGlob.ts @@ -262,7 +262,7 @@ export async function transformDynamicImportGlob( const query: DynamicImportRequest = {} const ast = (ctx.parse(original) as any).body[0].expression - const userPatternQuery = dynamicImportToGlob(ast.source, filename) + const userPatternQuery = dynamicImportToGlob(ast.source, filename as any) if (!userPatternQuery) { return null } diff --git a/packages/vite/types/shims.d.ts b/packages/vite/types/shims.d.ts index 8801ddfb4dd99c..d62252050acefc 100644 --- a/packages/vite/types/shims.d.ts +++ b/packages/vite/types/shims.d.ts @@ -59,6 +59,7 @@ declare module 'postcss-modules' { declare module '@rollup/plugin-dynamic-import-vars' { import type { Plugin } from 'rollup' + import type { BaseNode } from 'estree' interface Options { include?: string | RegExp | (string | RegExp)[] @@ -68,7 +69,10 @@ declare module '@rollup/plugin-dynamic-import-vars' { const p: (o?: Options) => Plugin export default p - export function dynamicImportToGlob(ast: any, source: string): null | string + export function dynamicImportToGlob( + ast: BaseNode, + source: string + ): null | string } declare module 'rollup-plugin-web-worker-loader' { From 9228c4819b57bdb688ddda8ee43570e72f325b2f Mon Sep 17 00:00:00 2001 From: yoho Date: Tue, 19 Apr 2022 23:49:55 +0800 Subject: [PATCH 06/30] fix: type error --- packages/vite/package.json | 2 +- packages/vite/src/node/importGlob.ts | 2 +- pnpm-lock.yaml | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/vite/package.json b/packages/vite/package.json index adf73956a5c33a..3187b83259b767 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -58,7 +58,7 @@ "@jridgewell/trace-mapping": "^0.3.4", "@rollup/plugin-alias": "^3.1.9", "@rollup/plugin-commonjs": "^21.0.3", - "@rollup/plugin-dynamic-import-vars": "^1.4.2", + "@rollup/plugin-dynamic-import-vars": "^1.4.3", "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "13.1.3", "@rollup/plugin-typescript": "^8.3.1", diff --git a/packages/vite/src/node/importGlob.ts b/packages/vite/src/node/importGlob.ts index 5dc6485474fa2c..61509220eb3756 100644 --- a/packages/vite/src/node/importGlob.ts +++ b/packages/vite/src/node/importGlob.ts @@ -262,7 +262,7 @@ export async function transformDynamicImportGlob( const query: DynamicImportRequest = {} const ast = (ctx.parse(original) as any).body[0].expression - const userPatternQuery = dynamicImportToGlob(ast.source, filename as any) + const userPatternQuery = dynamicImportToGlob(ast.source, filename) if (!userPatternQuery) { return null } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fbc05e51fbfc7a..77e7cd0bf9ec40 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -827,7 +827,7 @@ importers: '@jridgewell/trace-mapping': ^0.3.4 '@rollup/plugin-alias': ^3.1.9 '@rollup/plugin-commonjs': ^21.0.3 - '@rollup/plugin-dynamic-import-vars': ^1.4.2 + '@rollup/plugin-dynamic-import-vars': ^1.4.3 '@rollup/plugin-json': ^4.1.0 '@rollup/plugin-node-resolve': 13.1.3 '@rollup/plugin-typescript': ^8.3.1 @@ -905,7 +905,7 @@ importers: '@jridgewell/trace-mapping': 0.3.4 '@rollup/plugin-alias': 3.1.9_rollup@2.62.0 '@rollup/plugin-commonjs': 21.0.3_rollup@2.62.0 - '@rollup/plugin-dynamic-import-vars': 1.4.2_rollup@2.62.0 + '@rollup/plugin-dynamic-import-vars': 1.4.3_rollup@2.62.0 '@rollup/plugin-json': 4.1.0_rollup@2.62.0 '@rollup/plugin-node-resolve': 13.1.3_rollup@2.62.0 '@rollup/plugin-typescript': 8.3.1_7c5ff569c0887b4f0035eb7cb6988163 @@ -2360,8 +2360,8 @@ packages: rollup: 2.62.0 dev: true - /@rollup/plugin-dynamic-import-vars/1.4.2_rollup@2.62.0: - resolution: {integrity: sha512-SEaS9Pf0RyaZ/oJ1knLZT+Fu0X6DlyTfUcoE7XKkiKJjNaB+8SLoHmDVRhomo5RpWHPyd+B00G/bE5R5+Q+HEg==} + /@rollup/plugin-dynamic-import-vars/1.4.3_rollup@2.62.0: + resolution: {integrity: sha512-VYP9BBVI0pcYpLp/DkFT8YP+EmqmWFMmWXoTObDH6OouERxJyPsIj0tC3HxhjNBOKgcRc7eV75IQItzELt7QSg==} engines: {node: '>= 10.0.0'} peerDependencies: rollup: ^1.20.0||^2.0.0 From 09cc6546a32d0ab9dd9dd2b32c4a526138238915 Mon Sep 17 00:00:00 2001 From: yoho Date: Wed, 20 Apr 2022 12:49:58 +0800 Subject: [PATCH 07/30] test: resolve path TODO --- packages/playground/dynamic-import/alias/hello.js | 3 +++ packages/playground/dynamic-import/alias/hi.js | 3 +++ packages/playground/dynamic-import/nested/index.js | 5 +++++ packages/playground/dynamic-import/vite.config.js | 12 +++++++++--- 4 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 packages/playground/dynamic-import/alias/hello.js create mode 100644 packages/playground/dynamic-import/alias/hi.js diff --git a/packages/playground/dynamic-import/alias/hello.js b/packages/playground/dynamic-import/alias/hello.js new file mode 100644 index 00000000000000..67900ef0999962 --- /dev/null +++ b/packages/playground/dynamic-import/alias/hello.js @@ -0,0 +1,3 @@ +export function hello() { + return 'hello' +} diff --git a/packages/playground/dynamic-import/alias/hi.js b/packages/playground/dynamic-import/alias/hi.js new file mode 100644 index 00000000000000..45d3506803b2b6 --- /dev/null +++ b/packages/playground/dynamic-import/alias/hi.js @@ -0,0 +1,3 @@ +export function hi() { + return 'hi' +} diff --git a/packages/playground/dynamic-import/nested/index.js b/packages/playground/dynamic-import/nested/index.js index aa65d1f557d53b..aa7ff4e3c4cc64 100644 --- a/packages/playground/dynamic-import/nested/index.js +++ b/packages/playground/dynamic-import/nested/index.js @@ -81,3 +81,8 @@ console.log(mod) const base = '' const glob = import.meta.glob(`./*.js`, { as: 'raw' }) console.log(glob) + +// TODO +// const resolvePath = 'hello' +// const resplvePathMod = import(`@/${resolvePath}.js`) +// console.log(resplvePathMod) diff --git a/packages/playground/dynamic-import/vite.config.js b/packages/playground/dynamic-import/vite.config.js index 010e47d6308d30..50b90639fddd7f 100644 --- a/packages/playground/dynamic-import/vite.config.js +++ b/packages/playground/dynamic-import/vite.config.js @@ -1,7 +1,8 @@ const fs = require('fs') const path = require('path') +const vite = require('vite') -module.exports = { +module.exports = vite.defineConfig({ plugins: [ { name: 'copy', @@ -20,5 +21,10 @@ module.exports = { ) } } - ] -} + ], + resolve: { + alias: { + '@': path.resolve(__dirname, 'alias') + } + } +}) From b505f423ffe5a10f560c3402b0cce5192345e7fd Mon Sep 17 00:00:00 2001 From: yoho Date: Thu, 21 Apr 2022 00:37:24 +0800 Subject: [PATCH 08/30] feat: support dynamic import path alias --- .../playground/dynamic-import/nested/hello.js | 3 + .../playground/dynamic-import/nested/index.js | 28 ++++--- packages/vite/src/node/importGlob.ts | 69 ++++++++++++++---- .../src/node/plugins/dynamicImportVars.ts | 3 +- .../vite/src/node/plugins/importAnalysis.ts | 73 +++++++++++++++---- 5 files changed, 135 insertions(+), 41 deletions(-) create mode 100644 packages/playground/dynamic-import/nested/hello.js diff --git a/packages/playground/dynamic-import/nested/hello.js b/packages/playground/dynamic-import/nested/hello.js new file mode 100644 index 00000000000000..67900ef0999962 --- /dev/null +++ b/packages/playground/dynamic-import/nested/hello.js @@ -0,0 +1,3 @@ +export function hello() { + return 'hello' +} diff --git a/packages/playground/dynamic-import/nested/index.js b/packages/playground/dynamic-import/nested/index.js index aa7ff4e3c4cc64..c1647d8b4a3d6e 100644 --- a/packages/playground/dynamic-import/nested/index.js +++ b/packages/playground/dynamic-import/nested/index.js @@ -74,15 +74,19 @@ function text(el, text) { document.querySelector(el).textContent = text } -const variable = 'mxd' -const mod = import(`../${variable}.js?raw`) -console.log(mod) - -const base = '' -const glob = import.meta.glob(`./*.js`, { as: 'raw' }) -console.log(glob) - -// TODO -// const resolvePath = 'hello' -// const resplvePathMod = import(`@/${resolvePath}.js`) -// console.log(resplvePathMod) +const base = 'hello' + +import(`../alias/${base}.js`).then((mod) => { + console.log('dynamic-import-with-vars', mod) +}) + +import(`@/${base}.js`).then((mod) => { + console.log('dynamic-import-with-vars-alias', mod) +}) + +import(`../alias/${base}.js?raw`).then((mod) => { + console.log('dynamic-import-with-vars-?raw', mod) +}) + +const glob = import.meta.glob(`../alias/*.js`, { as: 'raw' }) +console.log('dynamic-import-import.meta.glob-vars', glob) diff --git a/packages/vite/src/node/importGlob.ts b/packages/vite/src/node/importGlob.ts index 61509220eb3756..db5d35f0dc2297 100644 --- a/packages/vite/src/node/importGlob.ts +++ b/packages/vite/src/node/importGlob.ts @@ -16,10 +16,11 @@ import { normalizePath, parseRequest } from './utils' -import type { RollupError, TransformPluginContext } from 'rollup' +import type { RollupError } from 'rollup' import type { Logger } from '.' import colors from 'picocolors' import { dynamicImportToGlob } from '@rollup/plugin-dynamic-import-vars' +import { parse as parseJS } from 'acorn' interface GlobParams { base: string @@ -42,6 +43,44 @@ interface DynamicImportRequest { raw?: boolean } +interface DynamicImportPattern { + query: DynamicImportRequest + userPattern: string + rawPattern: string +} + +export function parseDynamicImportPattern( + strings: string +): DynamicImportPattern | null { + const filename = strings.slice(1, -1) + const rawQuery = parseRequest(filename) + const query: DynamicImportRequest = {} + const ast = ( + parseJS(strings, { + ecmaVersion: 'latest', + sourceType: 'module' + }) as any + ).body[0].expression + + const userPatternQuery = dynamicImportToGlob(ast, filename) + if (!userPatternQuery) { + return null + } + + const [userPattern] = userPatternQuery.split('?', 2) + const [rawPattern] = filename.split('?', 2) + + if (rawQuery?.raw !== undefined) { + query.raw = true + } + + return { + query, + userPattern, + rawPattern + } +} + function formatGlobRelativePattern(base: string, pattern: string): GlobParams { let parentDepth = 0 while (pattern.startsWith('../')) { @@ -230,7 +269,6 @@ export async function transformImportGlob( } export async function transformDynamicImportGlob( - ctx: TransformPluginContext, source: string, expStart: number, expEnd: number, @@ -256,22 +294,25 @@ export async function transformDynamicImportGlob( ;(e as any).pos = start return e } - const original = source.slice(expStart, expEnd) - const filename = source.slice(start + 1, end - 1) - const rawQuery = parseRequest(filename) - const query: DynamicImportRequest = {} - const ast = (ctx.parse(original) as any).body[0].expression + let fileName = source.slice(start, end) - const userPatternQuery = dynamicImportToGlob(ast.source, filename) - if (!userPatternQuery) { - return null + if (fileName[1] !== '.' && fileName[1] !== '/' && resolve) { + const resolvedFileName = await resolve(fileName.slice(1, -1), importer) + if (!resolvedFileName) { + return null + } + const relativeFileName = path.relative( + path.dirname(importer), + resolvedFileName + ) + fileName = `\`${relativeFileName}\`` } - const [userPattern] = userPatternQuery.split('?', 2) - const [rawPattern] = filename.split('?', 2) - if (rawQuery?.raw !== undefined) { - query.raw = true + const dynamicImportPattern = parseDynamicImportPattern(fileName) + if (!dynamicImportPattern) { + return null } + const { query, rawPattern, userPattern } = dynamicImportPattern try { return { diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index 9151fb5ec7a190..22685c22ec7a37 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -56,7 +56,6 @@ export function dynamicImportVars(config: ResolvedConfig): Plugin { let result try { result = await transformDynamicImportGlob( - this, source, expStart, expEnd, @@ -85,7 +84,7 @@ export function dynamicImportVars(config: ResolvedConfig): Plugin { const glob = ${exp} const v = glob[path] if (v) { - return typeof v === 'function' ? v() : v + return typeof v === 'function' ? v() : Promise.resolve(v) } return new Promise((resolve, reject) => { (typeof queueMicrotask === 'function' ? queueMicrotask : setTimeout)( diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index 31e9cd76faa8a0..1cf70d5a4be1e5 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -42,7 +42,7 @@ import type { ViteDevServer } from '..' import { checkPublicFile } from './asset' import { parse as parseJS } from 'acorn' import type { Node } from 'estree' -import { transformImportGlob } from '../importGlob' +import { transformDynamicImportGlob, transformImportGlob } from '../importGlob' import { makeLegalIdentifier } from '@rollup/pluginutils' import { shouldExternalizeForSSR } from '../ssr/ssrExternal' import { performance } from 'perf_hooks' @@ -534,19 +534,66 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { .replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '') .trim() if (!hasViteIgnore && !isSupportedDynamicImport(url)) { - this.warn( - `\n` + - colors.cyan(importerModule.file) + - `\n` + - generateCodeFrame(source, start) + - `\nThe above dynamic import cannot be analyzed by vite.\n` + - `See ${colors.blue( - `https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations` - )} ` + - `for supported dynamic import formats. ` + - `If this is intended to be left as-is, you can use the ` + - `/* @vite-ignore */ comment inside the import() call to suppress this warning.\n` + const glob = await transformDynamicImportGlob( + source, + expStart, + expEnd, + importer, + start, + end, + config.root, + undefined, + resolve ) + if (glob) { + const { exp, imports, rawPattern } = glob + str() + .prepend(`function __variableDynamicImportRuntime_${index}_(path) { + const glob = ${exp} + const v = glob[path] + if (v) { + return typeof v === 'function' ? v() : Promise.resolve(v) + } + return new Promise((resolve, reject) => { + (typeof queueMicrotask === 'function' ? queueMicrotask : setTimeout)( + reject.bind(null, new Error("Unknown variable dynamic import: " + path)) + ); + }) + }\n`) + str().overwrite( + expStart, + expEnd, + `__variableDynamicImportRuntime_${index}_(\`${rawPattern}\`)` + ) + imports.forEach((url) => { + url = url.replace(base, '/') + importedUrls.add(url) + }) + if (!(importerModule.file! in server._globImporters)) { + server._globImporters[importerModule.file!] = { + module: importerModule, + importGlobs: [] + } + } + server._globImporters[importerModule.file!].importGlobs.push({ + base, + pattern: rawPattern + }) + } else { + this.warn( + `\n` + + colors.cyan(importerModule.file) + + `\n` + + generateCodeFrame(source, start) + + `\nThe above dynamic import cannot be analyzed by vite.\n` + + `See ${colors.blue( + `https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations` + )} ` + + `for supported dynamic import formats. ` + + `If this is intended to be left as-is, you can use the ` + + `/* @vite-ignore */ comment inside the import() call to suppress this warning.\n` + ) + } } if ( !/^('.*'|".*"|`.*`)$/.test(url) || From 1bf029e166e89a6a2a74aa81e7558672510e2458 Mon Sep 17 00:00:00 2001 From: yoho Date: Thu, 21 Apr 2022 11:25:18 +0800 Subject: [PATCH 09/30] feat: virtual module for dynamicImportHelper --- packages/vite/src/node/build.ts | 4 +- .../src/node/plugins/dynamicImportVars.ts | 56 +++++++++---- .../vite/src/node/plugins/importAnalysis.ts | 80 ++++++++++--------- packages/vite/src/node/plugins/index.ts | 2 + 4 files changed, 86 insertions(+), 56 deletions(-) diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts index 71bad8bd14b530..31e88e7055baea 100644 --- a/packages/vite/src/node/build.ts +++ b/packages/vite/src/node/build.ts @@ -26,7 +26,7 @@ import { copyDir, emptyDir, lookupFile, normalizePath } from './utils' import { manifestPlugin } from './plugins/manifest' import commonjsPlugin from '@rollup/plugin-commonjs' import type { RollupCommonJSOptions } from 'types/commonjs' -import { dynamicImportVars } from './plugins/dynamicImportVars' +import { dynamicImportVarsPlugin } from './plugins/dynamicImportVars' import type { RollupDynamicImportVarsOptions } from 'types/dynamicImportVars' import type { Logger } from './logger' import type { TransformOptions } from 'esbuild' @@ -313,7 +313,7 @@ export function resolveBuildPlugins(config: ResolvedConfig): { watchPackageDataPlugin(config), commonjsPlugin(options.commonjsOptions), dataURIPlugin(), - dynamicImportVars(config), + dynamicImportVarsPlugin(config), assetImportMetaUrlPlugin(config), ...(options.rollupOptions.plugins ? (options.rollupOptions.plugins.filter(Boolean) as Plugin[]) diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index 22685c22ec7a37..31951691dddcff 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -6,7 +6,37 @@ import type { ResolvedConfig } from '../config' import { transformDynamicImportGlob } from '../importGlob' import { createFilter } from '@rollup/pluginutils' -export function dynamicImportVars(config: ResolvedConfig): Plugin { +const dynamicImportHelper = (glob: Record, path: string) => { + const v = glob[path] + if (v) { + return typeof v === 'function' ? v() : Promise.resolve(v) + } + return new Promise((_, reject) => { + ;(typeof queueMicrotask === 'function' ? queueMicrotask : setTimeout)( + reject.bind(null, new Error('Unknown variable dynamic import: ' + path)) + ) + }) +} +export const dynamicImportHelperId = '/@vite/dynamic-import-helper' + +export function dynamicImportHelperPlugin(): Plugin { + return { + name: 'vite:dynamic-import-helper', + resolveId(id) { + if (id === dynamicImportHelperId) { + return id + } + }, + + load(id) { + if (id === dynamicImportHelperId) { + return 'export default' + dynamicImportHelper.toString() + } + } + } +} + +export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin { const resolve = config.createResolver({ preferRelative: true, tryIndex: false, @@ -38,7 +68,8 @@ export function dynamicImportVars(config: ResolvedConfig): Plugin { } let s: MagicString | undefined - let importIndex = 0 + let needDynamicImportHelper = false + for (let index = 0; index < imports.length; index++) { const { s: start, @@ -80,27 +111,20 @@ export function dynamicImportVars(config: ResolvedConfig): Plugin { const { rawPattern, exp } = result - s.prepend(`function __variableDynamicImportRuntime_${importIndex}_(path) { - const glob = ${exp} - const v = glob[path] - if (v) { - return typeof v === 'function' ? v() : Promise.resolve(v) - } - return new Promise((resolve, reject) => { - (typeof queueMicrotask === 'function' ? queueMicrotask : setTimeout)( - reject.bind(null, new Error("Unknown variable dynamic import: " + path)) - ); - }) - }\n`) + needDynamicImportHelper = true s.overwrite( expStart, expEnd, - `__variableDynamicImportRuntime_${importIndex}_(\`${rawPattern}\`)` + `__variableDynamicImportRuntimeHelper(${exp}, \`${rawPattern}\`)` ) - importIndex++ } if (s) { + if (needDynamicImportHelper) { + s.prepend( + `import __variableDynamicImportRuntimeHelper from "${dynamicImportHelperId}";` + ) + } return { code: s.toString(), map: config.build.sourcemap ? s.generateMap({ hires: true }) : null diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index 1cf70d5a4be1e5..6ab463a20b4819 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -52,6 +52,7 @@ import { getDepsCacheDir, optimizedDepNeedsInterop } from '../optimizer' +import { dynamicImportHelperId } from './dynamicImportVars' const isDebug = !!process.env.DEBUG const debug = createDebugger('vite:import-analysis') @@ -183,6 +184,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { let isSelfAccepting = false let hasEnv = false let needQueryInjectHelper = false + let needDynamicImportHelper = false let s: MagicString | undefined const str = () => s || (s = new MagicString(source)) const importedUrls = new Set() @@ -533,37 +535,31 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { const url = rawUrl .replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '') .trim() - if (!hasViteIgnore && !isSupportedDynamicImport(url)) { - const glob = await transformDynamicImportGlob( - source, - expStart, - expEnd, - importer, - start, - end, - config.root, - undefined, - resolve - ) + if (!isSupportedDynamicImport(url)) { + let glob + try { + glob = await transformDynamicImportGlob( + source, + expStart, + expEnd, + importer, + start, + end, + config.root, + undefined, + resolve + ) + } catch (e) { + this.error(e) + } + if (glob) { const { exp, imports, rawPattern } = glob - str() - .prepend(`function __variableDynamicImportRuntime_${index}_(path) { - const glob = ${exp} - const v = glob[path] - if (v) { - return typeof v === 'function' ? v() : Promise.resolve(v) - } - return new Promise((resolve, reject) => { - (typeof queueMicrotask === 'function' ? queueMicrotask : setTimeout)( - reject.bind(null, new Error("Unknown variable dynamic import: " + path)) - ); - }) - }\n`) + needDynamicImportHelper = true str().overwrite( expStart, expEnd, - `__variableDynamicImportRuntime_${index}_(\`${rawPattern}\`)` + `__variableDynamicImportRuntimeHelper(${exp}, \`${rawPattern}\`)` ) imports.forEach((url) => { url = url.replace(base, '/') @@ -580,19 +576,21 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { pattern: rawPattern }) } else { - this.warn( - `\n` + - colors.cyan(importerModule.file) + + if (!hasViteIgnore) { + this.warn( `\n` + - generateCodeFrame(source, start) + - `\nThe above dynamic import cannot be analyzed by vite.\n` + - `See ${colors.blue( - `https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations` - )} ` + - `for supported dynamic import formats. ` + - `If this is intended to be left as-is, you can use the ` + - `/* @vite-ignore */ comment inside the import() call to suppress this warning.\n` - ) + colors.cyan(importerModule.file) + + `\n` + + generateCodeFrame(source, start) + + `\nThe above dynamic import cannot be analyzed by vite.\n` + + `See ${colors.blue( + `https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations` + )} ` + + `for supported dynamic import formats. ` + + `If this is intended to be left as-is, you can use the ` + + `/* @vite-ignore */ comment inside the import() call to suppress this warning.\n` + ) + } } } if ( @@ -653,6 +651,12 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { ) } + if (needDynamicImportHelper) { + str().prepend( + `import __variableDynamicImportRuntimeHelper from "${dynamicImportHelperId}";` + ) + } + // normalize and rewrite accepted urls const normalizedAcceptedUrls = new Set() for (const { url, start, end } of acceptedUrls) { diff --git a/packages/vite/src/node/plugins/index.ts b/packages/vite/src/node/plugins/index.ts index 2d34b99aebf1c5..7d2ce7531e8d62 100644 --- a/packages/vite/src/node/plugins/index.ts +++ b/packages/vite/src/node/plugins/index.ts @@ -19,6 +19,7 @@ import { ssrRequireHookPlugin } from './ssrRequireHook' import { workerImportMetaUrlPlugin } from './workerImportMetaUrl' import { ensureWatchPlugin } from './ensureWatch' import { metadataPlugin } from './metadata' +import { dynamicImportHelperPlugin } from './dynamicImportVars' export async function resolvePlugins( config: ResolvedConfig, @@ -51,6 +52,7 @@ export async function resolvePlugins( ssrConfig: config.ssr, asSrc: true }), + dynamicImportHelperPlugin(), isBuild ? null : optimizedDepsPlugin(), htmlInlineProxyPlugin(config), cssPlugin(config), From fc37bdc1fb817983b91d556b00dd479447362589 Mon Sep 17 00:00:00 2001 From: yoho Date: Thu, 21 Apr 2022 12:35:07 +0800 Subject: [PATCH 10/30] fix: normal path --- packages/vite/src/node/importGlob.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vite/src/node/importGlob.ts b/packages/vite/src/node/importGlob.ts index db5d35f0dc2297..c8f86491ffbc1f 100644 --- a/packages/vite/src/node/importGlob.ts +++ b/packages/vite/src/node/importGlob.ts @@ -301,7 +301,7 @@ export async function transformDynamicImportGlob( if (!resolvedFileName) { return null } - const relativeFileName = path.relative( + const relativeFileName = path.posix.relative( path.dirname(importer), resolvedFileName ) From 0d556c63ab326cb3d83f9e7c191e5bc4b5c00357 Mon Sep 17 00:00:00 2001 From: yoho Date: Thu, 21 Apr 2022 13:02:00 +0800 Subject: [PATCH 11/30] feat: test --- .../__tests__/dynamic-import.spec.ts | 24 +++++++++++++++++++ packages/playground/dynamic-import/index.html | 14 +++++++++++ .../playground/dynamic-import/nested/index.js | 9 +++---- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/packages/playground/dynamic-import/__tests__/dynamic-import.spec.ts b/packages/playground/dynamic-import/__tests__/dynamic-import.spec.ts index c7157ef4652ec6..46af79300c7004 100644 --- a/packages/playground/dynamic-import/__tests__/dynamic-import.spec.ts +++ b/packages/playground/dynamic-import/__tests__/dynamic-import.spec.ts @@ -59,3 +59,27 @@ test('should load dynamic import with css', async () => { true ) }) + +test('should load dynamic import with vars', async () => { + await untilUpdated( + () => page.textContent('.dynamic-import-with-vars'), + 'hello', + true + ) +}) + +test('should load dynamic import with vars alias', async () => { + await untilUpdated( + () => page.textContent('.dynamic-import-with-vars-alias'), + 'hello', + true + ) +}) + +test('should load dynamic import with vars raw', async () => { + await untilUpdated( + () => page.textContent('.dynamic-import-with-vars-raw'), + 'export function hello()', + true + ) +}) diff --git a/packages/playground/dynamic-import/index.html b/packages/playground/dynamic-import/index.html index c87ef2a17f48d5..5fd05298314946 100644 --- a/packages/playground/dynamic-import/index.html +++ b/packages/playground/dynamic-import/index.html @@ -9,6 +9,20 @@ +

dynamic-import-with-vars

+
todo
+ +

dynamic-import-with-vars-alias

+
todo
+ +

dynamic-import-with-vars-raw

+
todo
+
+ diff --git a/packages/playground/dynamic-import/nested/index.js b/packages/playground/dynamic-import/nested/index.js index c1647d8b4a3d6e..206012b44b29c0 100644 --- a/packages/playground/dynamic-import/nested/index.js +++ b/packages/playground/dynamic-import/nested/index.js @@ -77,16 +77,13 @@ function text(el, text) { const base = 'hello' import(`../alias/${base}.js`).then((mod) => { - console.log('dynamic-import-with-vars', mod) + text('.dynamic-import-with-vars', mod.hello()) }) import(`@/${base}.js`).then((mod) => { - console.log('dynamic-import-with-vars-alias', mod) + text('.dynamic-import-with-vars-alias', mod.hello()) }) import(`../alias/${base}.js?raw`).then((mod) => { - console.log('dynamic-import-with-vars-?raw', mod) + text('.dynamic-import-with-vars-raw', JSON.stringify(mod)) }) - -const glob = import.meta.glob(`../alias/*.js`, { as: 'raw' }) -console.log('dynamic-import-import.meta.glob-vars', glob) From 88a2e7fe4e4c5aa420e0fd5e09a8d6c422194192 Mon Sep 17 00:00:00 2001 From: yoho Date: Fri, 6 May 2022 09:16:34 +0800 Subject: [PATCH 12/30] fix: types --- packages/vite/src/node/importGlob.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/vite/src/node/importGlob.ts b/packages/vite/src/node/importGlob.ts index 7e7144a3ace7e0..afdf2dbc06bb87 100644 --- a/packages/vite/src/node/importGlob.ts +++ b/packages/vite/src/node/importGlob.ts @@ -18,7 +18,6 @@ import { } from './utils' import type { RollupError } from 'rollup' import type { Logger } from '.' -import colors from 'picocolors' import { dynamicImportToGlob } from '@rollup/plugin-dynamic-import-vars' import { parse as parseJS } from 'acorn' From a0e999ce00d1861fadb67b343e45f507d1d498c8 Mon Sep 17 00:00:00 2001 From: yoho Date: Mon, 9 May 2022 13:05:26 +0800 Subject: [PATCH 13/30] fix: bugs --- .../src/node/plugins/dynamicImportVars.ts | 77 ++++++++++++++++--- .../vite/src/node/plugins/importAnalysis.ts | 25 ++---- .../vite/src/node/plugins/importMetaGlob.ts | 27 +++++-- 3 files changed, 91 insertions(+), 38 deletions(-) diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index 7fd027e3f50203..2d005bb78b4dc5 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -1,9 +1,25 @@ +import path from 'path' import MagicString from 'magic-string' import { init, parse as parseImports } from 'es-module-lexer' import type { ImportSpecifier } from 'es-module-lexer' import type { Plugin } from '../plugin' import type { ResolvedConfig } from '../config' +import { parseRequest } from '../utils' +import { parse as parseJS } from 'acorn' import { createFilter } from '@rollup/pluginutils' +import { dynamicImportToGlob } from '@rollup/plugin-dynamic-import-vars' +import type { TransformGlobImportResult } from './importMetaGlob' +import { transformGlobImport } from './importMetaGlob' + +interface DynamicImportRequest { + as?: 'raw' +} + +interface DynamicImportPattern { + globParams: DynamicImportRequest | null + userPattern: string + rawPattern: string +} const dynamicImportHelper = (glob: Record, path: string) => { const v = glob[path] @@ -18,22 +34,50 @@ const dynamicImportHelper = (glob: Record, path: string) => { } export const dynamicImportHelperId = '/@vite/dynamic-import-helper' +export function parseDynamicImportPattern( + strings: string +): DynamicImportPattern | null { + const filename = strings.slice(1, -1) + const rawQuery = parseRequest(filename) + let globParams: DynamicImportRequest | null = null + const ast = ( + parseJS(strings, { + ecmaVersion: 'latest', + sourceType: 'module' + }) as any + ).body[0].expression + + const userPatternQuery = dynamicImportToGlob(ast, filename) + if (!userPatternQuery) { + return null + } + + const [userPattern] = userPatternQuery.split('?', 2) + const [rawPattern] = filename.split('?', 2) + + if (rawQuery?.raw !== undefined) { + globParams = { as: 'raw' } + } + + return { + globParams, + userPattern, + rawPattern + } +} + export async function transformDynamicImportGlob( source: string, + root: string, importer: string, start: number, end: number, - resolve?: (url: string, importer?: string) => Promise + resolve: (url: string, importer?: string) => Promise ): Promise<{ - exp: string + glob: TransformGlobImportResult pattern: string rawPattern: string } | null> { - const err = (msg: string) => { - const e = new Error(`Invalid dynamic import syntax: ${msg}`) - ;(e as any).pos = start - return e - } let fileName = source.slice(start, end) if (fileName[1] !== '.' && fileName[1] !== '/' && resolve) { @@ -52,12 +96,22 @@ export async function transformDynamicImportGlob( if (!dynamicImportPattern) { return null } - const { query, rawPattern, userPattern } = dynamicImportPattern + const { globParams, rawPattern, userPattern } = dynamicImportPattern + const params = globParams ? `, ${JSON.stringify(globParams)}` : '' + const exp = `import.meta.glob(${JSON.stringify(userPattern)}${params})` + const glob = await transformGlobImport( + exp, + importer, + root, + resolve, + false, + false + ) return { rawPattern, pattern: userPattern, - exp: `import.meta.glob(${JSON.stringify(userPattern)})` + glob: glob! } } @@ -130,6 +184,7 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin { try { result = await transformDynamicImportGlob( source, + config.root, importer, start, end, @@ -147,13 +202,13 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin { continue } - const { rawPattern, exp } = result + const { rawPattern, glob } = result needDynamicImportHelper = true s.overwrite( expStart, expEnd, - `__variableDynamicImportRuntimeHelper(${exp}, \`${rawPattern}\`)` + `__variableDynamicImportRuntimeHelper(${glob.s.toString()}, \`${rawPattern}\`)` ) } diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index 4113778958d383..177de1f6a3820f 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -499,10 +499,11 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { .replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '') .trim() if (!isSupportedDynamicImport(url)) { - let glob + let importGlobResult try { - glob = await transformDynamicImportGlob( + importGlobResult = await transformDynamicImportGlob( source, + config.root, importer, start, end, @@ -512,28 +513,14 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { this.error(e) } - if (glob) { - const { exp, imports, rawPattern } = glob + if (importGlobResult) { + const { glob, rawPattern } = importGlobResult needDynamicImportHelper = true str().overwrite( expStart, expEnd, - `__variableDynamicImportRuntimeHelper(${exp}, \`${rawPattern}\`)` + `__variableDynamicImportRuntimeHelper(${glob.s.toString()}, \`${rawPattern}\`)` ) - imports.forEach((url) => { - url = url.replace(base, '/') - importedUrls.add(url) - }) - if (!(importerModule.file! in server._globImporters)) { - server._globImporters[importerModule.file!] = { - module: importerModule, - importGlobs: [] - } - } - server._globImporters[importerModule.file!].importGlobs.push({ - base, - pattern: rawPattern - }) } else { if (!hasViteIgnore) { this.warn( diff --git a/packages/vite/src/node/plugins/importMetaGlob.ts b/packages/vite/src/node/plugins/importMetaGlob.ts index 20bc10f8296ed4..4f435fb35555a0 100644 --- a/packages/vite/src/node/plugins/importMetaGlob.ts +++ b/packages/vite/src/node/plugins/importMetaGlob.ts @@ -11,7 +11,7 @@ import type { ViteDevServer } from '../server' import type { ModuleNode } from '../server/moduleGraph' import type { ResolvedConfig } from '../config' import { isCSSRequest } from './css' -import type { GeneralImportGlobOptions } from '../../../types/importGlob' +import type { GeneralImportGlobOptions } from 'types/importGlob' import { normalizePath, slash } from '../utils' export interface ParsedImportGlob { @@ -168,12 +168,13 @@ export async function parseImportGlob( for (const property of arg2.properties) { if ( property.type === 'SpreadElement' || - property.key.type !== 'Identifier' + (property.key.type !== 'Identifier' && + property.key.type !== 'Literal') ) throw err('Could only use literals') - const name = property.key.name as keyof GeneralImportGlobOptions - + const name = ((property.key as any).name || + (property.key as any).value) as keyof GeneralImportGlobOptions if (name === 'query') { if (property.value.type === 'ObjectExpression') { const data: Record = {} @@ -256,13 +257,23 @@ const importPrefix = '__vite_glob_' const { basename, dirname, relative, join } = posix +export interface TransformGlobImportResult { + s: MagicString + matches: ParsedImportGlob[] + files: Set +} + +/** + * @param optimizeExport for dynamicImportVar plugin don't need to optimize export. + */ export async function transformGlobImport( code: string, id: string, root: string, resolveId: IdResolver, - restoreQueryExtension = false -) { + restoreQueryExtension = false, + optimizeExport = true +): Promise { id = slash(id) root = slash(root) const isVirtual = isVirtualModule(id) @@ -284,7 +295,7 @@ export async function transformGlobImport( } }) - if (!matches.length) return + if (!matches.length) return null const s = new MagicString(code) @@ -369,7 +380,7 @@ export async function transformGlobImport( objectProps.push(`${JSON.stringify(filePath)}: ${variableName}`) } else { let importStatement = `import(${JSON.stringify(importPath)})` - if (options.import) + if (options.import && optimizeExport) importStatement += `.then(m => m[${JSON.stringify( options.import )}])` From 9c42293bcc0f802c8bf5c6f0b6bdb5a96934fb66 Mon Sep 17 00:00:00 2001 From: yoho Date: Mon, 9 May 2022 13:16:05 +0800 Subject: [PATCH 14/30] feat: hmr --- packages/vite/src/node/plugins/importAnalysis.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index 177de1f6a3820f..8b73c88f6a920f 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -521,6 +521,14 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { expEnd, `__variableDynamicImportRuntimeHelper(${glob.s.toString()}, \`${rawPattern}\`)` ) + if (server) { + const allGlobs = glob.matches.map((i) => i.globsResolved) + server._importGlobMap.set(importer, allGlobs) + glob.files.forEach((file) => { + // update watcher + server!.watcher.add(path.posix.dirname(file)) + }) + } } else { if (!hasViteIgnore) { this.warn( From 4092cf111a3deaabda65de9f6763ef105fba2f76 Mon Sep 17 00:00:00 2001 From: yoho Date: Mon, 9 May 2022 13:18:08 +0800 Subject: [PATCH 15/30] feat: hmr --- .../vite/src/node/plugins/dynamicImportVars.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index 2d005bb78b4dc5..fc9891cf5e54c2 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -10,6 +10,7 @@ import { createFilter } from '@rollup/pluginutils' import { dynamicImportToGlob } from '@rollup/plugin-dynamic-import-vars' import type { TransformGlobImportResult } from './importMetaGlob' import { transformGlobImport } from './importMetaGlob' +import type { ViteDevServer } from '../server' interface DynamicImportRequest { as?: 'raw' @@ -141,10 +142,15 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin { const { include, exclude, warnOnError } = config.build.dynamicImportVarsOptions const filter = createFilter(include, exclude) + let server: ViteDevServer return { name: 'vite:dynamic-import-vars', + configureServer(_server) { + server = _server + }, + async transform(source, importer) { if (!filter(importer)) { return @@ -210,6 +216,14 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin { expEnd, `__variableDynamicImportRuntimeHelper(${glob.s.toString()}, \`${rawPattern}\`)` ) + if (server) { + const allGlobs = glob.matches.map((i) => i.globsResolved) + server._importGlobMap.set(importer, allGlobs) + glob.files.forEach((file) => { + // update watcher + server!.watcher.add(path.posix.dirname(file)) + }) + } } if (s) { From eab35a08033c93f0d9de9f3a0c976a59626b0776 Mon Sep 17 00:00:00 2001 From: yoho Date: Mon, 9 May 2022 14:49:15 +0800 Subject: [PATCH 16/30] feat: snapshot --- .../__snapshots__/parse.test.ts.snap | 29 +++++++++++++++++ .../plugins/dynamicImportVar/mods/hello.js | 3 ++ .../plugins/dynamicImportVar/mods/hi.js | 3 ++ .../plugins/dynamicImportVar/parse.test.ts | 31 +++++++++++++++++++ .../src/node/plugins/dynamicImportVars.ts | 28 ++++++++--------- .../vite/src/node/plugins/importAnalysis.ts | 8 ++--- 6 files changed, 82 insertions(+), 20 deletions(-) create mode 100644 packages/vite/src/node/__tests__/plugins/dynamicImportVar/__snapshots__/parse.test.ts.snap create mode 100644 packages/vite/src/node/__tests__/plugins/dynamicImportVar/mods/hello.js create mode 100644 packages/vite/src/node/__tests__/plugins/dynamicImportVar/mods/hi.js create mode 100644 packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.test.ts diff --git a/packages/vite/src/node/__tests__/plugins/dynamicImportVar/__snapshots__/parse.test.ts.snap b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/__snapshots__/parse.test.ts.snap new file mode 100644 index 00000000000000..6e9485057fd6ea --- /dev/null +++ b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/__snapshots__/parse.test.ts.snap @@ -0,0 +1,29 @@ +// Vitest Snapshot v1 + +exports[`parse positives > alias path 1`] = ` +"__variableDynamicImportRuntimeHelper({ +\\"./mods/hello.js\\": () => import(\\"./mods/hello.js\\"), +\\"./mods/hi.js\\": () => import(\\"./mods/hi.js\\") +}, \`./mods/\${base}.js\`)" +`; + +exports[`parse positives > basic 1`] = ` +"__variableDynamicImportRuntimeHelper({ +\\"./mods/hello.js\\": () => import(\\"./mods/hello.js\\"), +\\"./mods/hi.js\\": () => import(\\"./mods/hi.js\\") +}, \`./mods/\${base}.js\`)" +`; + +exports[`parse positives > with query raw 1`] = ` +"__variableDynamicImportRuntimeHelper({ +\\"./mods/hello.js\\": () => import(\\"./mods/hello.js?raw\\"), +\\"./mods/hi.js\\": () => import(\\"./mods/hi.js?raw\\") +}, \`./mods/\${base}.js\`)" +`; + +exports[`parse positives > with query url 1`] = ` +"__variableDynamicImportRuntimeHelper({ +\\"./mods/hello.js\\": () => import(\\"./mods/hello.js\\"), +\\"./mods/hi.js\\": () => import(\\"./mods/hi.js\\") +}, \`./mods/\${base}.js\`)" +`; diff --git a/packages/vite/src/node/__tests__/plugins/dynamicImportVar/mods/hello.js b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/mods/hello.js new file mode 100644 index 00000000000000..67900ef0999962 --- /dev/null +++ b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/mods/hello.js @@ -0,0 +1,3 @@ +export function hello() { + return 'hello' +} diff --git a/packages/vite/src/node/__tests__/plugins/dynamicImportVar/mods/hi.js b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/mods/hi.js new file mode 100644 index 00000000000000..45d3506803b2b6 --- /dev/null +++ b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/mods/hi.js @@ -0,0 +1,3 @@ +export function hi() { + return 'hi' +} diff --git a/packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.test.ts b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.test.ts new file mode 100644 index 00000000000000..84a7f9ae96198e --- /dev/null +++ b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.test.ts @@ -0,0 +1,31 @@ +import { describe, expect, it } from 'vitest' +import { transformDynamicImport } from '../../../plugins/dynamicImportVars' +import { resolve } from 'path' + +async function run(input: string) { + const { glob, rawPattern } = await transformDynamicImport( + input, + resolve(__dirname), + resolve(__dirname, 'index.js'), + (id) => id.replace('@', resolve(__dirname, './mods/')) + ) + return `__variableDynamicImportRuntimeHelper(${glob.s.toString()}, \`${rawPattern}\`)` +} + +describe('parse positives', () => { + it('basic', async () => { + expect(await run('`./mods/${base}.js`')).toMatchSnapshot() + }) + + it('alias path', async () => { + expect(await run('`@/${base}.js`')).toMatchSnapshot() + }) + + it('with query raw', async () => { + expect(await run('`./mods/${base}.js?raw`')).toMatchSnapshot() + }) + + it('with query url', async () => { + expect(await run('`./mods/${base}.js?url`')).toMatchSnapshot() + }) +}) diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index fc9891cf5e54c2..cff27bd0dfd75e 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -67,22 +67,21 @@ export function parseDynamicImportPattern( } } -export async function transformDynamicImportGlob( - source: string, +export async function transformDynamicImport( + importSource: string, root: string, importer: string, - start: number, - end: number, - resolve: (url: string, importer?: string) => Promise + resolve: ( + url: string, + importer?: string + ) => Promise | string | undefined ): Promise<{ glob: TransformGlobImportResult pattern: string rawPattern: string } | null> { - let fileName = source.slice(start, end) - - if (fileName[1] !== '.' && fileName[1] !== '/' && resolve) { - const resolvedFileName = await resolve(fileName.slice(1, -1), importer) + if (importSource[1] !== '.' && importSource[1] !== '/') { + const resolvedFileName = await resolve(importSource.slice(1, -1), importer) if (!resolvedFileName) { return null } @@ -90,10 +89,11 @@ export async function transformDynamicImportGlob( path.dirname(importer), resolvedFileName ) - fileName = `\`${relativeFileName}\`` + importSource = + '`' + (relativeFileName[0] === '.' ? '' : './') + relativeFileName + '`' } - const dynamicImportPattern = parseDynamicImportPattern(fileName) + const dynamicImportPattern = parseDynamicImportPattern(importSource) if (!dynamicImportPattern) { return null } @@ -188,12 +188,10 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin { s ||= new MagicString(source) let result try { - result = await transformDynamicImportGlob( - source, + result = await transformDynamicImport( + source.slice(start, end), config.root, importer, - start, - end, resolve ) } catch (error) { diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index 8b73c88f6a920f..02f1dd16a07e64 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -42,7 +42,7 @@ import type { ViteDevServer } from '..' import { checkPublicFile } from './asset' import { parse as parseJS } from 'acorn' import type { Node } from 'estree' -import { transformDynamicImportGlob } from './dynamicImportVars' +import { transformDynamicImport } from './dynamicImportVars' import { makeLegalIdentifier } from '@rollup/pluginutils' import { shouldExternalizeForSSR } from '../ssr/ssrExternal' import { performance } from 'perf_hooks' @@ -501,12 +501,10 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { if (!isSupportedDynamicImport(url)) { let importGlobResult try { - importGlobResult = await transformDynamicImportGlob( - source, + importGlobResult = await transformDynamicImport( + url, config.root, importer, - start, - end, resolve ) } catch (e) { From d37615e033fd3ddbe04d50931fb6f2fb349657e8 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Mon, 9 May 2022 19:41:12 +0800 Subject: [PATCH 17/30] chore: update --- {packages/playground => playground}/dynamic-import/alias/hello.js | 0 {packages/playground => playground}/dynamic-import/alias/hi.js | 0 .../playground => playground}/dynamic-import/nested/hello.js | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename {packages/playground => playground}/dynamic-import/alias/hello.js (100%) rename {packages/playground => playground}/dynamic-import/alias/hi.js (100%) rename {packages/playground => playground}/dynamic-import/nested/hello.js (100%) diff --git a/packages/playground/dynamic-import/alias/hello.js b/playground/dynamic-import/alias/hello.js similarity index 100% rename from packages/playground/dynamic-import/alias/hello.js rename to playground/dynamic-import/alias/hello.js diff --git a/packages/playground/dynamic-import/alias/hi.js b/playground/dynamic-import/alias/hi.js similarity index 100% rename from packages/playground/dynamic-import/alias/hi.js rename to playground/dynamic-import/alias/hi.js diff --git a/packages/playground/dynamic-import/nested/hello.js b/playground/dynamic-import/nested/hello.js similarity index 100% rename from packages/playground/dynamic-import/nested/hello.js rename to playground/dynamic-import/nested/hello.js From a2250ecc11c2ec2c4c2759df91d3cac2258c0796 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Mon, 9 May 2022 20:03:15 +0800 Subject: [PATCH 18/30] fix: simplify the implementation --- packages/vite/src/node/build.ts | 2 - .../src/node/plugins/dynamicImportVars.ts | 53 ++++------- .../vite/src/node/plugins/importAnalysis.ts | 95 +++---------------- packages/vite/src/node/plugins/index.ts | 4 +- 4 files changed, 32 insertions(+), 122 deletions(-) diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts index f926bcc47f0f41..1bdfa5a35077e6 100644 --- a/packages/vite/src/node/build.ts +++ b/packages/vite/src/node/build.ts @@ -26,7 +26,6 @@ import { copyDir, emptyDir, lookupFile, normalizePath } from './utils' import { manifestPlugin } from './plugins/manifest' import commonjsPlugin from '@rollup/plugin-commonjs' import type { RollupCommonJSOptions } from 'types/commonjs' -import { dynamicImportVarsPlugin } from './plugins/dynamicImportVars' import type { RollupDynamicImportVarsOptions } from 'types/dynamicImportVars' import type { Logger } from './logger' import type { TransformOptions } from 'esbuild' @@ -285,7 +284,6 @@ export function resolveBuildPlugins(config: ResolvedConfig): { watchPackageDataPlugin(config), commonjsPlugin(options.commonjsOptions), dataURIPlugin(), - dynamicImportVarsPlugin(config), assetImportMetaUrlPlugin(config), ...(options.rollupOptions.plugins ? (options.rollupOptions.plugins.filter(Boolean) as Plugin[]) diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index 6b7fbbd52112fc..889a0a08fe0804 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -8,9 +8,6 @@ import { parseRequest } from '../utils' import { parse as parseJS } from 'acorn' import { createFilter } from '@rollup/pluginutils' import { dynamicImportToGlob } from '@rollup/plugin-dynamic-import-vars' -import type { TransformGlobImportResult } from './importMetaGlob' -import { transformGlobImport } from './importMetaGlob' -import type { ViteDevServer } from '../server' interface DynamicImportRequest { as?: 'raw' @@ -76,7 +73,7 @@ export async function transformDynamicImport( importer?: string ) => Promise | string | undefined ): Promise<{ - glob: TransformGlobImportResult + glob: string pattern: string rawPattern: string } | null> { @@ -101,30 +98,12 @@ export async function transformDynamicImport( const params = globParams ? `, ${JSON.stringify({ ...globParams, import: '*' })}` : '' - const exp = `import.meta.glob(${JSON.stringify(userPattern)}${params})` - const glob = await transformGlobImport(exp, importer, root, resolve, false) + const exp = `(import.meta.glob(${JSON.stringify(userPattern)}${params}))` return { rawPattern, pattern: userPattern, - glob: glob! - } -} - -export function dynamicImportHelperPlugin(): Plugin { - return { - name: 'vite:dynamic-import-helper', - resolveId(id) { - if (id === dynamicImportHelperId) { - return id - } - }, - - load(id) { - if (id === dynamicImportHelperId) { - return 'export default' + dynamicImportHelper.toString() - } - } + glob: exp } } @@ -137,13 +116,20 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin { const { include, exclude, warnOnError } = config.build.dynamicImportVarsOptions const filter = createFilter(include, exclude) - let server: ViteDevServer return { name: 'vite:dynamic-import-vars', - configureServer(_server) { - server = _server + resolveId(id) { + if (id === dynamicImportHelperId) { + return id + } + }, + + load(id) { + if (id === dynamicImportHelperId) { + return 'export default' + dynamicImportHelper.toString() + } }, async transform(source, importer) { @@ -157,7 +143,8 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin { try { imports = parseImports(source)[0] } catch (e: any) { - this.error(e, e.idx) + // ignore as it might not be a JS file, the subsequent plugins will catch the error + return null } if (!imports.length) { @@ -207,16 +194,8 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin { s.overwrite( expStart, expEnd, - `__variableDynamicImportRuntimeHelper(${glob.s.toString()}, \`${rawPattern}\`)` + `__variableDynamicImportRuntimeHelper(${glob}, \`${rawPattern}\`)` ) - if (server) { - const allGlobs = glob.matches.map((i) => i.globsResolved) - server._importGlobMap.set(importer, allGlobs) - glob.files.forEach((file) => { - // update watcher - server!.watcher.add(path.posix.dirname(file)) - }) - } } if (s) { diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index 02f1dd16a07e64..f12426aa923cfe 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -42,7 +42,6 @@ import type { ViteDevServer } from '..' import { checkPublicFile } from './asset' import { parse as parseJS } from 'acorn' import type { Node } from 'estree' -import { transformDynamicImport } from './dynamicImportVars' import { makeLegalIdentifier } from '@rollup/pluginutils' import { shouldExternalizeForSSR } from '../ssr/ssrExternal' import { performance } from 'perf_hooks' @@ -52,7 +51,6 @@ import { getDepsCacheDir, optimizedDepNeedsInterop } from '../optimizer' -import { dynamicImportHelperId } from './dynamicImportVars' const isDebug = !!process.env.DEBUG const debug = createDebugger('vite:import-analysis') @@ -110,11 +108,6 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { const { root, base } = config const clientPublicPath = path.posix.join(base, CLIENT_PUBLIC_PATH) let server: ViteDevServer - const resolve = config.createResolver({ - preferRelative: true, - tryIndex: false, - extensions: [] - }) return { name: 'vite:import-analysis', @@ -185,7 +178,6 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { let isSelfAccepting = false let hasEnv = false let needQueryInjectHelper = false - let needDynamicImportHelper = false let s: MagicString | undefined const str = () => s || (s = new MagicString(source)) const importedUrls = new Set() @@ -498,52 +490,20 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { const url = rawUrl .replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '') .trim() - if (!isSupportedDynamicImport(url)) { - let importGlobResult - try { - importGlobResult = await transformDynamicImport( - url, - config.root, - importer, - resolve - ) - } catch (e) { - this.error(e) - } - - if (importGlobResult) { - const { glob, rawPattern } = importGlobResult - needDynamicImportHelper = true - str().overwrite( - expStart, - expEnd, - `__variableDynamicImportRuntimeHelper(${glob.s.toString()}, \`${rawPattern}\`)` - ) - if (server) { - const allGlobs = glob.matches.map((i) => i.globsResolved) - server._importGlobMap.set(importer, allGlobs) - glob.files.forEach((file) => { - // update watcher - server!.watcher.add(path.posix.dirname(file)) - }) - } - } else { - if (!hasViteIgnore) { - this.warn( - `\n` + - colors.cyan(importerModule.file) + - `\n` + - generateCodeFrame(source, start) + - `\nThe above dynamic import cannot be analyzed by vite.\n` + - `See ${colors.blue( - `https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations` - )} ` + - `for supported dynamic import formats. ` + - `If this is intended to be left as-is, you can use the ` + - `/* @vite-ignore */ comment inside the import() call to suppress this warning.\n` - ) - } - } + if (!hasViteIgnore) { + this.warn( + `\n` + + colors.cyan(importerModule.file) + + `\n` + + generateCodeFrame(source, start) + + `\nThe above dynamic import cannot be analyzed by vite.\n` + + `See ${colors.blue( + `https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations` + )} ` + + `for supported dynamic import formats. ` + + `If this is intended to be left as-is, you can use the ` + + `/* @vite-ignore */ comment inside the import() call to suppress this warning.\n` + ) } if ( !/^('.*'|".*"|`.*`)$/.test(url) || @@ -603,12 +563,6 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { ) } - if (needDynamicImportHelper) { - str().prepend( - `import __variableDynamicImportRuntimeHelper from "${dynamicImportHelperId}";` - ) - } - // normalize and rewrite accepted urls const normalizedAcceptedUrls = new Set() for (const { url, start, end } of acceptedUrls) { @@ -697,27 +651,6 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { } } -/** - * https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations - * This is probably less accurate but is much cheaper than a full AST parse. - */ -function isSupportedDynamicImport(url: string) { - url = url.trim().slice(1, -1) - // must be relative - if (!url.startsWith('./') && !url.startsWith('../')) { - return false - } - // must have extension - if (!path.extname(url)) { - return false - } - // must be more specific if importing from same dir - if (url.startsWith('./${') && url.indexOf('/') === url.lastIndexOf('/')) { - return false - } - return true -} - type ImportNameSpecifier = { importedName: string; localName: string } /** diff --git a/packages/vite/src/node/plugins/index.ts b/packages/vite/src/node/plugins/index.ts index 1fd5f57f1796ad..3fd283b07b4e47 100644 --- a/packages/vite/src/node/plugins/index.ts +++ b/packages/vite/src/node/plugins/index.ts @@ -19,7 +19,7 @@ import { ssrRequireHookPlugin } from './ssrRequireHook' import { workerImportMetaUrlPlugin } from './workerImportMetaUrl' import { ensureWatchPlugin } from './ensureWatch' import { metadataPlugin } from './metadata' -import { dynamicImportHelperPlugin } from './dynamicImportVars' +import { dynamicImportVarsPlugin } from './dynamicImportVars' import { importGlobPlugin } from './importMetaGlob' export async function resolvePlugins( @@ -53,7 +53,6 @@ export async function resolvePlugins( ssrConfig: config.ssr, asSrc: true }), - dynamicImportHelperPlugin(), isBuild ? null : optimizedDepsPlugin(), htmlInlineProxyPlugin(config), cssPlugin(config), @@ -75,6 +74,7 @@ export async function resolvePlugins( isBuild && buildHtmlPlugin(config), workerImportMetaUrlPlugin(config), ...buildPlugins.pre, + dynamicImportVarsPlugin(config), importGlobPlugin(config), ...postPlugins, ...buildPlugins.post, From a998435cc39b1b1377a01b24f7cb5ab683f84fdf Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Mon, 9 May 2022 20:10:11 +0800 Subject: [PATCH 19/30] chore: update snap --- .../__snapshots__/parse.test.ts.snap | 28 +++---------------- .../plugins/dynamicImportVar/parse.test.ts | 3 +- .../src/node/plugins/dynamicImportVars.ts | 2 -- 3 files changed, 5 insertions(+), 28 deletions(-) diff --git a/packages/vite/src/node/__tests__/plugins/dynamicImportVar/__snapshots__/parse.test.ts.snap b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/__snapshots__/parse.test.ts.snap index 6e9485057fd6ea..0624965752bf80 100644 --- a/packages/vite/src/node/__tests__/plugins/dynamicImportVar/__snapshots__/parse.test.ts.snap +++ b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/__snapshots__/parse.test.ts.snap @@ -1,29 +1,9 @@ // Vitest Snapshot v1 -exports[`parse positives > alias path 1`] = ` -"__variableDynamicImportRuntimeHelper({ -\\"./mods/hello.js\\": () => import(\\"./mods/hello.js\\"), -\\"./mods/hi.js\\": () => import(\\"./mods/hi.js\\") -}, \`./mods/\${base}.js\`)" -`; +exports[`parse positives > alias path 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob(\\"./mods/*.js\\")), \`./mods/\${base}.js\`)"`; -exports[`parse positives > basic 1`] = ` -"__variableDynamicImportRuntimeHelper({ -\\"./mods/hello.js\\": () => import(\\"./mods/hello.js\\"), -\\"./mods/hi.js\\": () => import(\\"./mods/hi.js\\") -}, \`./mods/\${base}.js\`)" -`; +exports[`parse positives > basic 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob(\\"./mods/*.js\\")), \`./mods/\${base}.js\`)"`; -exports[`parse positives > with query raw 1`] = ` -"__variableDynamicImportRuntimeHelper({ -\\"./mods/hello.js\\": () => import(\\"./mods/hello.js?raw\\"), -\\"./mods/hi.js\\": () => import(\\"./mods/hi.js?raw\\") -}, \`./mods/\${base}.js\`)" -`; +exports[`parse positives > with query raw 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob(\\"./mods/*.js\\", {\\"as\\":\\"raw\\",\\"import\\":\\"*\\"})), \`./mods/\${base}.js\`)"`; -exports[`parse positives > with query url 1`] = ` -"__variableDynamicImportRuntimeHelper({ -\\"./mods/hello.js\\": () => import(\\"./mods/hello.js\\"), -\\"./mods/hi.js\\": () => import(\\"./mods/hi.js\\") -}, \`./mods/\${base}.js\`)" -`; +exports[`parse positives > with query url 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob(\\"./mods/*.js\\")), \`./mods/\${base}.js\`)"`; diff --git a/packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.test.ts b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.test.ts index 84a7f9ae96198e..7016402ce28ca9 100644 --- a/packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.test.ts +++ b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.test.ts @@ -5,11 +5,10 @@ import { resolve } from 'path' async function run(input: string) { const { glob, rawPattern } = await transformDynamicImport( input, - resolve(__dirname), resolve(__dirname, 'index.js'), (id) => id.replace('@', resolve(__dirname, './mods/')) ) - return `__variableDynamicImportRuntimeHelper(${glob.s.toString()}, \`${rawPattern}\`)` + return `__variableDynamicImportRuntimeHelper(${glob}, \`${rawPattern}\`)` } describe('parse positives', () => { diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index 889a0a08fe0804..8e5c4f6a926397 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -66,7 +66,6 @@ export function parseDynamicImportPattern( export async function transformDynamicImport( importSource: string, - root: string, importer: string, resolve: ( url: string, @@ -172,7 +171,6 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin { try { result = await transformDynamicImport( source.slice(start, end), - config.root, importer, resolve ) From d4204ec9fc2f6b0cb71b190ec618b5d4b182beb1 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Mon, 9 May 2022 20:33:59 +0800 Subject: [PATCH 20/30] chore: try fix windows --- .../vite/src/node/plugins/dynamicImportVars.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index 8e5c4f6a926397..3d61bc27101ea5 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -1,14 +1,16 @@ -import path from 'path' +import { posix } from 'path' import MagicString from 'magic-string' import { init, parse as parseImports } from 'es-module-lexer' import type { ImportSpecifier } from 'es-module-lexer' import type { Plugin } from '../plugin' import type { ResolvedConfig } from '../config' -import { parseRequest } from '../utils' +import { normalizePath, parseRequest } from '../utils' import { parse as parseJS } from 'acorn' import { createFilter } from '@rollup/pluginutils' import { dynamicImportToGlob } from '@rollup/plugin-dynamic-import-vars' +export const dynamicImportHelperId = '/@vite/dynamic-import-helper' + interface DynamicImportRequest { as?: 'raw' } @@ -30,9 +32,8 @@ const dynamicImportHelper = (glob: Record, path: string) => { ) }) } -export const dynamicImportHelperId = '/@vite/dynamic-import-helper' -export function parseDynamicImportPattern( +function parseDynamicImportPattern( strings: string ): DynamicImportPattern | null { const filename = strings.slice(1, -1) @@ -77,12 +78,13 @@ export async function transformDynamicImport( rawPattern: string } | null> { if (importSource[1] !== '.' && importSource[1] !== '/') { - const resolvedFileName = await resolve(importSource.slice(1, -1), importer) + let resolvedFileName = await resolve(importSource.slice(1, -1), importer) if (!resolvedFileName) { return null } - const relativeFileName = path.posix.relative( - path.dirname(importer), + resolvedFileName = normalizePath(resolvedFileName) + const relativeFileName = posix.relative( + posix.dirname(importer), resolvedFileName ) importSource = From ef9041f9d8378e3aa1d448b47ad7a84b050dc24d Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Mon, 9 May 2022 21:31:07 +0800 Subject: [PATCH 21/30] chore: fix windows --- packages/vite/src/node/plugins/dynamicImportVars.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index 3d61bc27101ea5..496ce19619f131 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -78,14 +78,13 @@ export async function transformDynamicImport( rawPattern: string } | null> { if (importSource[1] !== '.' && importSource[1] !== '/') { - let resolvedFileName = await resolve(importSource.slice(1, -1), importer) + const resolvedFileName = await resolve(importSource.slice(1, -1), importer) if (!resolvedFileName) { return null } - resolvedFileName = normalizePath(resolvedFileName) const relativeFileName = posix.relative( - posix.dirname(importer), - resolvedFileName + posix.dirname(normalizePath(importer)), + normalizePath(resolvedFileName) ) importSource = '`' + (relativeFileName[0] === '.' ? '' : './') + relativeFileName + '`' From 7e4c42a97b6849069060a45165a9770f91494280 Mon Sep 17 00:00:00 2001 From: yoho Date: Mon, 9 May 2022 23:15:12 +0800 Subject: [PATCH 22/30] fix: window --- packages/vite/src/node/plugins/dynamicImportVars.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index 496ce19619f131..ebaba713c67287 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -83,11 +83,12 @@ export async function transformDynamicImport( return null } const relativeFileName = posix.relative( - posix.dirname(normalizePath(importer)), - normalizePath(resolvedFileName) + posix.dirname(importer), + resolvedFileName ) - importSource = + importSource = normalizePath( '`' + (relativeFileName[0] === '.' ? '' : './') + relativeFileName + '`' + ) } const dynamicImportPattern = parseDynamicImportPattern(importSource) From 5d11b745d9a6316247696ec074096dacc45ba6bb Mon Sep 17 00:00:00 2001 From: yoho Date: Mon, 9 May 2022 23:27:06 +0800 Subject: [PATCH 23/30] fix: window --- packages/vite/src/node/plugins/dynamicImportVars.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index ebaba713c67287..97a598e86fe1d2 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -83,8 +83,8 @@ export async function transformDynamicImport( return null } const relativeFileName = posix.relative( - posix.dirname(importer), - resolvedFileName + posix.dirname(normalizePath(importer)), + normalizePath(resolvedFileName) ) importSource = normalizePath( '`' + (relativeFileName[0] === '.' ? '' : './') + relativeFileName + '`' From b987e850c1ac342f667e64f01705456327f72271 Mon Sep 17 00:00:00 2001 From: yoho Date: Tue, 10 May 2022 00:57:16 +0800 Subject: [PATCH 24/30] chore: safe Co-authored-by: Bjorn Lu --- packages/vite/src/node/plugins/dynamicImportVars.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index 97a598e86fe1d2..78fac22ce1c5d7 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -129,7 +129,7 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin { load(id) { if (id === dynamicImportHelperId) { - return 'export default' + dynamicImportHelper.toString() + return 'export default ' + dynamicImportHelper.toString() } }, From e715d41a53effd0986c048902f58f75a14dcdda3 Mon Sep 17 00:00:00 2001 From: yoho Date: Tue, 10 May 2022 14:18:28 +0800 Subject: [PATCH 25/30] fix: edge case --- packages/vite/src/node/plugins/dynamicImportVars.ts | 6 +++--- packages/vite/src/node/utils.ts | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index 78fac22ce1c5d7..f47abe7d22c454 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -4,7 +4,7 @@ import { init, parse as parseImports } from 'es-module-lexer' import type { ImportSpecifier } from 'es-module-lexer' import type { Plugin } from '../plugin' import type { ResolvedConfig } from '../config' -import { normalizePath, parseRequest } from '../utils' +import { normalizePath, parseRequest, requestQuerySplitRE } from '../utils' import { parse as parseJS } from 'acorn' import { createFilter } from '@rollup/pluginutils' import { dynamicImportToGlob } from '@rollup/plugin-dynamic-import-vars' @@ -51,8 +51,8 @@ function parseDynamicImportPattern( return null } - const [userPattern] = userPatternQuery.split('?', 2) - const [rawPattern] = filename.split('?', 2) + const [userPattern] = userPatternQuery.split(requestQuerySplitRE, 2) + const [rawPattern] = filename.split(requestQuerySplitRE, 2) if (rawQuery?.raw !== undefined) { globParams = { as: 'raw' } diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index ddcaced9832bc1..37f336f012abaf 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -723,6 +723,7 @@ export function toUpperCaseDriveLetter(pathName: string): string { export const multilineCommentsRE = /\/\*(.|[\r\n])*?\*\//gm export const singlelineCommentsRE = /\/\/.*/g +export const requestQuerySplitRE = /\?(?!.*[\/|\}])/ export const usingDynamicImport = typeof jest === 'undefined' /** From e88ec200de7949bc8edd85e1ea7306b04d52f9b5 Mon Sep 17 00:00:00 2001 From: yoho Date: Tue, 10 May 2022 14:23:47 +0800 Subject: [PATCH 26/30] fix: sourcemap generate logic --- packages/vite/src/node/plugins/dynamicImportVars.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index f47abe7d22c454..c7dd50e22c73c9 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -117,7 +117,7 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin { const { include, exclude, warnOnError } = config.build.dynamicImportVarsOptions const filter = createFilter(include, exclude) - + const isBuild = config.command === 'build' return { name: 'vite:dynamic-import-vars', @@ -206,7 +206,11 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin { } return { code: s.toString(), - map: config.build.sourcemap ? s.generateMap({ hires: true }) : null + map: isBuild + ? config.build.sourcemap + ? s.generateMap({ hires: true }) + : null + : s.generateMap({ hires: true }) } } } From 1be36937b7a99ed1b65372d5d7af271cac3e281b Mon Sep 17 00:00:00 2001 From: yoho Date: Tue, 10 May 2022 14:56:54 +0800 Subject: [PATCH 27/30] chore: nice judge Co-authored-by: Bjorn Lu --- packages/vite/src/node/plugins/dynamicImportVars.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index c7dd50e22c73c9..adb2be96011098 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -206,11 +206,9 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin { } return { code: s.toString(), - map: isBuild - ? config.build.sourcemap - ? s.generateMap({ hires: true }) - : null - : s.generateMap({ hires: true }) + map: !isBuild || config.build.sourcemap + ? s.generateMap({ hires: true }) + : null } } } From de3582f8a714574432d40263b8ecd4882fef771d Mon Sep 17 00:00:00 2001 From: yoho Date: Tue, 10 May 2022 14:57:20 +0800 Subject: [PATCH 28/30] fix: parseUrl --- .../dynamicImportVar/__snapshots__/parse.test.ts.snap | 4 ++++ .../node/__tests__/plugins/dynamicImportVar/parse.test.ts | 8 ++++++++ packages/vite/src/node/utils.ts | 4 ++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/vite/src/node/__tests__/plugins/dynamicImportVar/__snapshots__/parse.test.ts.snap b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/__snapshots__/parse.test.ts.snap index 0624965752bf80..be73ec998bc834 100644 --- a/packages/vite/src/node/__tests__/plugins/dynamicImportVar/__snapshots__/parse.test.ts.snap +++ b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/__snapshots__/parse.test.ts.snap @@ -1,5 +1,9 @@ // Vitest Snapshot v1 +exports[`parse positives > ? in url 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob(\\"./mo?ds/*.js\\", {\\"as\\":\\"raw\\",\\"import\\":\\"*\\"})), \`./mo?ds/\${base ?? foo}.js\`)"`; + +exports[`parse positives > ? in variables 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob(\\"./mods/*.js\\", {\\"as\\":\\"raw\\",\\"import\\":\\"*\\"})), \`./mods/\${base ?? foo}.js\`)"`; + exports[`parse positives > alias path 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob(\\"./mods/*.js\\")), \`./mods/\${base}.js\`)"`; exports[`parse positives > basic 1`] = `"__variableDynamicImportRuntimeHelper((import.meta.glob(\\"./mods/*.js\\")), \`./mods/\${base}.js\`)"`; diff --git a/packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.test.ts b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.test.ts index 7016402ce28ca9..ef1dcb2238a5b0 100644 --- a/packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.test.ts +++ b/packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.test.ts @@ -27,4 +27,12 @@ describe('parse positives', () => { it('with query url', async () => { expect(await run('`./mods/${base}.js?url`')).toMatchSnapshot() }) + + it('? in variables', async () => { + expect(await run('`./mods/${base ?? foo}.js?raw`')).toMatchSnapshot() + }) + + it('? in url', async () => { + expect(await run('`./mo?ds/${base ?? foo}.js?raw`')).toMatchSnapshot() + }) }) diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 37f336f012abaf..42ce86a0379d4c 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -740,11 +740,11 @@ export const dynamicImport = usingDynamicImport : require export function parseRequest(id: string): Record | null { - const { search } = parseUrl(id) + const [_, search] = id.split(requestQuerySplitRE, 2) if (!search) { return null } - return Object.fromEntries(new URLSearchParams(search.slice(1))) + return Object.fromEntries(new URLSearchParams(search)) } export const blankReplacer = (match: string) => ' '.repeat(match.length) From c8f62f8620de6ef9578d9c7e4dc0558b35669649 Mon Sep 17 00:00:00 2001 From: yoho Date: Tue, 10 May 2022 15:01:49 +0800 Subject: [PATCH 29/30] chore: useless --- packages/vite/src/node/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 42ce86a0379d4c..1f5ce1ffc4b764 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -19,7 +19,7 @@ import type { FSWatcher } from 'chokidar' import remapping from '@ampproject/remapping' import type { DecodedSourceMap, RawSourceMap } from '@ampproject/remapping' import { performance } from 'perf_hooks' -import { parse as parseUrl, URLSearchParams } from 'url' +import { URLSearchParams } from 'url' export function slash(p: string): string { return p.replace(/\\/g, '/') From 837624ef0b77421c1336ad013390d18a1a01c29f Mon Sep 17 00:00:00 2001 From: yoho Date: Tue, 10 May 2022 15:46:41 +0800 Subject: [PATCH 30/30] chore: format --- packages/vite/src/node/plugins/dynamicImportVars.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index adb2be96011098..c33590cf0343f4 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -206,9 +206,10 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin { } return { code: s.toString(), - map: !isBuild || config.build.sourcemap - ? s.generateMap({ hires: true }) - : null + map: + !isBuild || config.build.sourcemap + ? s.generateMap({ hires: true }) + : null } } }