提交 04944e14 编写于 作者: fxy060608's avatar fxy060608

wip(mp): transform static import to dynamic import

上级 c83c6ceb
......@@ -19,6 +19,8 @@
"url": "https://github.com/dcloudio/uni-app/issues"
},
"dependencies": {
"@babel/parser": "^7.15.0",
"@babel/types": "^7.15.0",
"@rollup/pluginutils": "^4.1.1",
"chokidar": "^3.5.2",
"compare-versions": "^3.6.0",
......
......@@ -2,6 +2,8 @@ import path from 'path'
import { PluginContext } from 'rollup'
import { init, parse as parseImports, ImportSpecifier } from 'es-module-lexer'
import { extend } from '@vue/shared'
import { isImportDeclaration, isImportDefaultSpecifier } from '@babel/types'
import { parse } from '@babel/parser'
import { EXTNAME_VUE, EXTNAME_VUE_RE } from '../constants'
export async function findVueComponentImports(
......@@ -24,7 +26,7 @@ export async function findVueComponentImports(
return []
}
const rewriteImports: ImportSpecifier[] = []
const rewriteImports: (ImportSpecifier & { i: string })[] = []
for (let i = 0; i < imports.length; i++) {
const importSpecifier = imports[i]
const { n } = importSpecifier
......@@ -41,7 +43,21 @@ export async function findVueComponentImports(
continue
}
if (EXTNAME_VUE_RE.test(res.id)) {
rewriteImports.push(extend(importSpecifier, { n: res.id }))
const expr = parse(source.slice(importSpecifier.ss, importSpecifier.se), {
sourceType: 'module',
}).program.body[0]
if (isImportDeclaration(expr) && expr.specifiers.length === 1) {
const importDefaultSpecifier = expr.specifiers[0]
if (!isImportDefaultSpecifier(importDefaultSpecifier)) {
continue
}
rewriteImports.push(
extend(importSpecifier, {
n: res.id,
i: importDefaultSpecifier.local.name,
})
)
}
}
}
return rewriteImports
......
......@@ -25,11 +25,11 @@ function parseWithElementTransform(
describe('compiler: element transform', () => {
test('import + resolve component', () => {
const { root, code } = parseWithElementTransform(`<Foo/>`)
const { root } = parseWithElementTransform(`<Foo/>`)
expect((root as CodegenRootNode).bindingComponents).toEqual({
Foo: { name: '_component_Foo', type: BindingComponentTypes.UNKNOWN },
})
expect(code).toContain(`if (!Math) {Math.max.call(Max, _component_Foo)}`)
// expect(code).toContain(`if (!Math) {Math.max.call(Max, _component_Foo)}`)
})
test('import + resolve component multi', () => {
......@@ -48,21 +48,16 @@ describe('compiler: element transform', () => {
Example: { name: '$setup["Example"]', type: BindingComponentTypes.SETUP },
Test: { name: '_component_Test', type: BindingComponentTypes.SELF },
})
expect(code).toContain(
`if (!Math) {Math.max.call(Max, _component_Foo, _component_Bar, $setup["Example"], _component_Test)}`
)
expect(code).toContain(`if (!Math) {Math.max.call(Max, $setup["Example"])}`)
})
test('resolve implcitly self-referencing component', () => {
const { root, code } = parseWithElementTransform(`<Example/>`, {
const { root } = parseWithElementTransform(`<Example/>`, {
filename: `/foo/bar/Example.vue?vue&type=template`,
})
expect((root as CodegenRootNode).bindingComponents).toEqual({
Example: { name: '_component_Example', type: BindingComponentTypes.SELF },
})
expect(code).toContain(
`if (!Math) {Math.max.call(Max, _component_Example)}`
)
})
test('resolve component from setup bindings', () => {
......
......@@ -151,25 +151,21 @@ function genComponentImports(
{ push }: CodegenContext
) {
const importDeclarations: string[] = []
// 仅记录easycom和setup组件
const components: string[] = []
Object.keys(bindingComponents).forEach((tag) => {
const { name, type } = bindingComponents[tag]
if (type === BindingComponentTypes.UNKNOWN) {
const source = matchEasycom(tag)
if (source) {
components.push(name)
addImportDeclaration(importDeclarations, name, source)
}
} else if (type === BindingComponentTypes.SETUP) {
components.push(name)
}
})
importDeclarations.forEach((str) => push(str))
}
function genComponents(
bindingComponents: TransformContext['bindingComponents'],
{ push }: CodegenContext
) {
const components = Object.keys(bindingComponents).map(
(tag) => bindingComponents[tag].name
)
if (components.length) {
push(`if (!Math) {`)
push(`Math.max.call(Max, ${components.map((name) => name).join(', ')})`)
......@@ -197,7 +193,6 @@ function genFunctionPreamble(ast: RootNode, context: CodegenContext) {
}
}
genComponentImports(bindingComponents, context)
genComponents(bindingComponents, context)
newline()
push(`return `)
}
......@@ -216,7 +211,6 @@ function genModulePreamble(
)
}
genComponentImports(bindingComponents, context)
genComponents(bindingComponents, context)
newline()
if (!inline) {
push(`export `)
......
......@@ -29,11 +29,13 @@ export function uniComponentPlugin(): Plugin {
}
const s = new MagicString(code)
const rewriteImports: string[] = []
vueComponentImports.forEach(({ n, ss, se }) => {
vueComponentImports.forEach(({ n, ss, se, i }) => {
s.remove(ss, se)
rewriteImports.push(`import('${virtualComponentPath(n!)}')`)
rewriteImports.push(
`const ${i} = ()=>import('${virtualComponentPath(n!)}')`
)
})
s.prepend(`if(!Math){${rewriteImports.join(';')}}`)
s.prepend(rewriteImports.join(';') + ';\n')
return s.toString()
},
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册