vuejs/core · error · Error

[@vue/compiler-sfc] Template preprocessing in the browser bu

Error message

[@vue/compiler-sfc] Template preprocessing in the browser build must provide the `preprocessCustomRequire` option to return the in-browser version of the preprocessor in the shape of { render(): string }.

What it means

Thrown by compileTemplate in @vue/compiler-sfc when template preprocessing is requested in a browser build (__ESM_BROWSER__ or __GLOBAL__), a preprocessLang is set, but no preprocessCustomRequire is given. The browser build cannot Node-require consolidate preprocessors, so the caller must return an object shaped { render(): string }. The guard at compileTemplate.ts:115 fires before resolving the preprocessor.

Source

Thrown at packages/compiler-sfc/src/compileTemplate.ts:115

      res = _res
    },
  )

  if (err) throw err
  return res
}

export function compileTemplate(
  options: SFCTemplateCompileOptions,
): SFCTemplateCompileResults {
  const { preprocessLang, preprocessCustomRequire } = options

  if (
    (__ESM_BROWSER__ || __GLOBAL__) &&
    preprocessLang &&
    !preprocessCustomRequire
  ) {
    throw new Error(
      `[@vue/compiler-sfc] Template preprocessing in the browser build must ` +
        `provide the \`preprocessCustomRequire\` option to return the in-browser ` +
        `version of the preprocessor in the shape of { render(): string }.`,
    )
  }

  const preprocessor = preprocessLang
    ? preprocessCustomRequire
      ? preprocessCustomRequire(preprocessLang)
      : __ESM_BROWSER__
        ? undefined
        : consolidate[preprocessLang as keyof typeof consolidate]
    : false
  if (preprocessor) {
    try {
      return doCompileTemplate({
        ...options,
        source: preprocess(options, preprocessor),

View on GitHub (pinned to a2b40db9a8)

Solutions

  1. Supply preprocessCustomRequire(preprocessLang) returning { render(): string } for each supported language (e.g. bundle pug for the browser).
  2. Pre-compile templates at build time so the browser never needs to preprocess.
  3. Resolve @vue/compiler-sfc to its Node build in your bundler config so consolidate can be required.

Example fix

// before (browser build)
compileTemplate({ filename: 'x.vue', source: 'div#x hello', preprocessLang: 'pug' })

// after
compileTemplate({
  filename: 'x.vue',
  source: 'div#x hello',
  preprocessLang: 'pug',
  preprocessCustomRequire: lang => (lang === 'pug' ? bundledPug : undefined),
})
Defensive patterns

Strategy: validation

Validate before calling

// Require preprocessCustomRequire for browser template preprocessing.
function safeCompileTemplateBrowser(opts) {
  if (opts.preprocessLang && !opts.preprocessCustomRequire && isBrowserBuild) {
    throw new Error('preprocessCustomRequire required for browser template preprocessing')
  }
  return compileTemplate(opts)
}

Type guard

function templatePreprocessReadyBrowser(opts: unknown): boolean {
  if (!opts) return true
  const o = opts as any
  if (!o.preprocessLang) return true
  return typeof o.preprocessCustomRequire === 'function'
}

Prevention

When it happens

Trigger: Calling compileTemplate({ preprocessLang: 'pug', source }) from the browser/global build of @vue/compiler-sfc without preprocessCustomRequire; an in-browser SFC compiler playground that allows pug/handlebars/etc. templates.

Common situations: Shipping a runtime template compiler to the browser; bundlers accidentally resolving the browser entry of compiler-sfc for a Node build pipeline that expected consolidate.

Related errors


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