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

wip(mp): transform static import to dynamic import

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