Browse Source

adjust optimizer strategy and avoid marking simple elements as static root

Evan You 9 years ago
parent
commit
9a659593c4

+ 9 - 1
src/compiler/optimizer.js

@@ -63,9 +63,17 @@ function markStaticRoots (node: ASTNode, isInFor: boolean) {
     if (node.static || node.once) {
       node.staticInFor = isInFor
     }
-    if (node.static) {
+    // For a node to qualify as a static root, it should have children that
+    // are not just static text. Otherwise the cost of hoisting out will
+    // outweigh the benefits and it's better off to just always render it fresh.
+    if (node.static && node.children.length && !(
+      node.children.length === 1 &&
+      node.children[0].type === 3
+    )) {
       node.staticRoot = true
       return
+    } else {
+      node.staticRoot = false
     }
     if (node.children) {
       for (let i = 0, l = node.children.length; i < l; i++) {

+ 8 - 11
test/unit/modules/compiler/codegen.spec.js

@@ -112,8 +112,7 @@ describe('codegen', () => {
   it('generate slot fallback content', () => {
     assertCodegen(
       '<slot><div>hi</div></slot>',
-      `with(this){return _t("default",[_m(0)])}`,
-      [`with(this){return _h('div',["hi"])}`]
+      `with(this){return _t("default",[_h('div',["hi"])])}`
     )
   })
 
@@ -128,8 +127,7 @@ describe('codegen', () => {
     // static
     assertCodegen(
       '<p class="class1">hello world</p>',
-      'with(this){return _m(0)}',
-      [`with(this){return _h('p',{staticClass:"class1"},["hello world"])}`]
+      `with(this){return _h('p',{staticClass:"class1"},["hello world"])}`,
     )
     // dynamic
     assertCodegen(
@@ -169,8 +167,7 @@ describe('codegen', () => {
   it('generate static attrs', () => {
     assertCodegen(
       '<input name="field1">',
-      `with(this){return _m(0)}`,
-      [`with(this){return _h('input',{attrs:{"name":"field1"}})}`]
+      `with(this){return _h('input',{attrs:{"name":"field1"}})}`
     )
   })
 
@@ -297,22 +294,22 @@ describe('codegen', () => {
   it('generate component with inline-template', () => {
     // have "inline-template'"
     assertCodegen(
-      '<my-component inline-template><p>hello world</p></my-component>',
-      `with(this){return _h('my-component',{inlineTemplate:{render:function(){with(this){return _m(0)}},staticRenderFns:[function(){with(this){return _h('p',["hello world"])}}]}})}`
+      '<my-component inline-template><p><span>hello world</span></p></my-component>',
+      `with(this){return _h('my-component',{inlineTemplate:{render:function(){with(this){return _m(0)}},staticRenderFns:[function(){with(this){return _h('p',[_h('span',["hello world"])])}}]}})}`
     )
     // "have inline-template attrs, but not having extactly one child element
     assertCodegen(
       '<my-component inline-template><hr><hr></my-component>',
-      `with(this){return _h('my-component',{inlineTemplate:{render:function(){with(this){return _m(0)}},staticRenderFns:[function(){with(this){return _h('hr')}}]}})}`
+      `with(this){return _h('my-component',{inlineTemplate:{render:function(){with(this){return _h('hr')}},staticRenderFns:[]}})}`
     )
     expect('Inline-template components must have exactly one child element.').toHaveBeenWarned()
   })
 
   it('generate static trees inside v-for', () => {
     assertCodegen(
-      `<div><div v-for="i in 10"><span></span></div></div>`,
+      `<div><div v-for="i in 10"><p><span></span></p></div></div>`,
       `with(this){return _h('div',[_l((10),function(i){return _h('div',[_m(0,true)])})])}`,
-      [`with(this){return _h('span')}`]
+      [`with(this){return _h('p',[_h('span')])}`]
     )
   })
 

+ 10 - 3
test/unit/modules/compiler/optimizer.spec.js

@@ -4,11 +4,18 @@ import { baseOptions } from 'web/compiler/index'
 
 describe('optimizer', () => {
   it('simple', () => {
-    const ast = parse('<h1 id="section1">hello world</h1>', baseOptions)
+    const ast = parse('<h1 id="section1"><span>hello world</span></h1>', baseOptions)
     optimize(ast, baseOptions)
     expect(ast.static).toBe(true) // h1
     expect(ast.staticRoot).toBe(true)
-    expect(ast.children[0].static).toBe(true) // text node
+    expect(ast.children[0].static).toBe(true) // span
+  })
+
+  it('skip simple nodes', () => {
+    const ast = parse('<h1 id="section1">hello</h1>', baseOptions)
+    optimize(ast, baseOptions)
+    expect(ast.static).toBe(true)
+    expect(ast.staticRoot).toBe(false) // this is too simple to warrant a static tree
   })
 
   it('interpolation', () => {
@@ -197,7 +204,7 @@ describe('optimizer', () => {
   })
 
   it('mark static trees inside v-for', () => {
-    const ast = parse(`<div><div v-for="i in 10"><span>hi</span></div></div>`, baseOptions)
+    const ast = parse(`<div><div v-for="i in 10"><p><span>hi</span></p></div></div>`, baseOptions)
     optimize(ast, baseOptions)
     expect(ast.children[0].children[0].staticRoot).toBe(true)
     expect(ast.children[0].children[0].staticInFor).toBe(true)