Skip to content

Commit

Permalink
fix(dynamic-import-vars): simplify the implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
poyoho committed May 9, 2022
2 parents d37615e + ef9041f commit 79c1909
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 157 deletions.
@@ -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\`)"`;
Expand Up @@ -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', () => {
Expand Down
2 changes: 0 additions & 2 deletions packages/vite/src/node/build.ts
Expand Up @@ -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'
Expand Down Expand Up @@ -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[])
Expand Down
70 changes: 24 additions & 46 deletions packages/vite/src/node/plugins/dynamicImportVars.ts
@@ -1,16 +1,15 @@
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'
import type { TransformGlobImportResult } from './importMetaGlob'
import { transformGlobImport } from './importMetaGlob'
import type { ViteDevServer } from '../server'

export const dynamicImportHelperId = '/@vite/dynamic-import-helper'

interface DynamicImportRequest {
as?: 'raw'
Expand All @@ -33,9 +32,8 @@ const dynamicImportHelper = (glob: Record<string, any>, path: string) => {
)
})
}
export const dynamicImportHelperId = '/@vite/dynamic-import-helper'

export function parseDynamicImportPattern(
function parseDynamicImportPattern(
strings: string
): DynamicImportPattern | null {
const filename = strings.slice(1, -1)
Expand Down Expand Up @@ -69,14 +67,13 @@ export function parseDynamicImportPattern(

export async function transformDynamicImport(
importSource: string,
root: string,
importer: string,
resolve: (
url: string,
importer?: string
) => Promise<string | undefined> | string | undefined
): Promise<{
glob: TransformGlobImportResult
glob: string
pattern: string
rawPattern: string
} | null> {
Expand All @@ -85,9 +82,9 @@ export async function transformDynamicImport(
if (!resolvedFileName) {
return null
}
const relativeFileName = path.posix.relative(
path.dirname(importer),
resolvedFileName
const relativeFileName = posix.relative(
posix.dirname(normalizePath(importer)),
normalizePath(resolvedFileName)
)
importSource =
'`' + (relativeFileName[0] === '.' ? '' : './') + relativeFileName + '`'
Expand All @@ -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
}
}

Expand All @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -185,7 +172,6 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin {
try {
result = await transformDynamicImport(
source.slice(start, end),
config.root,
importer,
resolve
)
Expand All @@ -207,16 +193,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) {
Expand Down
95 changes: 14 additions & 81 deletions packages/vite/src/node/plugins/importAnalysis.ts
Expand Up @@ -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'
Expand All @@ -52,7 +51,6 @@ import {
getDepsCacheDir,
optimizedDepNeedsInterop
} from '../optimizer'
import { dynamicImportHelperId } from './dynamicImportVars'

const isDebug = !!process.env.DEBUG
const debug = createDebugger('vite:import-analysis')
Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -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<string>()
Expand Down Expand Up @@ -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) ||
Expand Down Expand Up @@ -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<string>()
for (const { url, start, end } of acceptedUrls) {
Expand Down Expand Up @@ -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 }

/**
Expand Down
4 changes: 2 additions & 2 deletions packages/vite/src/node/plugins/index.ts
Expand Up @@ -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(
Expand Down Expand Up @@ -53,7 +53,6 @@ export async function resolvePlugins(
ssrConfig: config.ssr,
asSrc: true
}),
dynamicImportHelperPlugin(),
isBuild ? null : optimizedDepsPlugin(),
htmlInlineProxyPlugin(config),
cssPlugin(config),
Expand All @@ -75,6 +74,7 @@ export async function resolvePlugins(
isBuild && buildHtmlPlugin(config),
workerImportMetaUrlPlugin(config),
...buildPlugins.pre,
dynamicImportVarsPlugin(config),
importGlobPlugin(config),
...postPlugins,
...buildPlugins.post,
Expand Down

0 comments on commit 79c1909

Please sign in to comment.