Skip to content

Commit

Permalink
fix: skip cjs rewrite for export * declarations
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Jan 8, 2021
1 parent 5d00cee commit cca015b
Showing 1 changed file with 47 additions and 37 deletions.
84 changes: 47 additions & 37 deletions packages/vite/src/node/plugins/importsAnalysis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
import { ViteDevServer } from '../'
import { checkPublicFile } from './asset'
import { parse as parseJS } from 'acorn'
import { ImportDeclaration } from 'estree'
import { Node } from 'estree'
import { makeLegalIdentifier } from '@rollup/pluginutils'

const isDebug = !!process.env.DEBUG
Expand Down Expand Up @@ -306,11 +306,13 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
)
} else {
const exp = source.slice(expStart, expEnd)
str().overwrite(
expStart,
expEnd,
transformCjsImport(exp, url, rawUrl, i)
)
const rewritten = transformCjsImport(exp, url, rawUrl, i)
if (rewritten) {
str().overwrite(expStart, expEnd, rewritten)
} else {
// #1439 export * from '...'
str().overwrite(start, end, url)
}
}
} else {
str().overwrite(start, end, isLiteralDynamicId ? `'${url}'` : url)
Expand Down Expand Up @@ -450,45 +452,53 @@ type ImportNameSpecifier = { importedName: string; localName: string }
* module. Note this doesn't support dynamic re-assisgnments from within the cjs
* module.
*
* Note that es-module-lexer treats `export * from '...'` as an import as well,
* so, we may encounter ExportAllDeclaration here, in which case `undefined`
* will be returned.
*
* Credits \@csr632 via #837
*/
function transformCjsImport(
importExp: string,
url: string,
rawUrl: string,
importIndex: number
): string {
): string | undefined {
const ast = (parseJS(importExp, {
ecmaVersion: 2020,
sourceType: 'module'
}) as any).body[0] as ImportDeclaration

const importNames: ImportNameSpecifier[] = []

ast.specifiers.forEach((obj) => {
if (obj.type === 'ImportSpecifier' && obj.imported.type === 'Identifier') {
const importedName = obj.imported.name
const localName = obj.local.name
importNames.push({ importedName, localName })
} else if (obj.type === 'ImportDefaultSpecifier') {
importNames.push({ importedName: 'default', localName: obj.local.name })
} else if (obj.type === 'ImportNamespaceSpecifier') {
importNames.push({ importedName: '*', localName: obj.local.name })
}
})

// If there is multiple import for same id in one file,
// importIndex will prevent the cjsModuleName to be duplicate
const cjsModuleName = makeLegalIdentifier(
`$viteCjsImport${importIndex}_${rawUrl}`
)
const lines: string[] = [`import ${cjsModuleName} from "${url}";`]
importNames.forEach(({ importedName, localName }) => {
if (importedName === '*' || importedName === 'default') {
lines.push(`const ${localName} = ${cjsModuleName};`)
} else {
lines.push(`const ${localName} = ${cjsModuleName}["${importedName}"];`)
}
})
return lines.join('\n')
}) as any).body[0] as Node

if (ast.type === 'ImportDeclaration') {
const importNames: ImportNameSpecifier[] = []
ast.specifiers.forEach((obj) => {
if (
obj.type === 'ImportSpecifier' &&
obj.imported.type === 'Identifier'
) {
const importedName = obj.imported.name
const localName = obj.local.name
importNames.push({ importedName, localName })
} else if (obj.type === 'ImportDefaultSpecifier') {
importNames.push({ importedName: 'default', localName: obj.local.name })
} else if (obj.type === 'ImportNamespaceSpecifier') {
importNames.push({ importedName: '*', localName: obj.local.name })
}
})

// If there is multiple import for same id in one file,
// importIndex will prevent the cjsModuleName to be duplicate
const cjsModuleName = makeLegalIdentifier(
`$viteCjsImport${importIndex}_${rawUrl}`
)
const lines: string[] = [`import ${cjsModuleName} from "${url}";`]
importNames.forEach(({ importedName, localName }) => {
if (importedName === '*' || importedName === 'default') {
lines.push(`const ${localName} = ${cjsModuleName};`)
} else {
lines.push(`const ${localName} = ${cjsModuleName}["${importedName}"];`)
}
})
return lines.join('\n')
}
}

0 comments on commit cca015b

Please sign in to comment.