library-bundler

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

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.
这是一项用于构建、打包并将组件库发布至NPM的专业技能,专注于现代构建工具(tsup、Vite、Rollup)、包优化、多格式导出以及包发布工作流。

Core Capabilities

核心能力

1. Build System Configuration

1. 构建系统配置

  • 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)
  • tsup: 零配置的快速TypeScript打包工具
  • Vite: 支持HMR和优化的现代构建工具
  • Rollup: 功能强大的库模块打包工具
  • esbuild: 极快的JavaScript打包工具
  • Webpack: 全功能打包工具(必要时使用)

2. Bundle Optimization

2. 包优化

  • Tree-shaking for dead code elimination
  • Code splitting for optimal loading
  • Minification (Terser, esbuild)
  • Compression (gzip, brotli)
  • Bundle size analysis
  • Dependency externalization
  • Chunk optimization
  • Tree-shaking 死代码消除
  • 代码分割以优化加载速度
  • 代码压缩(Terser、esbuild)
  • 文件压缩(gzip、brotli)
  • 包体积分析
  • 依赖外部化
  • 代码块优化

3. Multi-Format Support

3. 多格式支持

  • 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)
  • ESM(ES Modules): 现代标准
  • CJS(CommonJS): Node.js兼容格式
  • UMD(Universal Module Definition): 浏览器全局变量格式
  • IIFE: 自执行浏览器包
  • 双包支持(ESM + CJS)

4. TypeScript Integration

4. TypeScript集成

  • Type declaration generation (.d.ts)
  • Declaration maps for IDE navigation
  • Type checking during build
  • Multiple tsconfig.json support
  • Path aliasing resolution
  • 类型声明文件生成(.d.ts)
  • 用于IDE导航的声明映射
  • 构建期间的类型检查
  • 多tsconfig.json支持
  • 路径别名解析

5. Package Publishing

5. 包发布

  • NPM registry publishing
  • Semantic versioning (semver)
  • Changelog generation
  • Git tagging
  • Pre-publish validation
  • Scoped packages (@org/package)
  • Package provenance
  • NPM注册表发布
  • 语义化版本控制(semver)
  • 变更日志生成
  • Git标签管理
  • 发布前验证
  • 作用域包(@org/package)
  • 包溯源(Package provenance)

6. Development Workflow

6. 开发工作流

  • Watch mode for rapid iteration
  • Source maps for debugging
  • Hot Module Replacement (HMR)
  • Build caching
  • Parallel builds
  • Incremental compilation
  • 用于快速迭代的监听模式
  • 用于调试的源映射
  • 热模块替换(HMR)
  • 构建缓存
  • 并行构建
  • 增量编译

Workflow

工作流

Phase 1: Build Configuration Setup

阶段1:构建配置设置

  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
  1. 分析项目结构
    • 入口文件(index.ts、components/)
    • 需要的输出格式(ESM、CJS、UMD)
    • 外部依赖
    • 目标环境(浏览器、Node.js)
  2. 选择构建工具
    • tsup: 适用于简单的TS库
    • Vite: 适用于现代ESM优先的库
    • Rollup: 适用于需要最大控制权的场景
    • esbuild: 适用于追求极致速度的场景
  3. 配置package.json
    • 入口点(main、module、types、exports)
    • 构建脚本
    • 要包含的文件
    • 对等依赖

Phase 2: Optimization

阶段2:优化

  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
  1. Tree-Shaking设置
    • 在package.json中标记副作用文件
    • 使用ESM导入/导出
    • 避免命名空间导入
    • 测试Tree-Shaking效果
  2. 包体积分析
    • 使用包分析工具
    • 识别大型依赖
    • 考虑替代方案
    • 外部化重型依赖
  3. 代码分割策略
    • 按路由/功能分割
    • 共享代码块优化
    • 在合适的场景使用动态导入

Phase 3: Publication Preparation

阶段3:发布准备

  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
  1. 版本管理
    • 遵循语义化版本控制
    • 更新package.json版本
    • 创建Git标签
    • 生成变更日志
  2. 发布前检查
    • 运行测试
    • 构建所有格式
    • 验证类型声明
    • 检查包体积
    • 在消费项目中测试
  3. 发布至NPM
    • npm login
    • npm publish(或publish:dry-run)
    • 在npmjs.com上验证
    • 测试安装

Build Tool Configurations

构建工具配置

tsup Configuration

tsup配置

typescript
// 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
    }
  },
})
typescript
// 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库模式

