vuejs/core · error · Error

On-the-fly template compilation is not supported in the ESM

Error message

On-the-fly template compilation is not supported in the ESM build of @vue/server-renderer. All templates must be pre-compiled into render functions.

What it means

Thrown by ssrCompile in @vue/server-renderer when the ESM build of the package is asked to compile a template string on the fly. On-the-fly SSR template compilation requires the compiler, which the ESM build deliberately excludes; the CJS build (__CJS__) still supports it. ssrCompile.ts:28 hard-fails for non-CJS builds. The intended workflow is to pre-compile templates into render functions.

Source

Thrown at packages/server-renderer/src/helpers/ssrCompile.ts:28

import * as Vue from '@vue/runtime-dom'
import * as helpers from '../internal'

type SSRRenderFunction = (
  context: any,
  push: PushFn,
  parentInstance: ComponentInternalInstance,
) => void

const compileCache: Record<string, SSRRenderFunction> = Object.create(null)

export function ssrCompile(
  template: string,
  instance: ComponentInternalInstance,
): SSRRenderFunction {
  // TODO: this branch should now work in ESM builds, enable it in a minor
  if (!__CJS__) {
    throw new Error(
      `On-the-fly template compilation is not supported in the ESM build of ` +
        `@vue/server-renderer. All templates must be pre-compiled into ` +
        `render functions.`,
    )
  }

  // TODO: This is copied from runtime-core/src/component.ts and should probably be refactored
  const Component = instance.type as ComponentOptions
  const { isCustomElement, compilerOptions } = instance.appContext.config
  const { delimiters, compilerOptions: componentCompilerOptions } = Component

  const finalCompilerOptions: CompilerOptions = extend(
    extend(
      {
        isCustomElement,
        delimiters,
      },
      compilerOptions,

View on GitHub (pinned to a2b40db9a8)

Solutions

  1. Pre-compile all templates: use SFC <template> blocks compiled by @vue/compiler-sfc at build time, or write render functions.
  2. If on-the-fly compilation is unavoidable, import the CJS build of @vue/server-renderer (and register the compiler) so __CJS__ is true.
  3. Register a runtime compiler via the app's compilerOptions only when using a build that supports it (CJS).
  4. Remove the `template` option from runtime components and replace with an imported render function.

Example fix

// before (ESM build)
const App = { template: '<div>{{ msg }}</div>' }
await renderToString(createApp(App))

// after
import { h } from 'vue'
const App = { render: () => h('div', msg.value) }
await renderToString(createApp(App))
Defensive patterns

Strategy: validation

Validate before calling

// Reject string templates before SSR when using the ESM build.
function assertNoStringTemplate(component: any) {
  if (typeof component.template === 'string') {
    throw new Error('Pre-compile templates; the ESM SSR build cannot compile on the fly.')
  }
}

Type guard

function hasStringTemplate(component: unknown): boolean {
  return !!component && typeof (component as any).template === 'string'
}

Prevention

When it happens

Trigger: Passing a `template` string option on a component that then gets server-rendered through renderToString/renderToStream from the ESM build of @vue/server-renderer. Using in-DOM/string templates in an SSR pipeline.

Common situations: Authoring components with the `template` option instead of render functions/<template> SFC blocks; running SSR through the ESM entry (default for modern Node ESM projects) instead of CJS; upgrading an SSR pipeline that previously bundled the CJS build.

Related errors


AI-assisted analysis of vuejs/core@a2b40db9a8 (2026-08-12). Data as JSON: /api/errors/2bf6d1041afc59d3. Report an issue: GitHub.