Browse Source

feat(compiler-vapor): extract `resolveComponent`

Avoid call `resolveComponent` repeatly for the same component
三咲智子 Kevin Deng 2 years ago
parent
commit
b9b3e021de

+ 2 - 1
packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap

@@ -125,9 +125,10 @@ const t0 = _template("<div :id=\\"foo\\"><Comp></Comp>{{ bar }}</div>")
 const t1 = _template("<div></div>")
 
 export function render(_ctx) {
+  const _component_Comp = _resolveComponent("Comp")
   const n0 = t0()
   const n3 = t1()
-  const n1 = _createComponent(_resolveComponent("Comp"))
+  const n1 = _createComponent(_component_Comp)
   const n2 = _createTextNode()
   _insert([n1, n2], n3)
   _renderEffect(() => _setText(n2, _ctx.bar))

+ 18 - 9
packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap

@@ -4,7 +4,8 @@ exports[`compiler: element transform > component > do not resolve component from
 "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
 
 export function render(_ctx) {
-  const n0 = _createComponent(_resolveComponent("Example"), null, true)
+  const _component_Example = _resolveComponent("Example")
+  const n0 = _createComponent(_component_Example, null, true)
   return n0
 }"
 `;
@@ -33,7 +34,8 @@ exports[`compiler: element transform > component > import + resolve component 1`
 "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
 
 export function render(_ctx) {
-  const n0 = _createComponent(_resolveComponent("Foo"), null, true)
+  const _component_Foo = _resolveComponent("Foo")
+  const n0 = _createComponent(_component_Foo, null, true)
   return n0
 }"
 `;
@@ -97,7 +99,8 @@ exports[`compiler: element transform > component > should wrap as function if v-
 "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
 
 export function render(_ctx) {
-  const n0 = _createComponent(_resolveComponent("Foo"), [{
+  const _component_Foo = _resolveComponent("Foo")
+  const n0 = _createComponent(_component_Foo, [{
     onBar: () => $event => (_ctx.handleBar($event))
   }], true)
   return n0
@@ -108,7 +111,8 @@ exports[`compiler: element transform > component > static props 1`] = `
 "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
 
 export function render(_ctx) {
-  const n0 = _createComponent(_resolveComponent("Foo"), [{
+  const _component_Foo = _resolveComponent("Foo")
+  const n0 = _createComponent(_component_Foo, [{
     id: () => ("foo"), 
     class: () => ("bar")
   }], true)
@@ -120,7 +124,8 @@ exports[`compiler: element transform > component > v-bind="obj" 1`] = `
 "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
 
 export function render(_ctx) {
-  const n0 = _createComponent(_resolveComponent("Foo"), [() => (_ctx.obj)], true)
+  const _component_Foo = _resolveComponent("Foo")
+  const n0 = _createComponent(_component_Foo, [() => (_ctx.obj)], true)
   return n0
 }"
 `;
@@ -129,7 +134,8 @@ exports[`compiler: element transform > component > v-bind="obj" after static pro
 "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
 
 export function render(_ctx) {
-  const n0 = _createComponent(_resolveComponent("Foo"), [{
+  const _component_Foo = _resolveComponent("Foo")
+  const n0 = _createComponent(_component_Foo, [{
     id: () => ("foo")
   }, () => (_ctx.obj)], true)
   return n0
@@ -140,7 +146,8 @@ exports[`compiler: element transform > component > v-bind="obj" before static pr
 "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
 
 export function render(_ctx) {
-  const n0 = _createComponent(_resolveComponent("Foo"), [() => (_ctx.obj), {
+  const _component_Foo = _resolveComponent("Foo")
+  const n0 = _createComponent(_component_Foo, [() => (_ctx.obj), {
     id: () => ("foo")
   }], true)
   return n0
@@ -151,7 +158,8 @@ exports[`compiler: element transform > component > v-bind="obj" between static p
 "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
 
 export function render(_ctx) {
-  const n0 = _createComponent(_resolveComponent("Foo"), [{
+  const _component_Foo = _resolveComponent("Foo")
+  const n0 = _createComponent(_component_Foo, [{
     id: () => ("foo")
   }, () => (_ctx.obj), {
     class: () => ("bar")
@@ -165,7 +173,8 @@ exports[`compiler: element transform > component > v-on="obj" 1`] = `
 import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
 
 export function render(_ctx) {
-  const n0 = _createComponent(_resolveComponent("Foo"), [() => (_toHandlers(_ctx.obj))], true)
+  const _component_Foo = _resolveComponent("Foo")
+  const n0 = _createComponent(_component_Foo, [() => (_toHandlers(_ctx.obj))], true)
   return n0
 }"
 `;

+ 12 - 6
packages/compiler-vapor/__tests__/transforms/__snapshots__/vModel.spec.ts.snap

@@ -4,7 +4,8 @@ exports[`compiler: vModel transform > component > v-model for component should g
 "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
 
 export function render(_ctx) {
-  const n0 = _createComponent(_resolveComponent("Comp"), [{
+  const _component_Comp = _resolveComponent("Comp")
+  const n0 = _createComponent(_component_Comp, [{
     modelValue: () => (_ctx.foo),
     "onUpdate:modelValue": () => $event => (_ctx.foo = $event),
     modelModifiers: () => ({ trim: true, "bar-baz": true })
@@ -17,7 +18,8 @@ exports[`compiler: vModel transform > component > v-model for component should w
 "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
 
 export function render(_ctx) {
-  const n0 = _createComponent(_resolveComponent("Comp"), [{
+  const _component_Comp = _resolveComponent("Comp")
+  const n0 = _createComponent(_component_Comp, [{
     modelValue: () => (_ctx.foo),
     "onUpdate:modelValue": () => $event => (_ctx.foo = $event)
   }], true)
@@ -29,7 +31,8 @@ exports[`compiler: vModel transform > component > v-model with arguments for com
 "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
 
 export function render(_ctx) {
-  const n0 = _createComponent(_resolveComponent("Comp"), [{
+  const _component_Comp = _resolveComponent("Comp")
+  const n0 = _createComponent(_component_Comp, [{
     foo: () => (_ctx.foo),
     "onUpdate:foo": () => $event => (_ctx.foo = $event),
     fooModifiers: () => ({ trim: true }), 
@@ -45,7 +48,8 @@ exports[`compiler: vModel transform > component > v-model with arguments for com
 "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
 
 export function render(_ctx) {
-  const n0 = _createComponent(_resolveComponent("Comp"), [{
+  const _component_Comp = _resolveComponent("Comp")
+  const n0 = _createComponent(_component_Comp, [{
     bar: () => (_ctx.foo),
     "onUpdate:bar": () => $event => (_ctx.foo = $event)
   }], true)
@@ -57,7 +61,8 @@ exports[`compiler: vModel transform > component > v-model with dynamic arguments
 "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
 
 export function render(_ctx) {
-  const n0 = _createComponent(_resolveComponent("Comp"), [{
+  const _component_Comp = _resolveComponent("Comp")
+  const n0 = _createComponent(_component_Comp, [{
     [_ctx.foo]: () => (_ctx.foo),
     ["onUpdate:" + _ctx.foo]: () => $event => (_ctx.foo = $event),
     [_ctx.foo + "Modifiers"]: () => ({ trim: true }), 
@@ -73,7 +78,8 @@ exports[`compiler: vModel transform > component > v-model with dynamic arguments
 "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
 
 export function render(_ctx) {
-  const n0 = _createComponent(_resolveComponent("Comp"), [{
+  const _component_Comp = _resolveComponent("Comp")
+  const n0 = _createComponent(_component_Comp, [{
     [_ctx.arg]: () => (_ctx.foo),
     ["onUpdate:" + _ctx.arg]: () => $event => (_ctx.foo = $event)
   }], true)

+ 1 - 1
packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts

@@ -198,7 +198,7 @@ describe('compiler: element transform', () => {
       )
 
       expect(code).toMatchSnapshot()
-      expect(code).contains('_createComponent(_resolveComponent("Foo"), [{')
+      expect(code).contains('_createComponent(_component_Foo, [{')
       expect(code).contains('  id: () => ("foo")')
       expect(code).contains('  class: () => ("bar")')
       expect(code).contains('}], true)')

+ 1 - 1
packages/compiler-vapor/src/generate.ts

@@ -125,7 +125,7 @@ export function generate(
   }
 
   push(INDENT_START)
-  push(...genBlockContent(ir.block, context))
+  push(...genBlockContent(ir.block, context, true))
   push(INDENT_END, NEWLINE)
 
   if (isSetupInlined) {

+ 16 - 1
packages/compiler-vapor/src/generators/block.ts

@@ -10,6 +10,7 @@ import {
   INDENT_START,
   NEWLINE,
   buildCodeFragment,
+  genCall,
 } from './utils'
 import type { CodegenContext } from '../generate'
 import { genWithDirective } from './directive'
@@ -21,6 +22,7 @@ export function genBlock(
   oper: BlockIRNode,
   context: CodegenContext,
   args: CodeFragment[] = [],
+  root?: boolean,
   customReturns?: (returns: CodeFragment[]) => CodeFragment[],
 ): CodeFragment[] {
   return [
@@ -28,7 +30,7 @@ export function genBlock(
     ...args,
     ') => {',
     INDENT_START,
-    ...genBlockContent(oper, context, customReturns),
+    ...genBlockContent(oper, context, root, customReturns),
     INDENT_END,
     NEWLINE,
     '}',
@@ -38,10 +40,23 @@ export function genBlock(
 export function genBlockContent(
   { dynamic, effect, operation, returns }: BlockIRNode,
   context: CodegenContext,
+  root?: boolean,
   customReturns?: (returns: CodeFragment[]) => CodeFragment[],
 ): CodeFragment[] {
   const [frag, push] = buildCodeFragment()
 
+  if (root)
+    for (const name of context.ir.component) {
+      push(
+        NEWLINE,
+        `const _component_${name} = `,
+        ...genCall(
+          context.vaporHelper('resolveComponent'),
+          JSON.stringify(name),
+        ),
+      )
+    }
+
   for (const child of dynamic.children) {
     push(...genChildren(child, context, child.id!))
   }

+ 1 - 1
packages/compiler-vapor/src/generators/component.ts

@@ -40,7 +40,7 @@ export function genCreateComponent(
 
   function genTag() {
     if (oper.resolve) {
-      return genCall(vaporHelper('resolveComponent'), JSON.stringify(oper.tag))
+      return [`_component_${oper.tag}`]
     } else {
       return genExpression(
         extend(createSimpleExpression(oper.tag, false), { ast: null }),

+ 1 - 1
packages/compiler-vapor/src/generators/for.ts

@@ -42,7 +42,7 @@ export function genFor(
   ]
 
   const blockFn = context.withId(
-    () => genBlock(render, context, ['_block'], blockReturns),
+    () => genBlock(render, context, ['_block'], false, blockReturns),
     idMap,
   )
 

+ 1 - 0
packages/compiler-vapor/src/ir.ts

@@ -57,6 +57,7 @@ export interface RootIRNode {
   node: RootNode
   source: string
   template: string[]
+  component: Set<string>
   block: BlockIRNode
 }
 

+ 4 - 0
packages/compiler-vapor/src/transform.ts

@@ -77,6 +77,8 @@ export interface TransformContext<T extends AllNode = AllNode> {
   inVOnce: boolean
   inVFor: number
 
+  component: Set<string>
+
   enterBlock(ir: TransformContext['block'], isVFor?: boolean): () => void
   reference(): number
   increaseId(): number
@@ -149,6 +151,7 @@ function createRootContext(
     inVOnce: false,
     inVFor: 0,
     comment: [],
+    component: root.component,
 
     increaseId: () => globalId++,
     reference() {
@@ -213,6 +216,7 @@ export function transform(
     node: root,
     source: root.source,
     template: [],
+    component: new Set(),
     block: {
       type: IRNodeTypes.BLOCK,
       node: root,

+ 3 - 0
packages/compiler-vapor/src/transforms/transformElement.ts

@@ -86,6 +86,9 @@ function transformComponentElement(
       }
     }
   }
+  if (resolve) {
+    context.component.add(tag)
+  }
 
   context.dynamic.flags |= DynamicFlag.NON_TEMPLATE | DynamicFlag.INSERT
   const root =