Просмотр исходного кода

fix(compiler-sfc): properly reuse hoisted asset imports

fix #4581
Evan You 4 лет назад
Родитель
Сommit
06c5bf53ab

+ 5 - 2
packages/compiler-sfc/__tests__/__snapshots__/templateTransformAssetUrl.spec.ts.snap

@@ -33,14 +33,17 @@ export function render(_ctx, _cache) {
 `;
 `;
 
 
 exports[`compiler sfc: transform asset url support uri fragment 1`] = `
 exports[`compiler sfc: transform asset url support uri fragment 1`] = `
-"import { openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\"
+"import { createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\"
 import _imports_0 from '@svg/file.svg'
 import _imports_0 from '@svg/file.svg'
 
 
 
 
 const _hoisted_1 = _imports_0 + '#fragment'
 const _hoisted_1 = _imports_0 + '#fragment'
 
 
 export function render(_ctx, _cache) {
 export function render(_ctx, _cache) {
-  return (_openBlock(), _createElementBlock(\\"use\\", { href: _hoisted_1 }))
+  return (_openBlock(), _createElementBlock(_Fragment, null, [
+    _createElementVNode(\\"use\\", { href: _hoisted_1 }),
+    _createElementVNode(\\"use\\", { href: _hoisted_1 })
+  ], 64 /* STABLE_FRAGMENT */))
 }"
 }"
 `;
 `;
 
 

+ 2 - 1
packages/compiler-sfc/__tests__/templateTransformAssetUrl.spec.ts

@@ -41,7 +41,8 @@ describe('compiler sfc: transform asset url', () => {
    */
    */
   test('support uri fragment', () => {
   test('support uri fragment', () => {
     const result = compileWithAssetUrls(
     const result = compileWithAssetUrls(
-      '<use href="~@svg/file.svg#fragment"></use>'
+      '<use href="~@svg/file.svg#fragment"></use>' +
+        '<use href="~@svg/file.svg#fragment"></use>'
     )
     )
 
 
     expect(result.code).toMatchSnapshot()
     expect(result.code).toMatchSnapshot()

+ 34 - 21
packages/compiler-sfc/src/templateTransformAssetUrl.ts

@@ -5,6 +5,7 @@ import {
   ExpressionNode,
   ExpressionNode,
   NodeTransform,
   NodeTransform,
   NodeTypes,
   NodeTypes,
+  SimpleExpressionNode,
   SourceLocation,
   SourceLocation,
   TransformContext
   TransformContext
 } from '@vue/compiler-core'
 } from '@vue/compiler-core'
@@ -153,30 +154,42 @@ function getImportsExpressionExp(
   context: TransformContext
   context: TransformContext
 ): ExpressionNode {
 ): ExpressionNode {
   if (path) {
   if (path) {
-    const existing = context.imports.find(i => i.path === path)
-    if (existing) {
-      return existing.exp as ExpressionNode
-    }
-    const name = `_imports_${context.imports.length}`
-    const exp = createSimpleExpression(
-      name,
-      false,
-      loc,
-      ConstantTypes.CAN_HOIST
-    )
-    context.imports.push({ exp, path })
-    if (hash && path) {
-      return context.hoist(
-        createSimpleExpression(
-          `${name} + '${hash}'`,
-          false,
-          loc,
-          ConstantTypes.CAN_HOIST
-        )
-      )
+    let name: string
+    let exp: SimpleExpressionNode
+    const existingIndex = context.imports.findIndex(i => i.path === path)
+    if (existingIndex > -1) {
+      name = `_imports_${existingIndex}`
+      exp = context.imports[existingIndex].exp as SimpleExpressionNode
     } else {
     } else {
+      name = `_imports_${context.imports.length}`
+      exp = createSimpleExpression(name, false, loc, ConstantTypes.CAN_HOIST)
+      context.imports.push({ exp, path })
+    }
+
+    if (!hash) {
       return exp
       return exp
     }
     }
+
+    const hashExp = `${name} + '${hash}'`
+    const existingHoistIndex = context.hoists.findIndex(h => {
+      return (
+        h &&
+        h.type === NodeTypes.SIMPLE_EXPRESSION &&
+        !h.isStatic &&
+        h.content === hashExp
+      )
+    })
+    if (existingHoistIndex > -1) {
+      return createSimpleExpression(
+        `_hoisted_${existingHoistIndex + 1}`,
+        false,
+        loc,
+        ConstantTypes.CAN_HOIST
+      )
+    }
+    return context.hoist(
+      createSimpleExpression(hashExp, false, loc, ConstantTypes.CAN_HOIST)
+    )
   } else {
   } else {
     return createSimpleExpression(`''`, false, loc, ConstantTypes.CAN_HOIST)
     return createSimpleExpression(`''`, false, loc, ConstantTypes.CAN_HOIST)
   }
   }