Skip to content

Commit

Permalink
fix(compiler-sfc): properly reuse hoisted asset imports
Browse files Browse the repository at this point in the history
fix #4581
  • Loading branch information
yyx990803 committed Sep 16, 2021
1 parent fc968d6 commit 06c5bf5
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 24 deletions.
Expand Up @@ -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 */))
}"
`;

Expand Down
Expand Up @@ -41,7 +41,8 @@ describe('compiler sfc: transform asset url', () => {
*/
test('support uri fragment', () => {
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()
Expand Down
55 changes: 34 additions & 21 deletions packages/compiler-sfc/src/templateTransformAssetUrl.ts
Expand Up @@ -5,6 +5,7 @@ import {
ExpressionNode,
NodeTransform,
NodeTypes,
SimpleExpressionNode,
SourceLocation,
TransformContext
} from '@vue/compiler-core'
Expand Down Expand Up @@ -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)
}
Expand Down

0 comments on commit 06c5bf5

Please sign in to comment.