Zero-config library builds
npm install @b9g/libuildZero-config library builds with ESBuild.
Libuild is a build tool for JavaScript/TypeScript libraries which publish to
NPM. It solves ESM/CJS support, type generation, and produces clean packages
with just the files and configuration needed by consumers.
``bash`
npm install -D @b9g/libuild
bun add -d @b9g/libuild
`bashBuild your library (development mode - no package.json changes)
libuild build
Features
- No configuration - Source files and standard package.json are all you need
- Multiple formats - Supports ESM, CJS, UMD, and generates d.ts files
- Clean output - Only necessary files and fields go into the package
- Development-friendly - NPM link just works and changes can be saved to package.json
Convention = Configuration
$3
- Library modules: All top-level .js/.ts files in src/ (excluding _ prefixed files)
- CLI binaries: Any file referenced in package.json bin field gets compiled to standalone executable
- UMD builds: If src/umd.ts exists, creates browser-compatible UMD build$3
- Structure-preserving: src/index.ts → dist/src/index.js (maintains src/ directory)
- ESM: .js files with ES module syntax
- CommonJS: .cjs files for Node.js compatibility
- TypeScript: .d.ts declaration files for all modules (when TypeScript is available)
- Module augmentation: declare module blocks are preserved in .d.ts output
- Code splitting: Dynamic imports create chunks in dist/src/_chunks/
- Clean package.json: Optimized for consumers (no dev scripts)$3
- ESM-only: Remove the main field from package.json to skip CommonJS builds
- CommonJS detection: Presence of main field enables .cjs builds
- UMD builds: Add src/umd.ts for browser-compatible builds$3
- Legacy support: ./entry.js automatically aliases to ./entry
- Package.json: Always exported as ./package.json
- Custom exports: Existing exports in package.json are preserved and enhanced$3
- Development mode (default): Root package.json unchanged, no git noise
- --save mode: Root package.json updated to point to ./dist/src/* artifacts for npm link
- Dist package.json: Clean consumer-ready version with relative src/ paths
- Bin paths: Automatically transformed from src/ references to built artifacts
- Exports field: Generated for all entry points with proper types-first orderingExamples
$3
Given this structure:
`
src/
index.ts
utils.ts
_internal.ts # ignored (underscore prefix)
`Produces:
`
dist/
src/
index.js # ESM
index.cjs # CommonJS
index.d.ts # TypeScript declarations
utils.js
utils.cjs
utils.d.ts
package.json # Clean consumer version
`$3
`
package.json:
{
"bin": { "mytool": "src/cli.js" }
}src/
index.ts
cli.ts
`Produces:
`
dist/
src/
index.js
index.cjs
index.d.ts
cli.js # Compiled CLI
cli.cjs
cli.d.ts
package.json # bin: { "mytool": "./src/cli.js" }
`$3
To build only ESM (no CommonJS), remove the
main field:`json
// package.json
{
"name": "my-lib",
"module": "dist/src/index.js", // ESM entry
"types": "dist/src/index.d.ts"
// no "main" field = no CJS
}
`Produces:
`
dist/
src/
index.js # ESM only
index.d.ts
utils.js # ESM only
utils.d.ts
package.json # ESM-only exports
`$3
`
src/
index.ts
utils.ts
umd.ts # Browser build entry
`Produces:
`
dist/
src/
index.js
index.cjs
index.d.ts
utils.js
utils.cjs
utils.d.ts
umd.js # UMD browser build
package.json
`$3
Dual format (ESM + CommonJS):
`json
{
"main": "src/index.cjs",
"module": "src/index.js",
"types": "src/index.d.ts",
"exports": {
".": {
"types": "./src/index.d.ts",
"import": "./src/index.js",
"require": "./src/index.cjs"
},
"./utils": {
"types": "./src/utils.d.ts",
"import": "./src/utils.js",
"require": "./src/utils.cjs"
},
"./utils.js": {
"types": "./src/utils.d.ts",
"import": "./src/utils.js",
"require": "./src/utils.cjs"
},
"./package.json": "./package.json"
}
}
`ESM-only (no
main field in source):
`json
{
"module": "src/index.js",
"types": "src/index.d.ts",
"type": "module",
"exports": {
".": {
"types": "./src/index.d.ts",
"import": "./src/index.js"
},
"./utils": {
"types": "./src/utils.d.ts",
"import": "./src/utils.js"
},
"./utils.js": {
"types": "./src/utils.d.ts",
"import": "./src/utils.js"
},
"./package.json": "./package.json"
}
}
`Root package.json (with --save):
`json
{
"main": "./dist/src/index.cjs",
"module": "./dist/src/index.js",
"types": "./dist/src/index.d.ts",
"exports": {
".": {
"types": "./dist/src/index.d.ts",
"import": "./dist/src/index.js",
"require": "./dist/src/index.cjs"
}
}
}
`Commands
$3
Builds your library in development mode:
- Compiles all entry points to multiple formats
- Generates TypeScript declarations
- Creates optimized package.json files
- Preserves root package.json (no git noise)$3
Builds and updates root package.json for npm link:
- Everything from libuild build
- Updates root package.json to point to dist artifacts
- Perfect for testing with npm link`- Node.js 16+ or Bun 1.0+ (for running libuild)
- TypeScript (optional, for .d.ts generation)
- No runtime requirements for library consumers
MIT