You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何打包支持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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 23:46:14