Claude-skill-registry library-bundler

Configure build systems, optimize bundle size, manage exports for ESM/CJS/UMD, and publish packages to NPM with proper versioning

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/library-bundler" ~/.claude/skills/majiayu000-claude-skill-registry-library-bundler && rm -rf "$T"
manifest: skills/data/library-bundler/SKILL.md
source content

Library Bundler

Expert skill for building, bundling, and publishing component libraries to NPM. Specializes in modern build tools (tsup, Vite, Rollup), bundle optimization, multi-format exports, and package publishing workflows.

Core Capabilities

1. Build System Configuration

  • tsup: Fast TypeScript bundler with zero config
  • Vite: Modern build tool with HMR and optimization
  • Rollup: Powerful module bundler for libraries
  • esbuild: Extremely fast JavaScript bundler
  • Webpack: Full-featured bundler (when needed)

2. Bundle Optimization

  • Tree-shaking for dead code elimination
  • Code splitting for optimal loading
  • Minification (Terser, esbuild)
  • Compression (gzip, brotli)
  • Bundle size analysis
  • Dependency externalization
  • Chunk optimization

3. Multi-Format Support

  • ESM (ES Modules): Modern standard
  • CJS (CommonJS): Node.js compatibility
  • UMD (Universal Module Definition): Browser globals
  • IIFE: Self-executing browser bundles
  • Dual package support (ESM + CJS)

4. TypeScript Integration

  • Type declaration generation (.d.ts)
  • Declaration maps for IDE navigation
  • Type checking during build
  • Multiple tsconfig.json support
  • Path aliasing resolution

5. Package Publishing

  • NPM registry publishing
  • Semantic versioning (semver)
  • Changelog generation
  • Git tagging
  • Pre-publish validation
  • Scoped packages (@org/package)
  • Package provenance

6. Development Workflow

  • Watch mode for rapid iteration
  • Source maps for debugging
  • Hot Module Replacement (HMR)
  • Build caching
  • Parallel builds
  • Incremental compilation

Workflow

Phase 1: Build Configuration Setup

  1. Analyze Project Structure

    • Entry points (index.ts, components/)
    • Output formats needed (ESM, CJS, UMD)
    • External dependencies
    • Target environments (browsers, Node.js)
  2. Choose Build Tool

    • tsup: Best for simple TS libraries
    • Vite: Best for modern ESM-first libraries
    • Rollup: Best for maximum control
    • esbuild: Best for raw speed
  3. Configure package.json

    • Entry points (main, module, types, exports)
    • Build scripts
    • Files to include
    • Peer dependencies

Phase 2: Optimization

  1. Tree-Shaking Setup

    • Mark side effects in package.json
    • Use ESM imports/exports
    • Avoid namespace imports
    • Test tree-shaking effectiveness
  2. Bundle Size Analysis

    • Use bundle analyzer tools
    • Identify large dependencies
    • Consider alternatives
    • Externalize heavy deps
  3. Code Splitting

    • Split by route/feature
    • Shared chunk optimization
    • Dynamic imports where beneficial

Phase 3: Publication Preparation

  1. Version Management

    • Follow semantic versioning
    • Update package.json version
    • Create git tag
    • Generate changelog
  2. Pre-publish Checks

    • Run tests
    • Build all formats
    • Verify type declarations
    • Check bundle sizes
    • Test in consuming projects
  3. Publish to NPM

    • npm login
    • npm publish (or publish:dry-run)
    • Verify on npmjs.com
    • Test installation

Build Tool Configurations

tsup Configuration

// tsup.config.ts
import { defineConfig } from 'tsup'

export default defineConfig({
  entry: ['src/index.ts'],
  format: ['cjs', 'esm'],
  dts: true,
  splitting: false,
  sourcemap: true,
  clean: true,
  treeshake: true,
  minify: true,
  external: ['react', 'react-dom'],
  esbuildOptions(options) {
    options.banner = {
      js: '"use client"', // For React Server Components
    }
  },
})

Vite Library Mode

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { resolve } from 'path'
import dts from 'vite-plugin-dts'

export default defineConfig({
  plugins: [
    react(),
    dts({
      insertTypesEntry: true,
    }),
  ],
  build: {
    lib: {
      entry: resolve(__dirname, 'src/index.ts'),
      name: 'MyLibrary',
      formats: ['es', 'cjs', 'umd'],
      fileName: (format) => `my-library.${format}.js`,
    },
    rollupOptions: {
      external: ['react', 'react-dom'],
      output: {
        globals: {
          react: 'React',
          'react-dom': 'ReactDOM',
        },
      },
    },
    sourcemap: true,
    minify: 'esbuild',
  },
})

Rollup Configuration

// rollup.config.mjs
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import typescript from '@rollup/plugin-typescript'
import { terser } from 'rollup-plugin-terser'
import peerDepsExternal from 'rollup-plugin-peer-deps-external'
import postcss from 'rollup-plugin-postcss'

