diff --git a/packages/uni-cli-shared/package.json b/packages/uni-cli-shared/package.json index c5ebc7d577fa99d5e3d3fd75e2cc4a56fcd7e58e..17577cd4566fb6cefdf8986dc3134fc1e9361c5d 100644 --- a/packages/uni-cli-shared/package.json +++ b/packages/uni-cli-shared/package.json @@ -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", diff --git a/packages/uni-cli-shared/src/mp/imports.ts b/packages/uni-cli-shared/src/mp/imports.ts index 84523d2c99c28892ecf558765975dcd7d884e657..07f535d05d64bfe0b3abf2d3d8db13d176862a2b 100644 --- a/packages/uni-cli-shared/src/mp/imports.ts +++ b/packages/uni-cli-shared/src/mp/imports.ts @@ -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 diff --git a/packages/uni-mp-compiler/__tests__/transformElement.spec.ts b/packages/uni-mp-compiler/__tests__/transformElement.spec.ts index 617f8a1def2d02a4670464d1f7d9c384141fa4ed..e0072a968e3b302094e30c57c44b3cdd65bd7be7 100644 --- a/packages/uni-mp-compiler/__tests__/transformElement.spec.ts +++ b/packages/uni-mp-compiler/__tests__/transformElement.spec.ts @@ -25,11 +25,11 @@ function parseWithElementTransform( describe('compiler: element transform', () => { test('import + resolve component', () => { - const { root, code } = parseWithElementTransform(``) + const { root } = parseWithElementTransform(``) 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(``, { + const { root } = parseWithElementTransform(``, { 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', () => { diff --git a/packages/uni-mp-compiler/src/codegen.ts b/packages/uni-mp-compiler/src/codegen.ts index c08cdc4f4f529faa7cbf45ddd01b5406c7103edd..d029b140adadc398d2306d3330cd681eab84daa6 100644 --- a/packages/uni-mp-compiler/src/codegen.ts +++ b/packages/uni-mp-compiler/src/codegen.ts @@ -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 `) diff --git a/packages/uni-mp-vite/src/plugins/component.ts b/packages/uni-mp-vite/src/plugins/component.ts index 3bf13f409c25125cffa9177d601a566d493ca022..79d706ed418a1634b78d6a3e5cab1eebfaf5b510 100644 --- a/packages/uni-mp-vite/src/plugins/component.ts +++ b/packages/uni-mp-vite/src/plugins/component.ts @@ -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() }, }