diff --git a/packages/compiler-core/src/codegen.ts b/packages/compiler-core/src/codegen.ts index 41f6e4c77..cc0637fc2 100644 --- a/packages/compiler-core/src/codegen.ts +++ b/packages/compiler-core/src/codegen.ts @@ -44,7 +44,8 @@ import { CREATE_TEXT, PUSH_SCOPE_ID, POP_SCOPE_ID, - WITH_SCOPE_ID + WITH_SCOPE_ID, + CREATE_BLOCK } from './runtimeHelpers' import { ImportItem } from './transform' @@ -333,14 +334,28 @@ function genModulePreamble( context: CodegenContext, genScopeId: boolean ) { - const { push, helper, newline, scopeId, runtimeModuleName } = context - // generate import statements for helpers - if (genScopeId) { - ast.helpers.push(WITH_SCOPE_ID) - if (ast.hoists.length) { - ast.helpers.push(PUSH_SCOPE_ID, POP_SCOPE_ID) + const { push, helper, newline, scopeId, runtimeModuleName, ssr } = context + + if (!__BROWSER__) { + // in ssr mode, `withId` helper is only needed if the template contains + // de-optimized component slots (which uses the createVNode helper) + if ( + ssr && + !( + ast.helpers.includes(CREATE_VNODE) || ast.helpers.includes(CREATE_BLOCK) + ) + ) { + genScopeId = false + } + if (genScopeId) { + ast.helpers.push(WITH_SCOPE_ID) + if (ast.hoists.length) { + ast.helpers.push(PUSH_SCOPE_ID, POP_SCOPE_ID) + } } } + + // generate import statements for helpers if (ast.helpers.length) { push( `import { ${ast.helpers.map(helper).join(', ')} } from ${JSON.stringify( @@ -348,21 +363,25 @@ function genModulePreamble( )}\n` ) } - if (!__BROWSER__ && ast.ssrHelpers && ast.ssrHelpers.length) { - push( - `import { ${ast.ssrHelpers - .map(helper) - .join(', ')} } from "@vue/server-renderer"\n` - ) - } - if (ast.imports.length) { - genImports(ast.imports, context) - newline() - } - if (genScopeId) { - push(`const withId = ${helper(WITH_SCOPE_ID)}("${scopeId}")`) - newline() + + if (!__BROWSER__) { + if (ast.ssrHelpers && ast.ssrHelpers.length) { + push( + `import { ${ast.ssrHelpers + .map(helper) + .join(', ')} } from "@vue/server-renderer"\n` + ) + } + if (ast.imports.length) { + genImports(ast.imports, context) + newline() + } + if (genScopeId) { + push(`const withId = ${helper(WITH_SCOPE_ID)}("${scopeId}")`) + newline() + } } + genHoists(ast.hoists, context) newline() push(`export `) diff --git a/packages/compiler-core/src/options.ts b/packages/compiler-core/src/options.ts index d195cf393..f88b007b5 100644 --- a/packages/compiler-core/src/options.ts +++ b/packages/compiler-core/src/options.ts @@ -49,6 +49,8 @@ export interface TransformOptions { // analysis to determine if a handler is safe to cache. // - Default: false cacheHandlers?: boolean + // SFC scoped styles ID + scopeId?: string | null ssr?: boolean onError?: (error: CompilerError) => void } diff --git a/packages/compiler-core/src/transform.ts b/packages/compiler-core/src/transform.ts index 81b386998..578e08d8e 100644 --- a/packages/compiler-core/src/transform.ts +++ b/packages/compiler-core/src/transform.ts @@ -118,6 +118,7 @@ function createTransformContext( nodeTransforms = [], directiveTransforms = {}, isBuiltInComponent = NOOP, + scopeId = null, ssr = false, onError = defaultOnError }: TransformOptions @@ -130,6 +131,7 @@ function createTransformContext( nodeTransforms, directiveTransforms, isBuiltInComponent, + scopeId, ssr, onError, diff --git a/packages/compiler-ssr/src/index.ts b/packages/compiler-ssr/src/index.ts index 2a0ba788f..e12acde64 100644 --- a/packages/compiler-ssr/src/index.ts +++ b/packages/compiler-ssr/src/index.ts @@ -31,6 +31,7 @@ export function compile( // apply DOM-specific parsing options ...parserOptions, ssr: true, + scopeId: options.mode === 'function' ? null : options.scopeId, // always prefix since compiler-ssr doesn't have size concern prefixIdentifiers: true, // disalbe optimizations that are unnecessary for ssr diff --git a/packages/compiler-ssr/src/transforms/ssrTransformElement.ts b/packages/compiler-ssr/src/transforms/ssrTransformElement.ts index df409ef2c..cb35c3316 100644 --- a/packages/compiler-ssr/src/transforms/ssrTransformElement.ts +++ b/packages/compiler-ssr/src/transforms/ssrTransformElement.ts @@ -246,6 +246,10 @@ export const ssrTransformElement: NodeTransform = (node, context) => { removeStaticBinding(openTag, 'class') } + if (context.scopeId) { + openTag.push(` ${context.scopeId}`) + } + openTag.push(`>`) if (rawChildren) { openTag.push(rawChildren)