使用 Vite 从零开始构建 React 组件库
这篇文章会介绍一个 React 组件库项目的搭建、打包、发布
但不会涉及组件库文档站点的构建,如有需要,建议查看《使用 dumi 打包 React 组件库并生成文档站点》
另外,虽然本文介绍的是 React 组件库,但对于 Vue 组件库也是通用的
一、创建项目
首先参考 Vite 的文档创建一个项目
yarn create vite my-packages --template react-ts
// 这里的 my-packages 是项目名称,按需修改
生成的项目如下:
结构很简单,但对于一个组件库来说,还需要完善
首先是 package.json, 需要将 dependencies 中的基础库移到 peerDependencies 和 devDependencies 中:
"dependencies": {
"classnames": "^2.3.1"
},
"peerDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
// react 版本根据实际需求做调整
这样就不会把 react 打包到组件库里面
然后我们还可以引入 ESLint、Husky 等工具来统一规范
除此之外,我认为有必要创建两个目录:
一个演示页面目录 example,用于在开发过程中查看效果
一个管理源码的目录 packages,用于打包发布
二、组件开发
初始化的项目中有一个 src 目录,可以先重命名为 example,用作开发过程中的调试页面
Vite 项目开发环境的入口文件是根目录下的 index.html,其默认引入的是 /src/main.tsx 文件
现在由于演示页面的目录已经改为 example,所以这里也需要调整:
<script type="module" src="/example/main.tsx"></script>
然后新建一个 packages 目录,用于管理组件源码
对于大部分的组件,都会有这三部分:组件 Component、组件创建的 TS 类型 types、组件样式 styles
以一个简单的 Button 组件为例:
在开发的时候,可以直接在 Button.tsx 完成 Component 和 types
然后在 index.tsx 中统一导出
// packages/Button/index.tsx
import Button from './Button';
export type { ButtonProps } from './Button';
export default Button;
import './styles/index.less';
// 这里同时引入了 styles
然后在 packages/index.ts 中引入并统一导出:
// packages/index.ts
export { default as Button } from './Button';
export type { ButtonProps } from './Button';
这样就能在使用组件库的时候,从组件库的入口文件同时拿到 Component 和 types:
import { Button } from 'my-packages';
import type { ButtonProps } from 'my-packages';
上面是在组件中直接引入了相应的 styles,也可以在最外层统一引入
但最终打包的时候(默认配置)都会整合到一个 style.css 中
三、组件打包
Vite 提供了一个库模式用于打包组件库,直接在 vite.config.ts 中配置即可
// vite.config.ts
import path from 'path';
import { defineConfig } from 'vite';
function resolve(str: string) {
return path.resolve(__dirname, str);
}
export default defineConfig({
build: {
// 打包输出的目录
outDir: 'lib',
// 防止 vite 将 rgba() 颜色转化为 #RGBA 十六进制
cssTarget: 'chrome61',
lib: {
// 组件库源码的入口文件
entry: resolve('packages/index.ts'),
// 组件库名称
name: 'MyPackages',
// 文件名称, 打包结果举例: my-packages.umd.cjs
fileName: 'my-packages',
},
rollupOptions: {
// 确保外部化处理那些你不想打包进库的依赖
external: ['react', 'react-dom'],
output: {
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
globals: {
react: 'react',
'react-dom': 'react-dom',
},
},
},
}
})
// 如果引入 'path' 的时候报错,检查一下是否安装了 @types/node
以上 build 配置算是一个最小配置,可以参考官网的《构建选项》查看完整配置
vite 的生产构建使用的是 rollup,以目前的配置只会构建出 js 代码,对于 typescript 类型,需要借助 rollup 的 typescript 插件来实现
yarn add @rollup/plugin-typescript -D
然后在 vite.config.ts 中使用插件
import { defineConfig } from 'vite';
import path from 'path';
import react from '@vitejs/plugin-react';
import typescript from '@rollup/plugin-typescript';
function resolve(str: string) {
return path.resolve(__dirname, str);
}
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
react(),
typescript({
target: 'es5',
rootDir: resolve('packages/'),
declaration: true,
declarationDir: resolve('lib'),
exclude: resolve('node_modules/**'),
allowSyntheticDefaultImports: true,
}),
],
build: {
// ...
},
});
打包配置到这里就完成了,执行 yarn build 命令就能打包组件库
四、发布到 npm
作为一个组件库,在发布到 npm 之前需要调整一下 package.json
{
"name": "my-packages",
"version": "0.1.0",
"type": "module",
"files": [
"lib"
],
"main": "./lib/my-packages.umd.cjs",
"module": "./lib/my-packages.js",
"typings": "./lib/index.d.ts",
"exports": {
".": {
"import": "./lib/my-packages.js",
"require": "./lib/my-packages.umd.cjs"
}
}
}
上面设置了 files 字段,其作用和 .npmignore 文件类似
只是 files 是规定哪些文件/目录会放在包内上传到 npm,而 .npmignore 是排除不需要上传的文件
如果需要上传到私有库,可以在 package.json 中定义:
{
"publishConfig": {
"registry": "https://your.npm.private.com"
}
}
然后登录 npm 账户,直接发布即可
npm login
npm version patch
npm publish
项目地址:https://github.com/wisewrong/bolg-demo-app/tree/main/vite-react-packages