From 06c5bf53abc8143acb92e25b21394a79e11170d8 Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 16 Sep 2021 13:33:02 -0400 Subject: [PATCH] fix(compiler-sfc): properly reuse hoisted asset imports fix #4581 --- .../templateTransformAssetUrl.spec.ts.snap | 7 ++- .../templateTransformAssetUrl.spec.ts | 3 +- .../src/templateTransformAssetUrl.ts | 55 ++++++++++++------- 3 files changed, 41 insertions(+), 24 deletions(-) diff --git a/packages/compiler-sfc/__tests__/__snapshots__/templateTransformAssetUrl.spec.ts.snap b/packages/compiler-sfc/__tests__/__snapshots__/templateTransformAssetUrl.spec.ts.snap index ecc6738450f..753f3f9a524 100644 --- a/packages/compiler-sfc/__tests__/__snapshots__/templateTransformAssetUrl.spec.ts.snap +++ b/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`] = ` -"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' const _hoisted_1 = _imports_0 + '#fragment' 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 */)) }" `; diff --git a/packages/compiler-sfc/__tests__/templateTransformAssetUrl.spec.ts b/packages/compiler-sfc/__tests__/templateTransformAssetUrl.spec.ts index ba25358371c..d07b9226686 100644 --- a/packages/compiler-sfc/__tests__/templateTransformAssetUrl.spec.ts +++ b/packages/compiler-sfc/__tests__/templateTransformAssetUrl.spec.ts @@ -41,7 +41,8 @@ describe('compiler sfc: transform asset url', () => { */ test('support uri fragment', () => { const result = compileWithAssetUrls( - '' + '' + + '' ) expect(result.code).toMatchSnapshot() diff --git a/packages/compiler-sfc/src/templateTransformAssetUrl.ts b/packages/compiler-sfc/src/templateTransformAssetUrl.ts index c65a47c2277..4246817dff8 100644 --- a/packages/compiler-sfc/src/templateTransformAssetUrl.ts +++ b/packages/compiler-sfc/src/templateTransformAssetUrl.ts @@ -5,6 +5,7 @@ import { ExpressionNode, NodeTransform, NodeTypes, + SimpleExpressionNode, SourceLocation, TransformContext } from '@vue/compiler-core' @@ -153,30 +154,42 @@ function getImportsExpressionExp( context: TransformContext ): ExpressionNode { 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 { + name = `_imports_${context.imports.length}` + exp = createSimpleExpression(name, false, loc, ConstantTypes.CAN_HOIST) + context.imports.push({ exp, path }) + } + + if (!hash) { 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 { return createSimpleExpression(`''`, false, loc, ConstantTypes.CAN_HOIST) }