Library mode

Vite · Advanced · 12 min

Component libraries and SDKs need different output than apps.

An app build produces an HTML entry and hashed assets. A library needs stable file names, ESM (and sometimes CommonJS) output, and must not bundle its dependencies. Vite's library mode handles this:

  • build.lib.entry: one or more entry files (an object for multiple entry points).
  • build.lib.formats: defaults to ['es', 'umd'] for a single entry; ['es', 'cjs'] is common for npm packages. name is required for umd/iife (the global variable).
  • build.lib.fileName: base name for output files.
  • build.rolldownOptions.external: dependencies and peer dependencies that consumers install, e.g. react, react/jsx-runtime. Otherwise you ship a second copy of React inside your package.

What Vite does not do for you:

  • Type declarations: run tsc --emitDeclarationOnly or a plugin such as vite-plugin-dts.
  • package.json: point exports (with types, import, require conditions) at the generated files and list them in files.
  • CSS is emitted as a separate file that consumers must import; document it.

For pure TypeScript libraries without CSS or framework transforms, dedicated tools (tsdown, built on Rolldown, or plain tsc) are often simpler. Library mode shines for component libraries that need Vite's CSS and framework plugins.

Example

// vite.config.js
import { defineConfig } from "vite";
import { fileURLToPath } from "node:url";

export default defineConfig({
  build: {
    lib: {
      entry: fileURLToPath(new URL("./lib/index.js", import.meta.url)),
      formats: ["es", "cjs"],
      fileName: "ann-dates",        // dist/ann-dates.js and dist/ann-dates.cjs
    },
    rolldownOptions: {
      external: ["date-fns"],       // a dependency: don't bundle it
    },
  },
});
// package.json:
//   "exports": { ".": { "import": "./dist/ann-dates.js", "require": "./dist/ann-dates.cjs" } },
//   "files": ["dist"], "dependencies": { "date-fns": "^4.1.0" }
// dist/ann-dates.js starts with: import { format as e } from "date-fns";

Remember

  • build.lib sets entry, formats and file names
  • Externalize dependencies and peer dependencies
  • Generate .d.ts separately; wire exports and files yourself
  • Consider tsdown or tsc for plain TypeScript libraries

Watch out for

  • Forgetting to externalize React in a component library, shipping a second React copy.

Check yourself

  1. Why mark `react` as external in a React component library build?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: vite.dev/guide/build#library-mode