vitejs/vite · error · Error

terser not found. Since Vite v3, terser has become an option

Error message

terser not found. Since Vite v3, terser has become an optional dependency. You need to install it.

What it means

Since Vite v3 terser is an optional peer dependency and is loaded lazily by the terser plugin at packages/vite/src/node/plugins/terser.ts:33. If build.minify === 'terser' (or @vitejs/plugin-legacy needs it) and neither the user's project root nor Vite's own install directory can resolve 'terser', loadTerserPath throws. esbuild (the default) does not need terser.

Source

Thrown at packages/vite/src/node/plugins/terser.ts:33

   * when minifying files with terser.
   *
   * @default number of CPUs minus 1
   */
  maxWorkers?: number
}

let terserPath: string | undefined
function loadTerserPath(root: string) {
  if (terserPath) return terserPath

  // Try resolve from project root first, then the current vite installation path
  const resolved =
    nodeResolveWithVite('terser', undefined, { root }) ??
    nodeResolveWithVite('terser', _dirname, { root })
  if (resolved) return (terserPath = resolved)

  // Error if we can't find the package
  throw new Error(
    'terser not found. Since Vite v3, terser has become an optional dependency. You need to install it.',
  )
}

export function terserPlugin(config: ResolvedConfig): Plugin {
  const { maxWorkers, ...terserOptions } = config.build.terserOptions

  const makeWorker = () =>
    new WorkerWithFallback(
      () =>
        async (
          terserPath: string,
          code: string,
          options: TerserMinifyOptions,
        ) => {
          const terser: typeof import('terser') = await import(terserPath)
          try {
            return (await terser.minify(code, options)) as TerserMinifyOutput

View on GitHub (pinned to 89620f09af)

Solutions

  1. Run `npm i -D terser` (or pnpm/yarn add -D terser) in the project root so nodeResolveWithVite finds it.
  2. If you did not intend to use terser, set build.minify: 'esbuild' (the default) and remove any terserOptions config.
  3. For CI with optional deps stripped, install with --include=optional or add terser as a direct devDependency so it is never pruned.
  4. In a monorepo, ensure terser is installed in the same workspace that runs the build, or set Vite's resolve to look in the workspace root.

Example fix

// before
export default defineConfig({ build: { minify: 'terser' } })

// after (option A: keep terser)
//   npm i -D terser
// after (option B: drop terser)
export default defineConfig({ build: { minify: 'esbuild' } })
Defensive patterns

Strategy: validation

Validate before calling

import { createRequire } from 'node:module'
function terserAvailable(): boolean {
  try { createRequire(process.cwd() + '/package.json').resolve('terser'); return true }
  catch { return false }
}
if (config.build?.minify === 'terser' && !terserAvailable()) {
  throw new Error('terser minify requested but terser is not installed; run `npm i -D terser`')
}

Type guard

function hasTerser(cwd = process.cwd()): boolean {
  try { createRequire(cwd + '/package.json').resolve('terser'); return true }
  catch { return false }
}

Prevention

When it happens

Trigger: Setting build.minify: 'terser' in vite.config; using @vitejs/plugin-legacy which forces the terser plugin via applyToEnvironment; running a build in a fresh install where terser was pruned as an optional dep; a corrupted node_modules where terser's package.json exists but its main file is missing.

Common situations: Copying a vite.config from a v2 project (terser was the default then) into a v3+ project without adding terser; CI caching node_modules with --omit=optional discarding terser; monorepo hoisting leaving terser only in a sibling workspace so it resolves from project root but not from Vite's install dir.

Related errors


AI-assisted analysis of vitejs/vite@89620f09af (2026-08-03). Data as JSON: /data/errors/8cfdfe3e462d549b.json. Report an issue: GitHub.