用 Next.js 构建企业级组件库
📌 第 1 部分:项目初始化与结构规划
✅ 使用 create-next-app 初始化项目
npx create-next-app@latest my-ui-library --typescript
cd my-ui-library
✅ 项目结构建议
my-ui-library/
├── components/ // 组件库源码
│ ├── Button/
│ │ ├── Button.tsx
│ │ ├── Button.module.css
│ │ └── index.ts
│ └── index.ts // 导出所有组件
├── docs/ // 文档演示页面
│ └── button.md
├── pages/ // Next.js 页面(文档展示)
├── public/ // 公共资源
├── styles/ // 全局样式/主题变量
├── utils/ // 工具函数
├── types/ // 全局类型定义
├── .storybook/ // Storybook 配置(可选)
├── tsconfig.json
├── package.json
└── README.md
📦 第 2 部分:开发基础组件
以 Button 组件为例:
// components/Button/Button.tsx
import React from 'react';
import styles from './Button.module.css';
type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
variant?: 'primary' | 'secondary';
};
const Button: React.FC<ButtonProps> = ({ variant = 'primary', ...rest }) => {
return <button className={styles[variant]} {...rest} />;
};
export default Button;
/* components/Button/Button.module.css */
.primary {
background: #0070f3;
color: white;
}
.secondary {
background: #eaeaea;
color: #333;
}
// components/Button/index.ts
export { default } from './Button';
// components/index.ts
export { default as Button } from './Button';
📚 第 3 部分:构建组件文档系统
✅ 方法一:直接使用 Next.js 作为文档平台
- 创建 pages/docs/button.tsx 来演示组件:
// pages/docs/button.tsx
import { Button } from '@/components';
export default function ButtonDoc() {
return (
<div>
<h1>Button 组件</h1>
<Button variant="primary">主按钮</Button>
<Button variant="secondary">次按钮</Button>
</div>
);
}
✅ 方法二:引入 Storybook(推荐)
npx storybook init
创建故事文件:
// components/Button/Button.stories.tsx
import React from 'react';
import Button from './Button';
import type { Meta, StoryObj } from '@storybook/react';
const meta: Meta<typeof Button> = {
title: 'Components/Button',
component: Button,
};
export default meta;
export const Primary: StoryObj<typeof Button> = {
args: {
children: '主按钮',
variant: 'primary',
},
};
export const Secondary: StoryObj<typeof Button> = {
args: {
children: '次按钮',
variant: 'secondary',
},
};
运行:
npm run storybook
⚙️ 第 4 部分:构建系统与按需引入
✅ 使用 babel-plugin-import 或打包为单独模块
可选:使用
rollup或tsup构建最终产物
npm install tsup -D
// tsup.config.ts
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['components/index.ts'],
format: ['esm', 'cjs'],
dts: true,
clean: true,
});
构建命令:
npx tsup
输出结果:
dist/
├── index.js
├── index.d.ts
├── Button/
│ ├── Button.js
│ ├── Button.d.ts
🌐 第 5 部分:组件库主题化支持
你可以通过 CSS 变量 或 styled-components、Tailwind 等方式支持主题切换。
方案示例:全局 CSS 变量
:root {
--primary-color: #0070f3;
--secondary-color: #eaeaea;
}
<button style={{ backgroundColor: 'var(--primary-color)' }}>
🚀 第 6 部分:发布组件库到 NPM(可选)
1. 修改 package.json
{
"name": "my-ui-library",
"version": "1.0.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": ["dist"]
}
2. 登录 & 发布
npm login
npm publish
✅ 第 7 部分:最佳实践
| 实践 | 推荐做法 |
|---|---|
| 类型系统 | 使用 TypeScript |
| 文档 | 使用 Storybook + 示例文档 |
| 复用性 | 避免组件中硬编码样式,支持 props |
| 测试 | 使用 Jest + RTL 进行单元测试 |
| CI/CD | 发布前集成自动测试、构建流程 |
| 组件命名 | 使用 PascalCase 命名组件文件夹 |
🎯 示例组件建议列表
| 组件名称 | 功能说明 |
|---|---|
| Button | 基础按钮、加载态、禁用态等 |
| Input | 输入框、支持错误、前缀图标 |
| Modal | 弹窗、支持 portal |
| Form | 表单容器、校验逻辑 |
| Tabs | 标签页切换组件 |
| Select | 下拉选择器 |
| Toast | 全局提示框 |
| Table | 表格封装、排序分页 |
| ThemeProvider | 全局主题支持 |