Skip to content

Commit 1cc0553

Browse files
authored
refactor: rewrite defineVaporAsyncComponent import to defineAsyncComponent in SSR + vapor mode (#14016)
This limits the defineVaporAsyncComponent only used in the `.vue` file in SSR revert 8974043
1 parent fe416ee commit 1cc0553

File tree

9 files changed

+191
-147
lines changed

9 files changed

+191
-147
lines changed

packages/compiler-sfc/__tests__/compileScript.spec.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1711,3 +1711,41 @@ describe('compileScript', () => {
17111711
expect(scriptAst).not.toBeDefined()
17121712
})
17131713
})
1714+
1715+
describe('vapor mode + ssr', () => {
1716+
test('rewrite defineVaporAsyncComponent import', () => {
1717+
const { content } = compile(
1718+
`
1719+
<script setup vapor>
1720+
import { defineVaporAsyncComponent } from 'vue'
1721+
</script>
1722+
`,
1723+
{
1724+
templateOptions: {
1725+
ssr: true,
1726+
},
1727+
},
1728+
)
1729+
expect(content).toContain(
1730+
`import { defineAsyncComponent as defineVaporAsyncComponent } from 'vue'`,
1731+
)
1732+
})
1733+
1734+
test('rewrite defineVaporAsyncComponent import with local name', () => {
1735+
const { content } = compile(
1736+
`
1737+
<script setup vapor>
1738+
import { defineVaporAsyncComponent as def } from 'vue'
1739+
</script>
1740+
`,
1741+
{
1742+
templateOptions: {
1743+
ssr: true,
1744+
},
1745+
},
1746+
)
1747+
expect(content).toContain(
1748+
`import { defineAsyncComponent as def } from 'vue'`,
1749+
)
1750+
})
1751+
})

