1 背景
我之前封装了十几个react
组件,后面想在其他的个人项目中进行使用,所以需要把开发好的组件库
发布到npm上。
本文讲一下都需要哪些步骤,组件以vite + react
进行开发的,如果是其他打包工具流程也是类似的。
2 流程
首先假设你已经开发好了组件,并且也是使用的vite + react
,
2.1 package.json
修改package.json
如下,其中有几个入口文件还有.d.ts
还没有准备好,我们后面会介绍如何创建。
{
"name": "@sunwu51/camel-ui", // 先到npm上搜一下,有没有同名的,保险的方案就是@username/xxx
"version": "0.0.1",
"type": "module",
"main": "dist/camel.umd.js", // umd模式下的 import require用这个文件
"module": "dist/camel.es.js", // es模式下 import require用这个,这个比较重要,前端开发都只用es
"types": "dist/types/index.d.ts", // 类型声明的d.ts文件,方便别人引入提供智能提示
"keywords": [ // npm的关键字,可有可无
"react",
"component",
"react-aria",
"camel-ui"
],
"author": "Frank", // 作者 证书 git仓库, 可有可无
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/sunwu51/camel-ui.git"
},
"publishConfig": { // 声明是public的,带@username的默认是private
"access": "public"
},
"files": [ // 需要上传到npm的文件,只上传dist即可src等不需要
"dist"
],
"scripts": {
//...
},
"dependencies": {
//...
},
"peerDependencies": { // 把react react-dom从dependencies移到peerDependenies,
"react": "^18.2.0", // 项目中会自己引入,不要在组件库引入
"react-dom": "^18.2.0"
},
"devDependencies": {
// ...
}
}
2.2 types.ts
与index.d.ts
一般而言开发组件库,最好使用ts
并配有类型声明文件,这样在用户使用的时候,才能有每个组件的属性智能提示。当然我们还要把这些类型声明出去才能被使用。
首先创建type.ts
,把组件的各种props
属性进行声明如下:
......
export interface ButtonProps extends BaseProps, AriaButtonOptions<'button'> {}
export interface BadgeProps extends BaseProps {}
export interface CardProps extends BaseProps {}
export interface CheckboxProps extends BaseProps, ToggleStateOptions, AriaCheckboxProps {}
在我们组件开发过程中,就需要用到这些属性,例如BadgeProps
组件中是这样的,通过types.ts
引入属性。
import './Badge.css'
import {cn} from '../cn'
import { BadgeProps } from '../../types'
function Badge(props: BadgeProps) {
return <>
<span className={ cn("badge-container", props.className) } style={{...props.style}}>
{props.children}
</span>
</>
}
而对于使用方来说,则是通过index.d.ts
,也对应了pacakge.json
中的types
属性配置。
export * from './types';
declare module 'camel-ui' {
export * from './types';
}
2.3 vite.config.ts
与tsconfig.json
需要先安装两个插件:
vite-plugin-dts
插件用来生成.d.ts
类型声明的文件,这对于react组件库很重要,他会对每个组件都生成一个类型声明的文件,智能提示很有用,并且还会拷贝上面的index.d.ts
文件。vite-plugin-lib-inject-css
用来内连css
到js
中,使得只引入js
组件,就自带了样式,不需要再引一次css
。当然如果你本来就用了css-in-js
的方案,那这个组件可能是不需要的。
$ npm i -D vite-plugin-lib-inject-css vite-plugin-dts
接下来是最重要的修改vite.config.ts
,默认的build
行为是以index.html
为入口,打包各种js文件,使其成为一个web项目。但是组件库不同,我们要配置build
为lib
。
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'// 这里我用的swc如果vite项目没选swc的话,应该是另一个插件
import { libInjectCss } from 'vite-plugin-lib-inject-css'
import dts from 'vite-plugin-dts';
import path from 'path';
export default defineConfig({
plugins: [react(),
libInjectCss(), // 内连css
dts({ // 生成所有组件的dts声明到dist/types目录
tsconfigPath: './tsconfig.json', // 指定tsconfig文件
outDir: 'dist/types',
}),],
build: {
lib: {
entry: path.resolve(__dirname, 'src/index.ts'),
name: 'CamelUI',
fileName: (format) => `camel.${format}.js` // 默认输出format有俩,umd和es
},
rollupOptions: {
external: ['react', 'react-dom'], // 排除react的打包,减小包体积
output: {
globals: {
react: 'React',
'react-dom': 'ReactDOM'
}
}
}
}
});
然后是tsconfig.json
添加两行。
{
...
+ "declaration": true,
+ "declarationDir": "./dist/types",
...
}
2.4 打包与本地测试
$ npm run build
得到dist
目录结构如下,camel.{format}.js
是前面配置的主要入口js文件,index.css
是所有的样式,types
是dts
插件生成的各种组件和属性声明。
└── 📁dist
└── camel.es.js
└── camel.umd.js
└── index.css
└── 📁types
└── App.d.ts
└── 📁components
└── 📁Badge
└── Badge.d.ts
...
└── BaseProps.d.ts
└── index.d.ts
└── main.d.ts
└── types.d.ts
在上传到npm
之前最好先本地测试一下
# 在当前组件库目录下运行
$ npm link
# 然后到一个测试项目中运行
$ npm link @sunwu51/camel-ui # 这里换成你的组件库名
此时就会直接把组件库的目录,链接到测试项目的node_modules
中,就可以测试使用了。
2.5 发布npm
如果没有npm账号,先去注册一个,然后在组件库项目下登录。
$ npm login #根据提示完成登录
$ npm publish
发布完成后,即可在npm
页面中看到,并且因为是public
的,所以其他人也可以浏览和安装。