export default {
  input: 'src/index.ts',
  output: [
    {
      file: 'dist/index.cjs.js',
      format: 'cjs',
      sourcemap: true,
    },
    {
      file: 'dist/index.esm.js',
      format: 'esm',
      sourcemap: true,
    },
    {
      file: 'dist/index.umd.js',
      format: 'umd',
      name: 'MyLibrary',
      sourcemap: true,
      globals: {
        react: 'React',
        'react-dom': 'ReactDOM',
      },
    },
  ],
  plugins: [
    peerDepsExternal(),
    resolve(),
    commonjs(),
    typescript({
      tsconfig: './tsconfig.json',
      declaration: true,
      declarationDir: 'dist',
    }),
    postcss({
      extensions: ['.css'],
      minimize: true,
      inject: false,
      extract: 'styles.css',
    }),
    terser(),
  ],
  external: ['react', 'react-dom'],
}

Package.json Configuration

Modern Package.json (ESM-First)

{
  "name": "@myorg/ui-library",
  "version": "1.0.0",
  "description": "Modern React component library",
  "type": "module",
  "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"
    },
    "./button": {
      "types": "./dist/button.d.ts",
      "import": "./dist/button.js",
      "require": "./dist/button.cjs"
    },
    "./package.json": "./package.json"
  },
  "files": [
    "dist",
    "README.md",
    "LICENSE"
  ],
  "sideEffects": false,
  "scripts": {
    "build": "tsup",
    "dev": "tsup --watch",
    "prepublishOnly": "npm run build && npm test",
    "publish:dry": "npm publish --dry-run"
  },
  "peerDependencies": {
    "react": "^18.0.0",
    "react-dom": "^18.0.0"
  },
  "devDependencies": {
    "@types/react": "^18.2.0",
    "react": "^18.2.0",
    "tsup": "^8.0.0",
    "typescript": "^5.3.0"
  },
  "publishConfig": {
    "access": "public"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/myorg/ui-library"
  },
  "keywords": [
    "react",
    "components",
    "ui",
    "library"
  ],
  "author": "Your Name",
  "license": "MIT"
}

Dual Package (ESM + CJS)

{
  "name": "my-library",
  "version": "1.0.0",
  "type": "module",
  "exports": {
    ".": {
      "import": {
        "types": "./dist/index.d.ts",
        "default": "./dist/index.js"
      },
      "require": {
        "types": "./dist/index.d.cts",
        "default": "./dist/index.cjs"
      }
    }
  },
  "main": "./dist/index.cjs",
  "module": "./dist/index.js",
  "types": "./dist/index.d.ts"
}

Monorepo Package (Turborepo/Nx)

{
  "name": "@myorg/ui-components",
  "private": false,
  "version": "1.0.0",
  "exports": {
    "./button": {
      "types": "./dist/button.d.ts",
      "import": "./dist/button.js"
    },
    "./input": {
      "types": "./dist/input.d.ts",
      "import": "./dist/input.js"
    }
  },
  "typesVersions": {
    "*": {
      "button": ["./dist/button.d.ts"],
      "input": ["./dist/input.d.ts"]
    }
  }
}

TypeScript Configuration

Library tsconfig.json

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "jsx": "react-jsx",
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "removeComments": true,
    "strict": true,
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": false,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "noUncheckedIndexedAccess": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
}

Optimization Strategies

1. Tree-Shaking Optimization

// package.json
{
  "sideEffects": false
}

// Or specify files with side effects
{
  "sideEffects": ["*.css", "*.scss"]
}
// Use named exports (tree-shakeable)
export { Button } from './Button'
export { Input } from './Input'

// Avoid default exports for libraries
// ❌ export default { Button, Input }

2. Code Splitting Strategy

// tsup.config.ts
export default defineConfig({
  entry: {
    index: 'src/index.ts',
    button: 'src/components/Button/index.ts',
    input: 'src/components/Input/index.ts',
  },
  format: ['esm', 'cjs'],
  splitting: true, // Enable code splitting
  dts: true,
})

3. Bundle Size Analysis

# Install bundle analyzer
npm install -D rollup-plugin-visualizer

# Add to rollup config
import { visualizer } from 'rollup-plugin-visualizer'

plugins: [
  visualizer({
    filename: './dist/stats.html',
    open: true,
  }),
]

4. External Dependencies

// Don't bundle these (keep as peerDependencies)
external: [
  'react',
  'react-dom',
  'framer-motion',
  '@radix-ui/react-*',
]

// Regex pattern for dynamic externals
external: (id) => {
  return /^react/.test(id) || /^@radix-ui/.test(id)
}

5. Minification Options

// esbuild (fastest)
minify: true

// Terser (best compression)
import { terser } from 'rollup-plugin-terser'

plugins: [
  terser({
    compress: {
      drop_console: true,
      drop_debugger: true,
    },
    format: {
      comments: false,
    },
  }),
]

Publishing Workflow

1. Semantic Versioning

# Patch: Bug fixes (1.0.0 → 1.0.1)
npm version patch

# Minor: New features, backwards compatible (1.0.0 → 1.1.0)
npm version minor

# Major: Breaking changes (1.0.0 → 2.0.0)
npm version major

# Pre-release
npm version prerelease --preid=beta
# 1.0.0 → 1.0.1-beta.0