typescript
// 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',
  },
})
typescript
// 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配置

typescript
// 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'],
}
typescript
// 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

Package.json配置

Modern Package.json (ESM-First)

现代Package.json(ESM优先)

json
{
  "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"
}
json
{
  "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)

双格式包(ESM + CJS)

json
{
  "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"
}
json
{
  "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)

单仓库多包(Turborepo/Nx)

json
{
  "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"]
    }
  }
}
json
{
  "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

TypeScript配置

Library tsconfig.json

库tsconfig.json

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"]
}
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

1. Tree-Shaking优化

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

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

// Avoid default exports for libraries
// ❌ export default { Button, Input }
json
// package.json
{
  "sideEffects": false
}

// 或者指定有副作用的文件
{
  "sideEffects": ["*.css", "*.scss"]
}
typescript
// 使用具名导出(支持Tree-Shaking)
export { Button } from './Button'
export { Input } from './Input'

// 库避免使用默认导出
// ❌ export default { Button, Input }

2. Code Splitting Strategy

2. 代码分割配置

typescript
// 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,
})
typescript
// 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, // 启用代码分割
  dts: true,
})

3. Bundle Size Analysis

3. 包体积分析

bash
undefined
bash
undefined

Install bundle analyzer

安装包分析工具

npm install -D rollup-plugin-visualizer
npm install -D rollup-plugin-visualizer

Add to rollup config

添加到rollup配置

import { visualizer } from 'rollup-plugin-visualizer'
plugins: [ visualizer({ filename: './dist/stats.html', open: true, }), ]
undefined
import { visualizer } from 'rollup-plugin-visualizer'
plugins: [ visualizer({ filename: './dist/stats.html', open: true, }), ]
undefined

4. External Dependencies

4. 外部依赖配置

typescript
// 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)
}
typescript
// 不打包这些依赖(保留为对等依赖)
external: [
  'react',
  'react-dom',
  'framer-motion',
  '@radix-ui/react-*',
]

// 使用正则表达式匹配动态外部依赖
external: (id) => {
  return /^react/.test(id) || /^@radix-ui/.test(id)
}

5. Minification Options

5. 代码压缩选项

typescript
// 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,
    },
  }),
]
typescript
// esbuild(最快)
minify: true

// Terser(压缩效果最佳)
import { terser } from 'rollup-plugin-terser'

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

Publishing Workflow

发布工作流

1. Semantic Versioning

1. 语义化版本控制命令

bash
undefined
bash
undefined

Patch: Bug fixes (1.0.0 → 1.0.1)

补丁版本:Bug修复(1.0.0 → 1.0.1)

npm version patch
npm version patch

Minor: New features, backwards compatible (1.0.0 → 1.1.0)

次版本:新增向后兼容的功能(1.0.0 → 1.1.0)

npm version minor
npm version minor

Major: Breaking changes (1.0.0 → 2.0.0)

主版本:不兼容的变更(1.0.0 → 2.0.0)

npm version major
npm version major

Pre-release

预发布版本

npm version prerelease --preid=beta
npm version prerelease --preid=beta

1.0.0 → 1.0.1-beta.0

1.0.0 → 1.0.1-beta.0

undefined
undefined

2. Changelog Generation

2. 变更日志生成

bash
undefined
bash
undefined

Install conventional-changelog

安装conventional-changelog

npm install -D conventional-changelog-cli
npm install -D conventional-changelog-cli

Generate changelog

生成变更日志

npx conventional-changelog -p angular -i CHANGELOG.md -s
undefined
npx conventional-changelog -p angular -i CHANGELOG.md -s
undefined

3. Pre-publish Script

3. 发布前脚本

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

4. Publishing Commands

4. 发布命令

bash
undefined
bash
undefined

Dry run (test without publishing)

试运行(不实际发布)

npm publish --dry-run
npm publish --dry-run

Publish to npm

发布至NPM

npm publish
npm publish

Publish scoped package

发布作用域包

npm publish --access public
npm publish --access public

Publish with tag

带标签发布

npm publish --tag beta
npm publish --tag beta

Publish specific folder

发布指定文件夹

cd dist && npm publish
undefined
cd dist && npm publish
undefined

5. NPM Provenance (Recommended)

5. NPM包溯源(推荐)

bash
undefined
bash
undefined

Publish with provenance (requires GitHub Actions)

发布时添加溯源信息(需要GitHub Actions)

