vuejs/core · error · Error

[@vue/compiler-sfc] Style preprocessing in the browser build

Error message

[@vue/compiler-sfc] Style preprocessing in the browser build must provide the `preprocessCustomRequire` option to return the in-browser version of the preprocessor.

What it means

Thrown by the internal preprocess() helper in @vue/compiler-sfc when style preprocessing is requested in a browser build (__ESM_BROWSER__ or __GLOBAL__) without a preprocessCustomRequire option. Preprocessors (sass, less, stylus) are Node modules; in the browser the caller must supply an in-browser replacement. The guard at compileStyle.ts:226 fires before the preprocessor is invoked.

Source

Thrown at packages/compiler-sfc/src/compileStyle.ts:226

  } catch (e: any) {
    errors.push(e)
  }

  return {
    code: code || ``,
    map: outMap && outMap.toJSON(),
    errors,
    rawResult: result,
    dependencies,
  }
}

function preprocess(
  options: SFCStyleCompileOptions,
  preprocessor: StylePreprocessor,
): StylePreprocessorResults {
  if ((__ESM_BROWSER__ || __GLOBAL__) && !options.preprocessCustomRequire) {
    throw new Error(
      `[@vue/compiler-sfc] Style preprocessing in the browser build must ` +
        `provide the \`preprocessCustomRequire\` option to return the in-browser ` +
        `version of the preprocessor.`,
    )
  }

  return preprocessor(
    options.source,
    options.inMap || options.map,
    {
      filename: options.filename,
      ...options.preprocessOptions,
    },
    options.preprocessCustomRequire,
  )
}

View on GitHub (pinned to a2b40db9a8)

Solutions

  1. Provide preprocessCustomRequire returning an in-browser preprocessor bundle (e.g. an inlined sass.js, less.browser), keyed by the preprocessLang.
  2. Move style preprocessing to the build step and ship only plain CSS to the browser.
  3. Strip the preprocessLang from options when targeting the browser build if preprocessor support is not needed.

Example fix

// before (browser build)
compileStyle({ filename: 'x.css', source, preprocessLang: 'scss' })

// after
compileStyle({
  filename: 'x.css',
  source,
  preprocessLang: 'scss',
  preprocessCustomRequire: lang => (lang === 'scss' ? inBrowserSass : undefined),
})
Defensive patterns

Strategy: validation

Validate before calling

// Ensure preprocessCustomRequire is present whenever a preprocessor is used in the browser.
function safeCompileStyleBrowser(opts) {
  if (opts.preprocessLang && !opts.preprocessCustomRequire && isBrowserBuild) {
    throw new Error('preprocessCustomRequire required for browser style preprocessing')
  }
  return compileStyle(opts)
}

Type guard

function hasPreprocessCustomRequire(opts: unknown): boolean {
  return !!opts && typeof (opts as any).preprocessCustomRequire === 'function'
}

Prevention

When it happens

Trigger: Calling compileStyle({ preprocessLang: 'scss', ... }) from the browser build of @vue/compiler-sfc without preprocessCustomRequire; attempting in-browser SCSS/Less/Stylus compilation against the global or esm-browser entry.

Common situations: A live in-browser SFC playground that ships the browser build; tooling that lets end users author <style lang="scss"> at runtime.

Related errors


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