2. Changelog Generation

# Install conventional-changelog
npm install -D conventional-changelog-cli

# Generate changelog
npx conventional-changelog -p angular -i CHANGELOG.md -s

3. Pre-publish Script

{
  "scripts": {
    "prepublishOnly": "npm run lint && npm test && npm run build",
    "prepack": "cp README.md LICENSE dist/"
  }
}

4. Publishing Commands

# Dry run (test without publishing)
npm publish --dry-run

# Publish to npm
npm publish

# Publish scoped package
npm publish --access public

# Publish with tag
npm publish --tag beta

# Publish specific folder
cd dist && npm publish

5. NPM Provenance (Recommended)

# Publish with provenance (requires GitHub Actions)
npm publish --provenance

6. GitHub Actions for Publishing

# .github/workflows/publish.yml
name: Publish Package

on:
  push:
    tags:
      - 'v*'

jobs:
  publish:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '18'
          registry-url: 'https://registry.npmjs.org'
      - run: npm ci
      - run: npm test
      - run: npm run build
      - run: npm publish --provenance --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

Build Scripts

Development Scripts

{
  "scripts": {
    "dev": "tsup --watch",
    "build": "tsup",
    "build:analyze": "tsup && rollup-plugin-visualizer",
    "type-check": "tsc --noEmit",
    "clean": "rm -rf dist"
  }
}

CI/CD Scripts

{
  "scripts": {
    "ci:build": "npm run clean && npm run build",
    "ci:test": "npm run type-check && npm test",
    "ci:publish": "npm run ci:test && npm run ci:build && npm publish"
  }
}

Testing Build Output

1. Local Testing

# Create tarball
npm pack

# Install in test project
cd ../test-project
npm install ../my-library/my-library-1.0.0.tgz

2. Link for Development

# In library
npm link

# In consuming project
npm link my-library

3. Verify Exports

// test.mjs
import * as lib from 'my-library'
console.log(Object.keys(lib))

// test.cjs
const lib = require('my-library')
console.log(Object.keys(lib))

Monorepo Considerations

Turborepo Configuration

// turbo.json
{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}

Workspace Package

// packages/ui/package.json
{
  "name": "@myorg/ui",
  "version": "1.0.0",
  "main": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "types": "./dist/index.d.ts"
    }
  }
}

// apps/docs/package.json
{
  "dependencies": {
    "@myorg/ui": "workspace:*"
  }
}

Best Practices

Package Design

  1. ESM-First: Modern standard, better tree-shaking
  2. Dual Package: Provide both ESM and CJS for compatibility
  3. Explicit Exports: Use exports field for better control
  4. Tree-Shakeable: Mark side effects, use named exports
  5. Small Bundles: Externalize dependencies, optimize code

Build Configuration

  1. Source Maps: Always generate for debugging
  2. Type Declarations: Essential for TypeScript users
  3. Declaration Maps: Enable IDE navigation
  4. Minification: For production builds
  5. Clean Output: Clear dist/ before building

Publishing

  1. Semantic Versioning: Follow strictly
  2. Changelog: Document all changes
  3. Git Tags: Tag releases
  4. Pre-publish Tests: Run comprehensive checks
  5. Provenance: Use for supply chain security

Performance

  1. Bundle Size: Keep minimal
  2. Code Splitting: Split by feature
  3. Tree-Shaking: Maximize dead code elimination
  4. Compression: Use gzip/brotli
  5. Lazy Loading: Dynamic imports where beneficial

Troubleshooting

Common Issues

Dual Package Hazard

// Ensure consistent resolution
// Use exports field properly
{
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "require": "./dist/index.cjs"
    }
  }
}

Missing Type Declarations

// Check tsconfig.json
{
  "compilerOptions": {
    "declaration": true,
    "declarationMap": true
  }
}

// Check package.json
{
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts"
    }
  }
}

Large Bundle Size

# Analyze bundle
npm run build:analyze

# Check for duplicate dependencies
npm dedupe

# Externalize peer dependencies
external: ['react', 'react-dom']

CJS/ESM Compatibility

// Use conditional exports
{
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "require": "./dist/index.cjs"
    }
  }
}

// Add "type": "module" to package.json
// Name CJS files with .cjs extension

When to Use This Skill

Activate this skill when you need to:

  • Set up build configuration for a library
  • Optimize bundle size
  • Configure multi-format exports (ESM/CJS/UMD)
  • Prepare package for NPM publishing
  • Set up TypeScript declaration generation
  • Configure tree-shaking
  • Implement code splitting
  • Create build scripts
  • Set up CI/CD for publishing
  • Troubleshoot build issues
  • Migrate build tools
  • Configure monorepo builds

Output Format

When configuring builds, provide:

  1. Complete Configuration: Build tool config files
  2. package.json Setup: Proper entry points and scripts
  3. Build Instructions: How to build and test
  4. Publishing Guide: Step-by-step publishing process
  5. Optimization Report: Bundle sizes and improvements
  6. Verification Steps: How to verify build output

Always optimize for modern standards (ESM-first) while maintaining backwards compatibility where needed.