vitejs/vite · error · Error

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

Error message

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

What it means

terserPlugin lazily resolves the 'terser' module from the project root, then from Vite's own install dir. If neither resolves, it throws because terser was made an optional peer dependency in Vite v3. The throw happens the first time build.minify === 'terser' triggers terser code path.

Solutions

  1. Install terser: `npm install --save-dev terser`.
  2. Or switch to the default esbuild minifier (build.minify: 'esbuild') which needs no extra install.
  3. Verify the install lands in the project root node_modules so nodeResolveWithVite finds it.
  4. Pin a terser version compatible with your Vite if a newer terser breaks output.

Example fix

// before (vite.config.ts)
build: { minify: 'terser' }
// after — option A: install it
// npm i -D terser
// option B: use the built-in
build: { minify: 'esbuild' }
Defensive patterns

Strategy: validation

Validate before calling

import { createRequire } from 'node:module'
function terserAvailable(root) {
  const require = createRequire(`${root}/`)
  try { require.resolve('terser'); return true } catch { return false }
}
if (config.build?.minify === 'terser' && !terserAvailable(process.cwd())) {
  throw new Error('Install terser: npm i -D terser')
}

Prevention

When it happens

Trigger: Setting build.minify to 'terser' (or letting a config/plugin select it) without having terser in node_modules. loadTerserPath is called when the terser plugin initializes its worker.

Common situations: Pre-v3 projects upgrading to Vite 3+ where terser was previously bundled; CI caches that dropped the optional dep; or copy-pasted configs that set minify: 'terser' without installing it.

Related errors


AI-assisted analysis of vitejs/vite@b4d66fee14 (2026-08-11). Data as JSON: /api/errors/8cfdfe3e462d549b. Report an issue: GitHub.

Appendix: 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 b4d66fee14)