library-bundler
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseLibrary 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:构建配置设置
-
Analyze Project Structure
- Entry points (index.ts, components/)
- Output formats needed (ESM, CJS, UMD)
- External dependencies
- Target environments (browsers, Node.js)
-
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
-
Configure package.json
- Entry points (main, module, types, exports)
- Build scripts
- Files to include
- Peer dependencies
-
分析项目结构
- 入口文件(index.ts、components/)
- 需要的输出格式(ESM、CJS、UMD)
- 外部依赖
- 目标环境(浏览器、Node.js)
-
选择构建工具
- tsup: 适用于简单的TS库
- Vite: 适用于现代ESM优先的库
- Rollup: 适用于需要最大控制权的场景
- esbuild: 适用于追求极致速度的场景
-
配置package.json
- 入口点(main、module、types、exports)
- 构建脚本
- 要包含的文件
- 对等依赖
Phase 2: Optimization
阶段2:优化
-
Tree-Shaking Setup
- Mark side effects in package.json
- Use ESM imports/exports
- Avoid namespace imports
- Test tree-shaking effectiveness
-
Bundle Size Analysis
- Use bundle analyzer tools
- Identify large dependencies
- Consider alternatives
- Externalize heavy deps
-
Code Splitting
- Split by route/feature
- Shared chunk optimization
- Dynamic imports where beneficial
-
Tree-Shaking设置
- 在package.json中标记副作用文件
- 使用ESM导入/导出
- 避免命名空间导入
- 测试Tree-Shaking效果
-
包体积分析
- 使用包分析工具
- 识别大型依赖
- 考虑替代方案
- 外部化重型依赖
-
代码分割策略
- 按路由/功能分割
- 共享代码块优化
- 在合适的场景使用动态导入
Phase 3: Publication Preparation
阶段3:发布准备
-
Version Management
- Follow semantic versioning
- Update package.json version
- Create git tag
- Generate changelog
-
Pre-publish Checks
- Run tests
- Build all formats
- Verify type declarations
- Check bundle sizes
- Test in consuming projects
-
Publish to NPM
- npm login
- npm publish (or publish:dry-run)
- Verify on npmjs.com
- Test installation
-
版本管理
- 遵循语义化版本控制
- 更新package.json版本
- 创建Git标签
- 生成变更日志
-
发布前检查
- 运行测试
- 构建所有格式
- 验证类型声明
- 检查包体积
- 在消费项目中测试
-
发布至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
undefinedbash
undefinedInstall 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,
}),
]
undefinedimport { visualizer } from 'rollup-plugin-visualizer'
plugins: [
visualizer({
filename: './dist/stats.html',
open: true,
}),
]
undefined4. 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
undefinedbash
undefinedPatch: 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
undefinedundefined2. Changelog Generation
2. 变更日志生成
bash
undefinedbash
undefinedInstall 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
undefinednpx conventional-changelog -p angular -i CHANGELOG.md -s
undefined3. 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
undefinedbash
undefinedDry 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
undefinedcd dist && npm publish
undefined5. NPM Provenance (Recommended)
5. NPM包溯源(推荐)
bash
undefinedbash
undefinedPublish with provenance (requires GitHub Actions)
发布时添加溯源信息(需要GitHub Actions)
npm publish --provenance
undefinednpm publish --provenance
undefined6. GitHub Actions for Publishing
6. GitHub Actions自动发布配置
yaml
undefinedyaml
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 }}
undefinedname: 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 }}
undefinedBuild 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
undefinedbash
undefinedCreate tarball
创建压缩包
npm pack
npm pack
Install in test project
在测试项目中安装
cd ../test-project
npm install ../my-library/my-library-1.0.0.tgz
undefinedcd ../test-project
npm install ../my-library/my-library-1.0.0.tgz
undefined2. Link for Development
2. 开发时链接
bash
undefinedbash
undefinedIn library
在库项目中
npm link
npm link
In consuming project
在消费项目中
npm link my-library
undefinednpm link my-library
undefined3. 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
包设计
- ESM-First: Modern standard, better tree-shaking
- Dual Package: Provide both ESM and CJS for compatibility
- Explicit Exports: Use exports field for better control
- Tree-Shakeable: Mark side effects, use named exports
- Small Bundles: Externalize dependencies, optimize code
- ESM优先: 现代标准,Tree-Shaking效果更好
- 双格式包: 同时提供ESM和CJS以保证兼容性
- 显式导出: 使用exports字段实现更精细的控制
- 支持Tree-Shaking: 标记副作用,使用具名导出
- 小包体积: 外部化依赖,优化代码
Build Configuration
构建配置
- Source Maps: Always generate for debugging
- Type Declarations: Essential for TypeScript users
- Declaration Maps: Enable IDE navigation
- Minification: For production builds
- Clean Output: Clear dist/ before building
- 源映射: 始终生成为调试提供支持
- 类型声明: 对TypeScript用户至关重要
- 声明映射: 启用IDE导航功能
- 代码压缩: 生产构建时启用
- 清理输出: 构建前清空dist/目录
Publishing
发布
- Semantic Versioning: Follow strictly
- Changelog: Document all changes
- Git Tags: Tag releases
- Pre-publish Tests: Run comprehensive checks
- Provenance: Use for supply chain security
- 语义化版本控制: 严格遵循
- 变更日志: 记录所有变更
- Git标签: 为版本打标签
- 发布前测试: 运行全面检查
- 包溯源: 用于供应链安全
Performance
性能
- Bundle Size: Keep minimal
- Code Splitting: Split by feature
- Tree-Shaking: Maximize dead code elimination
- Compression: Use gzip/brotli
- Lazy Loading: Dynamic imports where beneficial
- 包体积: 保持最小
- 代码分割: 按功能分割
- Tree-Shaking: 最大化死代码消除
- 压缩: 使用gzip/brotli
- 懒加载: 在合适的场景使用动态导入
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
undefinedAnalyze 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 extensionexternal: ['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:
- Complete Configuration: Build tool config files
- package.json Setup: Proper entry points and scripts
- Build Instructions: How to build and test
- Publishing Guide: Step-by-step publishing process
- Optimization Report: Bundle sizes and improvements
- Verification Steps: How to verify build output
Always optimize for modern standards (ESM-first) while maintaining backwards compatibility where needed.
配置构建时,提供以下内容:
- 完整配置: 构建工具配置文件
- package.json设置: 正确的入口点和脚本
- 构建说明: 如何构建和测试
- 发布指南: 分步发布流程
- 优化报告: 包体积和优化效果
- 验证步骤: 如何验证构建输出
始终优先优化现代标准(ESM优先),同时在需要时保持向后兼容性。