From a2250ecc11c2ec2c4c2759df91d3cac2258c0796 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Mon, 9 May 2022 20:03:15 +0800 Subject: [PATCH 1/4] 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 2/4] 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 3/4] 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 4/4] 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 + '`'