perf: support only attaching slot scope ids when necessary

This is done by adding the `slotted: false` option to:

- compiler-dom
- compiler-ssr
- compiler-sfc (forwarded to template compiler)

At runtime, only slotted component will render slot fragments with
slot scope Ids. For SSR, only slotted component will add slot scope Ids
to rendered slot content. This should improve both runtime performance
and reduce SSR rendered markup size.

Note: requires SFC tooling (e.g. `vue-loader` and `vite`) to pass on
the `slotted` option from the SFC descriptoer to the `compileTemplate`
call.
This commit is contained in:
Evan You
2021-03-05 12:12:49 -05:00
parent f74b16ccfe
commit 02cbbb718c
11 changed files with 110 additions and 31 deletions

View File

@@ -170,6 +170,22 @@ h1 { color: red }
expect(errors.length).toBe(0)
})
test('slotted detection', async () => {
expect(parse(`<template>hi</template>`).descriptor.slotted).toBe(false)
expect(
parse(`<template>hi</template><style>h1{color:red;}</style>`).descriptor
.slotted
).toBe(false)
expect(
parse(`<template>hi</template><style>:slotted(h1){color:red;}</style>`)
.descriptor.slotted
).toBe(true)
expect(
parse(`<template>hi</template><style>::v-slotted(h1){color:red;}</style>`)
.descriptor.slotted
).toBe(true)
})
test('error tolerance', () => {
const { errors } = parse(`<template>`)
expect(errors.length).toBe(1)

View File

@@ -45,6 +45,7 @@ export interface SFCTemplateCompileOptions {
filename: string
id: string
scoped?: boolean
slotted?: boolean
isProd?: boolean
ssr?: boolean
ssrCssVars?: string[]
@@ -158,6 +159,7 @@ function doCompileTemplate({
filename,
id,
scoped,
slotted,
inMap,
source,
ssr = false,
@@ -204,6 +206,7 @@ function doCompileTemplate({
? genCssVarsFromList(ssrCssVars, shortId, isProd)
: '',
scopeId: scoped ? longId : undefined,
slotted,
...compilerOptions,
nodeTransforms: nodeTransforms.concat(compilerOptions.nodeTransforms || []),
filename,

View File

@@ -59,6 +59,9 @@ export interface SFCDescriptor {
styles: SFCStyleBlock[]
customBlocks: SFCBlock[]
cssVars: string[]
// whether the SFC uses :slotted() modifier.
// this is used as a compiler optimization hint.
slotted: boolean
}
export interface SFCParseResult {
@@ -100,7 +103,8 @@ export function parse(
scriptSetup: null,
styles: [],
customBlocks: [],
cssVars: []
cssVars: [],
slotted: false
}
const errors: (CompilerError | SyntaxError)[] = []
@@ -231,6 +235,10 @@ export function parse(
warnExperimental(`v-bind() CSS variable injection`, 231)
}
// check if the SFC uses :slotted
const slottedRE = /(?:::v-|:)slotted\(/
descriptor.slotted = descriptor.styles.some(s => slottedRE.test(s.content))
const result = {
descriptor,
errors