如何在@company/ui包中安全导出React服务端与客户端组件?
不用必须拆成两个独立包,试试这些方案
你遇到的编辑器自动补全丢失问题,主要是server-only风格的exports配置没配合好类型声明导致的,没必要直接拆包,下面几个方案可以解决问题:
1. 分环境的条件导出 + 完整类型声明
在package.json里配置多入口的exports,把客户端、服务端、共享组件分开,同时给每个入口配上对应的.d.ts类型文件,编辑器就能识别并提供补全:
package.json 配置示例
{ "exports": { ".": { "import": "./index.js", "types": "./index.d.ts" }, "./client": { "browser": "./client/index.js", "import": "./client/index.js", "types": "./client/index.d.ts" }, "./server": { "node": "./server/index.js", "import": "./server/index.js", "types": "./server/index.d.ts" } } }
目录结构示例
@company/ui/ ├── index.js # 只导出共享组件(Avatar、ErrorBoundary) ├── index.d.ts ├── client/ │ ├── index.js # 导出客户端专属组件(Button、Modal) │ └── index.d.ts └── server/ ├── index.js # 导出服务端专属组件(Layout、Sidebar) └── index.d.ts
用户可以按需导入:
// 导入共享组件 import { Avatar } from '@company/ui'; // 导入客户端组件 import { Button } from '@company/ui/client'; // 导入服务端组件 import { Layout } from '@company/ui/server';
每个入口的类型文件都完整声明导出的组件,编辑器就能正常补全了。
2. 给客户端组件加'use client'指令,桶文件全量导出
给所有客户端专属组件的文件顶部加上'use client'指令,然后在根目录的index.js里全量导出所有组件:
客户端组件示例(Button.js)
'use client'; export const Button = ({ children }) => { // 客户端组件逻辑 return <button>{children}</button>; };
根目录index.js
// 共享组件 export { Avatar, ErrorBoundary } from './shared'; // 客户端组件(已加'use client') export { Button, Modal } from './client-components'; // 服务端组件 export { Layout, Sidebar } from './server-components';
这种方式下,React会自动识别带'use client'的组件,不会让服务端代码加载客户端逻辑,同时根目录的类型声明文件(index.d.ts)正常导出所有组件的类型,编辑器补全不受影响。
3. 用类型别名区分环境组件
如果不想改目录结构,也可以在类型声明文件里用类型别名把客户端、服务端组件分组,让编辑器能清晰提示:
index.d.ts 示例
import type { Button, Modal } from './client-components'; import type { Layout, Sidebar } from './server-components'; import { Avatar, ErrorBoundary } from './shared'; export { Avatar, ErrorBoundary }; export { Button, Modal }; export { Layout, Sidebar }; // 类型别名,方便编辑器识别分组 export type ClientUIComponents = { Button: typeof Button; Modal: typeof Modal; }; export type ServerUIComponents = { Layout: typeof Layout; Sidebar: typeof Sidebar; };
这样用户在导入时,编辑器会提示哪些属于客户端组件、哪些属于服务端组件,同时组件的正常导出不受影响。
如果你的团队规模较大,拆成@company/ui-client和@company/ui-server能让职责划分更清晰,那拆包也是可行的,但不是解决问题的必要选项。上面的方案都能在保留单包结构的前提下,解决编辑器补全问题,同时避免污染React服务端组件。
内容的提问来源于stack exchange,提问作者SayJeyHi
相关产品推荐
相关产品推荐

