如何打包支持Tree Shaking的React 18客户端/服务端组件库适配Next.js13
适配Next.js 13的React组件库打包方案:兼顾Tree Shaking与客户端/服务端组件特性
核心思路
基于Rollup(更适合库打包,Tree Shaking能力更精准)配置,保留'use client'指令的同时,确保ESM模块结构让Next.js能按需摇树,同时区分客户端/服务端组件的特性。
1. 基础Rollup配置:确保Tree Shaking生效
Rollup的核心配置要围绕ESM输出和模块结构保留来做:
- 输出ESM格式:Next.js 13对ESM的静态分析更友好,是Tree Shaking的基础
- 开启
preserveModules: true:保留源文件的模块结构,让Next.js能精准导入单个组件,而非打包成一个大文件 - 外部化React依赖:避免重复打包,让用户项目提供React版本
示例rollup.config.js:
import resolve from '@rollup/plugin-node-resolve'; import typescript from '@rollup/plugin-typescript'; import { terser } from 'rollup-plugin-terser'; export default { input: 'src/index.ts', output: [ { format: 'esm', dir: 'dist/esm', preserveModules: true, preserveModulesRoot: 'src', // 保持dist文件结构和src一致 sourcemap: true, }, // 可选:输出CJS格式兼容旧环境 { format: 'cjs', dir: 'dist/cjs', preserveModules: true, preserveModulesRoot: 'src', sourcemap: true, }, ], plugins: [ resolve(), typescript({ tsconfig: './tsconfig.json' }), terser(), // 生产环境可选压缩代码 ], external: ['react', 'react-dom'], // 不打包React依赖 };
2. 正确保留'use client'指令
- 仅在需要交互的客户端组件顶部添加
'use client'注释,服务端组件(纯静态、无交互)无需添加 - Rollup默认不会移除顶部注释,但若使用Babel,需确保配置
comments: true避免误删 - 不要在库的入口文件(如
src/index.ts)添加'use client',否则所有组件都会被标记为客户端组件
示例客户端组件:
// src/client/Button.tsx 'use client'; import React from 'react'; export const Button = ({ children }: { children: React.ReactNode }) => { return <button onClick={() => alert('Clicked')}>{children}</button>; };
3. TypeScript与Package.json配置优化
tsconfig.json关键设置:
{ "compilerOptions": { "module": "ESNext", "target": "ESNext", "moduleResolution": "bundler", "declaration": true, "declarationDir": "dist/types", "jsx": "react-jsx", "strict": true }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] }
package.json关键设置:
{ "name": "my-package", "type": "module", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/types/index.d.ts", "sideEffects": false, // 告诉打包工具所有文件无副作用,放心摇树 "scripts": { "build": "rollup -c", "clean": "rm -rf dist" }, "peerDependencies": { "react": "^18.2.0", "react-dom": "^18.2.0" } }
sideEffects: false:是Tree Shaking生效的关键,如果有全局样式等副作用文件,需单独列出(如["src/styles/global.css"])peerDependencies:强制用户项目提供React,避免版本冲突
4. 组件导出结构
在src/index.ts中统一导出所有组件,让用户可以通过import { Button } from 'my-package'导入:
// src/index.ts export { Button } from './client/Button'; export { StaticCard } from './server/StaticCard'; // 服务端组件,无'use client'
5. 验证Tree Shaking效果
在Next.js 13项目中导入单个组件,执行next build后:
- 查看
.next/static/chunks目录下的文件大小,确认仅包含导入组件的代码 - 可使用
source-map-explorer分析客户端bundle,验证未导入的组件是否被摇掉
内容的提问来源于stack exchange,提问作者SirGolem
相关产品推荐
相关产品推荐

