O Vite Library Mode no Node.js permite empacotar bibliotecas JavaScript e TypeScript usando uma configuração orientada à distribuição. Ele é especialmente útil para componentes, SDKs de navegador, utilitários compartilhados e pacotes que precisam de uma página de demonstração durante o desenvolvimento.
O modo de biblioteca define entry points, formatos de saída, nomes de arquivos e integração com o pipeline do Vite. Porém, o autor ainda precisa externalizar dependências, gerar declarações TypeScript, definir exports, controlar CSS e testar o tarball em consumidores reais.
Neste guia, você aprenderá a configurar Vite Library Mode, criar entradas únicas ou múltiplas, gerar ESM e CommonJS, externalizar peer dependencies, exportar CSS, produzir tipos e publicar um pacote seguro.
Quando usar Library Mode?
Use quando o pacote é consumido por outras aplicações e precisa de:
- bundle ESM;
- formato CommonJS ou UMD;
- tree shaking;
- assets e CSS processados;
- servidor de desenvolvimento para exemplos;
- plugins do ecossistema Vite;
- build rápido e configuração pequena.
Para bibliotecas Node.js puras e fluxos avançados, Rollup, Rolldown ou esbuild podem oferecer controle mais direto.
Instalação
npm install --save-dev vite typescriptCrie uma estrutura:
my-lib/
├── src/
│ ├── index.ts
│ └── secondary.ts
├── vite.config.ts
├── tsconfig.json
└── package.jsonConfiguração de entrada única
import { resolve } from 'node:path';
import { defineConfig } from 'vite';
export default defineConfig({
build: {
lib: {
entry: resolve(import.meta.dirname, 'src/index.ts'),
name: 'MyLibrary',
fileName: 'my-library'
}
}
});A documentação atual de Library Mode do Vite explica que o preset gera formatos adequados à distribuição e permite personalizar o pipeline subjacente.
Scripts
{
"scripts": {
"dev": "vite",
"build": "vite build",
"build:watch": "vite build --watch",
"typecheck": "tsc --noEmit"
}
}Veja npm Scripts no Node.js.
Página de demonstração
Durante o desenvolvimento, index.html pode importar a biblioteca:
<script type="module" src="/demo/main.ts"></script>import { createWidget } from '../src/index.ts';
createWidget(document.querySelector('#app'));Isso oferece HMR e feedback rápido sem publicar o pacote.
Múltiplos entry points
export default defineConfig({
build: {
lib: {
entry: {
index: resolve(import.meta.dirname, 'src/index.ts'),
secondary: resolve(import.meta.dirname, 'src/secondary.ts')
}
}
}
});O package.json precisa expor cada entrada:
{
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.cjs"
},
"./secondary": {
"import": "./dist/secondary.js",
"require": "./dist/secondary.cjs"
}
}
}Consulte Exports e Imports no package.json.
Formatos
lib: {
entry: resolve(import.meta.dirname, 'src/index.ts'),
formats: ['es', 'cjs'],
fileName(format) {
return format === 'es' ? 'index.js' : 'index.cjs';
}
}Uma entrada única também pode gerar UMD quando consumidores usam script global. Para bibliotecas modernas, ESM costuma ser o formato principal.
Externalizando dependências
build: {
lib: { /* ... */ },
rolldownOptions: {
external: ['react', 'react-dom']
}
}Dependências que o consumidor fornece devem ficar externas. Isso evita duas cópias de React ou outro framework.
Peer dependencies
{
"peerDependencies": {
"react": "^19.0.0",
"react-dom": "^19.0.0"
}
}Teste todas as versões declaradas. Não use um range amplo apenas para evitar manutenção.
External automático
Uma função pode ler dependencies e peerDependencies:
const externals = [
...Object.keys(pkg.dependencies ?? {}),
...Object.keys(pkg.peerDependencies ?? {})
];
external(id) {
return externals.some(name =>
id === name || id.startsWith(`${name}/`)
);
}Decida conscientemente se dependencies devem ser empacotadas. Em uma biblioteca de navegador, incorporar utilitários pequenos pode simplificar consumo; em plugins e SDKs, externalização costuma ser preferível.
Globais para UMD
output: {
globals: {
react: 'React',
'react-dom': 'ReactDOM'
}
}Essa configuração só é necessária para formatos globais como UMD ou IIFE.
Package.json recomendado
{
"name": "@empresa/widget",
"version": "1.0.0",
"type": "module",
"files": ["dist"],
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
}
}
}TypeScript não é verificado pelo Vite
Vite transforma TypeScript, mas não executa typecheck completo. Mantenha:
npm run typecheckNo CI, execute typecheck antes da publicação. Consulte CI para Node.js com GitHub Actions.
Declarações TypeScript
Gere tipos com tsc:
{
"compilerOptions": {
"emitDeclarationOnly": true,
"declaration": true,
"declarationMap": true,
"outDir": "dist",
"rootDir": "src"
},
"include": ["src"]
}tsc -p tsconfig.types.jsonPlugins como vite-plugin-dts podem automatizar, mas executam código adicional e precisam ser avaliados. A etapa nativa é mais previsível quando a estrutura é simples.
CSS da biblioteca
Quando a biblioteca importa CSS:
import './style.css';O Vite gera um arquivo CSS separado. Exporte-o:
{
"exports": {
".": "./dist/index.js",
"./style.css": "./dist/my-library.css"
}
}Defina cssFileName para um nome estável quando necessário.
CSS inline ou separado?
CSS separado permite cache e import explícito. Injetar CSS pelo JavaScript pode facilitar widgets, mas cria efeitos colaterais e dificulta SSR. Documente a escolha.
Assets
Imagens, fontes e WASM importados podem ser copiados ou incorporados conforme o tamanho. Teste URLs no pacote instalado, não apenas no servidor local.
Variáveis de ambiente
No Library Mode, referências a import.meta.env podem ser substituídas durante o build. Não coloque segredos. Bibliotecas não devem fixar configuração do ambiente do consumidor.
Para valores dinâmicos, aceite opções:
createClient({
endpoint,
apiKey
});Define
define: {
__LIB_VERSION__: JSON.stringify(pkg.version)
}Use apenas metadados públicos. Tudo incorporado fica visível.
Tree shaking
Publique ESM, exports nomeados e módulos sem efeitos colaterais. No package.json:
{
"sideEffects": ["**/*.css"]
}Isso informa que JavaScript pode ser removido, mas imports de CSS devem ser preservados.
Minificação
Bibliotecas geralmente não precisam ser minificadas. O consumidor pode minificar com contexto completo. Entregar código legível melhora debug e auditoria.
Sourcemaps
build: {
sourcemap: true,
lib: { /* ... */ }
}Sourcemaps ajudam consumidores, mas podem aumentar tamanho e revelar fontes. Defina uma política.
Watch mode
vite build --watchUse para desenvolver junto com uma aplicação consumidora local. Mudanças no arquivo de configuração podem exigir reinício do processo.
Testando com npm pack
npm run typecheck
npm test
npm run build
npm pack --dry-run
npm packInstale o tarball em um projeto limpo:
npm install ../empresa-widget-1.0.0.tgzVeja Publicar Pacote no npm.
Testes de formatos
node --input-type=module -e "import('@empresa/widget').then(console.log)"
node -e "console.log(require('@empresa/widget'))"Para bibliotecas de navegador, crie também testes em navegadores reais com Playwright.
SSR
Se a biblioteca pode rodar em SSR, não acesse window ou document durante import. Faça a leitura dentro de funções ou proteja por ambiente.
Bibliotecas Node.js puras
Vite Library Mode é orientado principalmente a bibliotecas de navegador e frameworks. Para pacotes Node.js sem assets ou página demo, Rollup para Bibliotecas Node.js ou esbuild no Node.js pode ser mais direto.
Monorepos
Em npm Workspaces, cada pacote pode ter sua configuração ou compartilhar helpers. Não deixe dependências internas serem incorporadas quando devem permanecer como pacotes separados.
CI
- run: npm ci
- run: npm run lint
- run: npm run typecheck
- run: npm test
- run: npm run build
- run: npm pack --dry-runTeste o tarball em uma aplicação exemplo e armazene o pacote como artifact antes da release.
Segurança
- Fixe Vite e plugins.
- Não incorpore segredos.
- Externalize frameworks.
- Restrinja o campo files.
- Revise sourcemaps.
- Teste SSR.
- Publique com OIDC.
Erros comuns
- Sem external: framework é duplicado.
- Sem types: consumidores perdem IntelliSense.
- Exports incorretos: import ou require falha.
- CSS não exportado: estilos desaparecem.
- Import.meta.env com segredo: dado entra no bundle.
- Teste só no demo: pacote instalado quebra.
- Side effects false com CSS: bundler remove estilo.
- Usar Vite para backend sem necessidade: configuração fica indireta.
Configuração recomendada
import { resolve } from 'node:path';
import { defineConfig } from 'vite';
export default defineConfig({
build: {
sourcemap: true,
lib: {
entry: {
index: resolve(import.meta.dirname, 'src/index.ts'),
secondary: resolve(import.meta.dirname, 'src/secondary.ts')
},
formats: ['es', 'cjs']
},
rolldownOptions: {
external: ['react', 'react-dom']
}
}
});Conclusão
O Vite Library Mode no Node.js combina experiência de desenvolvimento rápida com um preset de build orientado à distribuição. Entradas, formatos, CSS e assets podem ser configurados sem montar toda a infraestrutura manualmente.
Externalize peer dependencies, gere declarations, defina exports e teste o tarball. Quando o pacote é validado fora do demo local, Vite se torna uma base eficiente para bibliotecas modernas.




