@vue/server-renderer <img> inside slot leads to double import of same asset
Version
3.0.0
Reproduction link
https://github.com/BobbySpoon/vue-compiler-ssr-staticAsset-slot
Steps to reproduce
This is a modified version of #2379. I did some further investigation. Actually the issue is not router-link based, but slot-based. See below for details.
const { compileTemplate } = require('@vue/compiler-sfc');
const { code } = compileTemplate({
source: "<slot-test><img class='logo' src='./logo.png' /></slot-test>",
inMap: undefined,
filename: 'C:\\some\\file',
ssr: true,
compiler: undefine
compilerOptions: { scopeId: null, bindingMetadata: {} },
transformAssetUrls: true,
});
console.log(code);
What is expected?
No duplicate import of same asset.
What is actually happening?
During compilation @vue/compiler-ssr (lines 250ff) is creating a clone of node (fallback vnode-based branch) which is being traversed by @vue/compiler-dom. (@vue/compiler-ssr lines 387 [function subTransform(node, options, parentContext) {..}]. In a next step, some properties of the context of the cloned node (childcontext) are being added to the parentcontext. Since no checks are being performed, parentcontext ends up with same import _imports_0 from './logo.png' twice (since transformAssetUrl (@vue/compiler-sfc lines 335) is being called both on parent and clone)
I am not completely aware of why the fallback-branch has to be created, so I'm also not very sure on how to fix this. Most obvious to me would be to check if path in childcontext.imports already exists in parentcontext.imports. On the other hand, I feel like this is always the case since the same traversion is being performed on both parent and child (clone), so maybe leave out transformAssetUrl when traversing the clone?
This can also be reproduced by compiling a simple template (for SSR):
<div>
<img src="./logo.png">
<img src="./logo.png">
</div>
SyntaxError: /Users/Razvan/work/test/v2/src/pages/Index.vue: Identifier '_imports_0' has already been declared (4:7)
2 | import { ssrRenderComponent as _ssrRenderComponent, ssrRenderAttr as _ssrRenderAttr, ssrInterpolate as _ssrInterpolate } from "@vue/server-renderer"
3 | import _imports_0 from './logo.png'
> 4 | import _imports_0 from './logo.png'