packages/compiler-sfc/src/compileScript.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,23 @@ export function compileScript(
388388
const local = specifier.local.name
389389
const imported = getImportedName(specifier)
390390
const source = node.source.value
391+
392+
// rewrite defineVaporAsyncComponent import to defineAsyncComponent
393+
// in SSR + Vapor mode
394+
if (
395+
vapor &&
396+
ssr &&
397+
specifier.type === 'ImportSpecifier' &&
398+
source === 'vue' &&
399+
imported === 'defineVaporAsyncComponent'
400+
) {
401+
ctx.s.overwrite(
402+
specifier.start! + startOffset,
403+
specifier.end! + startOffset,
404+
`defineAsyncComponent as ${local}`,
405+
)
406+
}
407+
391408
const existing = ctx.userImports[local]
392409
if (source === 'vue' && MACROS.includes(imported)) {
393410
if (local === imported) {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
// for type generation only
2-
export * from './indexBase'
2+
export * from './index'
33
export * from '@vue/runtime-vapor'

packages/vue/src/index.ts

Lines changed: 107 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,107 @@
1-
export * from './indexBase'
2-
export * from './vaporAliases'
1+
// This entry is the "full-build" that includes both the runtime
2+
// and the compiler, and supports on-the-fly compilation of the template option.
3+
import { initDev } from './dev'
4+
import {
5+
type CompilerError,
6+
type CompilerOptions,
7+
compile,
8+
} from '@vue/compiler-dom'
9+
import {
10+
type RenderFunction,
11+
registerRuntimeCompiler,
12+
warn,
13+
} from '@vue/runtime-dom'
14+
import * as runtimeDom from '@vue/runtime-dom'
15+
import {
16+
NOOP,
17+
extend,
18+
genCacheKey,
19+
generateCodeFrame,
20+
isString,
21+
} from '@vue/shared'
22+
import type { InternalRenderFunction } from 'packages/runtime-core/src/component'
23+
24+
if (__DEV__) {
25+
initDev()
26+
}
27+
28+
const compileCache: Record<string, RenderFunction> = Object.create(null)
29+
30+
function compileToFunction(
31+
template: string | HTMLElement,
32+
options?: CompilerOptions,
33+
): RenderFunction {
34+
if (!isString(template)) {
35+
if (template.nodeType) {
36+
template = template.innerHTML
37+
} else {
38+
__DEV__ && warn(`invalid template option: `, template)
39+
return NOOP
40+
}
41+
}
42+
43+
const key = genCacheKey(template, options)
44+
const cached = compileCache[key]
45+
if (cached) {
46+
return cached
47+
}
48+
49+
if (template[0] === '#') {
50+
const el = document.querySelector(template)
51+
if (__DEV__ && !el) {
52+
warn(`Template element not found or is empty: ${template}`)
53+
}
54+
// __UNSAFE__
55+
// Reason: potential execution of JS expressions in in-DOM template.
56+
// The user must make sure the in-DOM template is trusted. If it's rendered
57+
// by the server, the template should not contain any user data.
58+
template = el ? el.innerHTML : ``
59+
}
60+
61+
const opts = extend(
62+
{
63+
hoistStatic: true,
64+
onError: __DEV__ ? onError : undefined,
65+
onWarn: __DEV__ ? e => onError(e, true) : NOOP,
66+
} as CompilerOptions,
67+
options,
68+
)
69+
70+
if (!opts.isCustomElement && typeof customElements !== 'undefined') {
71+
opts.isCustomElement = tag => !!customElements.get(tag)
72+
}
73+
74+
const { code } = compile(template, opts)
75+
76+
function onError(err: CompilerError, asWarning = false) {
77+
const message = asWarning
78+
? err.message
79+
: `Template compilation error: ${err.message}`
80+
const codeFrame =
81+
err.loc &&
82+
generateCodeFrame(
83+
template as string,
84+
err.loc.start.offset,
85+
err.loc.end.offset,
86+
)
87+
warn(codeFrame ? `${message}\n${codeFrame}` : message)
88+
}
89+
90+
// The wildcard import results in a huge object with every export
91+
// with keys that cannot be mangled, and can be quite heavy size-wise.
92+
// In the global build we know `Vue` is available globally so we can avoid
93+
// the wildcard object.
94+
const render = (
95+
__GLOBAL__ ? new Function(code)() : new Function('Vue', code)(runtimeDom)
96+
) as RenderFunction
97+
98+
// mark the function as runtime compiled
99+
;(render as InternalRenderFunction)._rc = true
100+
101+
return (compileCache[key] = render)
102+
}
103+
104+
registerRuntimeCompiler(compileToFunction)
105+
106+
export { compileToFunction as compile }
107+
export * from '@vue/runtime-dom'

packages/vue/src/indexBase.ts

Lines changed: 0 additions & 107 deletions
This file was deleted.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
export * from './runtimeBase'
1+
export * from './runtime'
22
export * from '@vue/runtime-vapor'

packages/vue/src/runtime.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,27 @@
1-
export * from './runtimeBase'
2-
export * from './vaporAliases'
1+
// This entry exports the runtime only, and is built as
2+
// `dist/vue.esm-bundler.js` which is used by default for bundlers.
3+
import { NOOP } from '@vue/shared'
4+
import { initDev } from './dev'
5+
import { type RenderFunction, warn } from '@vue/runtime-dom'
6+
7+
if (__DEV__) {
8+
initDev()
9+
}
10+
11+
export * from '@vue/runtime-dom'
12+
13+
export const compile = (_template: string): RenderFunction => {
14+
if (__DEV__) {
15+
warn(
16+
`Runtime compilation is not supported in this build of Vue.` +
17+
(__ESM_BUNDLER__
18+
? ` Configure your bundler to alias "vue" to "vue/dist/vue.esm-bundler.js".`
19+
: __ESM_BROWSER__
20+
? ` Use "vue.esm-browser.js" instead.`
21+
: __GLOBAL__
22+
? ` Use "vue.global.js" instead.`
23+
: ``) /* should not happen */,
24+
)
25+
}
26+
return NOOP
27+
}

packages/vue/src/runtimeBase.ts

Lines changed: 0 additions & 27 deletions
This file was deleted.

packages/vue/src/vaporAliases.ts

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)