为RSC与Next.js App Router打包组件库的方案咨询
解决方案
Vite 环境下的最优方案
方案1:修复 rollup-plugin-preserve-directives 在 Vite 中的配置
Vite 默认会封装 Rollup 插件的执行逻辑,得确保插件在正确阶段生效:
- 安装最新版
rollup-plugin-preserve-directives - 在
vite.config.ts里显式配置插件,同时开启build.preserveModules:
import { defineConfig } from 'vite'; import preserveDirectives from 'rollup-plugin-preserve-directives'; import react from '@vitejs/plugin-react'; export default defineConfig({ build: { preserveModules: true, lib: { entry: 'src/index.ts', formats: ['es'], fileName: 'index', }, }, plugins: [ react(), { ...preserveDirectives(), enforce: 'post', // 让插件在最后处理代码,避免指令被其他插件清掉 }, ], });
这样配置后,Vite 会保留单个文件中的 "use client" 指令,不会全局添加,同时维持组件库的模块化输出。
方案2:修复源码分发时的 TypeScript 路径冲突
如果想继续用源码分发 + transpilePackages 的方案,可以通过统一路径映射解决冲突:
- 在组件库的
tsconfig.json里,把绝对路径配置为基于包根的别名:
{ "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["src/*"] } } }
- 在使用组件库的 Next.js 项目的
next.config.js中,添加对应的别名映射,同时保留transpilePackages:
const path = require('path'); const nextConfig = { transpilePackages: ['ui-library'], webpack: (config) => { config.resolve.alias['@'] = path.resolve(__dirname, 'node_modules/ui-library/src'); return config; }, }; module.exports = nextConfig;
这样 Next.js 就能正确解析组件库的绝对路径,不会和项目自身的路径配置冲突。
其他打包工具替代方案
Rollup 直接打包
既然你已经验证纯 Rollup 环境下 rollup-plugin-preserve-directives + preserveModules: true 能正常保留指令,直接用 Rollup 作为组件库的打包工具是最稳妥的选择:
- 创建
rollup.config.js:
import preserveDirectives from 'rollup-plugin-preserve-directives'; import typescript from '@rollup/plugin-typescript'; export default { input: 'src/index.ts', output: { dir: 'dist', format: 'es', preserveModules: true, }, plugins: [ typescript(), preserveDirectives(), ], };
- 在
package.json里配置打包脚本:"build": "rollup -c"
Parcel 2
Parcel 2 对 React Server Components 的 "use client" 指令有原生支持,不需要额外插件:
- 在组件库的
package.json里配置入口:
{ "source": "src/index.ts", "main": "dist/index.js", "module": "dist/index.esm.js", "scripts": { "build": "parcel build" } }
Parcel 会自动保留单个文件中的指令,同时处理 TypeScript 转译和模块化输出,配置成本极低。
Webpack 方案
Webpack 5 也能实现,但配置复杂度更高,不是首选:
- 使用
babel-plugin-transform-react-server-components确保 Babel 不会移除"use client"注释; - 在配置中开启
output.preserveModules: true,配合babel-loader处理 TypeScript/JSX 文件。
内容的提问来源于stack exchange,提问作者eliasondrej
相关产品推荐
相关产品推荐