npm publish --provenance
undefined
npm publish --provenance
undefined

6. GitHub Actions for Publishing

6. GitHub Actions自动发布配置

yaml
undefined
yaml
undefined

.github/workflows/publish.yml

.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 }}
undefined
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 }}
undefined

Build Scripts

构建脚本

Development Scripts

开发脚本

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

CI/CD Scripts

CI/CD脚本

json
{
  "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"
  }
}
json
{
  "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

1. 本地测试

bash
undefined
bash
undefined

Create tarball

创建压缩包

npm pack
npm pack

Install in test project

在测试项目中安装

cd ../test-project npm install ../my-library/my-library-1.0.0.tgz
undefined
cd ../test-project npm install ../my-library/my-library-1.0.0.tgz
undefined

2. Link for Development

2. 开发时链接

bash
undefined
bash
undefined

In library

在库项目中

npm link
npm link

In consuming project

在消费项目中

npm link my-library
undefined
npm link my-library
undefined

3. Verify Exports

3. 验证导出

typescript
// 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))
typescript
// 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

Turborepo配置

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

Workspace Package

工作空间包配置

json
// 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:*"
  }
}
json
// 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
  1. ESM优先: 现代标准,Tree-Shaking效果更好
  2. 双格式包: 同时提供ESM和CJS以保证兼容性
  3. 显式导出: 使用exports字段实现更精细的控制
  4. 支持Tree-Shaking: 标记副作用,使用具名导出
  5. 小包体积: 外部化依赖,优化代码

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
  1. 源映射: 始终生成为调试提供支持
  2. 类型声明: 对TypeScript用户至关重要
  3. 声明映射: 启用IDE导航功能
  4. 代码压缩: 生产构建时启用
  5. 清理输出: 构建前清空dist/目录

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
  1. 语义化版本控制: 严格遵循
  2. 变更日志: 记录所有变更
  3. Git标签: 为版本打标签
  4. 发布前测试: 运行全面检查
  5. 包溯源: 用于供应链安全

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
  1. 包体积: 保持最小
  2. 代码分割: 按功能分割
  3. Tree-Shaking: 最大化死代码消除
  4. 压缩: 使用gzip/brotli
  5. 懒加载: 在合适的场景使用动态导入

Troubleshooting

故障排除

Common Issues

常见问题

Dual Package Hazard
typescript
// Ensure consistent resolution
// Use exports field properly
{
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "require": "./dist/index.cjs"
    }
  }
}
Missing Type Declarations
typescript
// 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
bash
undefined
双格式包冲突
typescript
// 确保解析一致
// 正确使用exports字段
{
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "require": "./dist/index.cjs"
    }
  }
}
缺失类型声明
typescript
// 检查tsconfig.json
{
  "compilerOptions": {
    "declaration": true,
    "declarationMap": true
  }
}

// 检查package.json
{
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts"
    }
  }
}
包体积过大
bash
undefined

Analyze bundle

分析包体积

npm run build:analyze
npm run build:analyze

Check for duplicate dependencies

检查重复依赖

npm dedupe
npm dedupe

Externalize peer dependencies

外部化对等依赖

external: ['react', 'react-dom']

**CJS/ESM Compatibility**
```typescript
// Use conditional exports
{
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "require": "./dist/index.cjs"
    }
  }
}

// Add "type": "module" to package.json
// Name CJS files with .cjs extension
external: ['react', 'react-dom']

**CJS/ESM兼容性问题**
```typescript
// 使用条件导出
{
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "require": "./dist/index.cjs"
    }
  }
}

// 在package.json中添加"type": "module"
// CJS文件使用.cjs扩展名

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
当你需要以下操作时,启用此技能:
  • 为库设置构建配置
  • 优化包体积
  • 配置ESM/CJS/UMD多格式导出
  • 准备包以发布至NPM
  • 设置TypeScript声明生成
  • 配置Tree-Shaking
  • 实现代码分割
  • 创建构建脚本
  • 设置CI/CD自动发布
  • 排查构建问题
  • 迁移构建工具
  • 配置单仓库多包构建

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.
配置构建时,提供以下内容:
  1. 完整配置: 构建工具配置文件
  2. package.json设置: 正确的入口点和脚本
  3. 构建说明: 如何构建和测试
  4. 发布指南: 分步发布流程
  5. 优化报告: 包体积和优化效果
  6. 验证步骤: 如何验证构建输出
始终优先优化现代标准(ESM优先),同时在需要时保持向后兼容性。