组件库这东西之前倒是实现过,也发布到 npm 上去过,但进来技术变化很快,索性就梳理一遍目前组件库的实现。
一般实现
首先,用 Vite 创建一个 Library 项目,其实和普通的 TypeScript 项目没啥差别,主要在于配置 build 上。
build: {
lib: {
entry: './src/index.ts',
name: 'index',
fileName: 'index',
formats: ['es']
}
}
告诉 Vite 需要打包的格式,文件名就可以了,另外需要装一个插件 vite-plugin-dts
,用来生成 .d.ts 类型声明文件的一个插件,如果不使用这个,打包出来后引用方将看不到类型。
还有 package.json 中要告诉使用方如何使用自己:
"type": "module",
"files": [
"dist"
],
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
需要注意的是如果要兼容 CommonJS 需要修改 format 中打包出来的格式,以及 package 中需要增加 main 字段指向打包出来的 cjs 文件。
依赖组件 peerDependencies
用来指定自身所依赖的库,避免依赖方重复安装依赖
package.json 中声明所依赖的包
"peerDependencies": {
"dayjs": "^1.11.12"
}
然后到 Vite 修改打包配置,如果此处不修改,会将依赖的包一起打包进去
build: {
rollupOptions: {
external: ['dayjs'],
}
}
React 组件库
同上,先在 peerDependencies 中加上 react, react-dom, 然后修改 Vite 配置文件,这里的 react/jsx-runtime
是一个特殊情况,React 最新版拆分了 jsx 的 runtime,所以此处需要单独列出来(17 之前使用 React.createElement,之后用 jsx,并且编译器支持自动注入,不再需要单独 import 某个东西)
build: {
rollupOptions: {
external: ['react', 'react-dom', 'react/jsx-runtime']
},
}
如果用的 typescript 需要修改 tsconfig.json
compilerOptions: {
"jsx": "react-jsx"
}
另外,这里我并没有安装 Vite 支持 react 的插件 @vitejs/plugin-react
,有需要可以自行安装
{
plugins: [react()]
}
Monorepo
现在基本各个组件库,业务项目也都在用,此处我们只说组件库,因为业务上多项目好用也会带来一定的问题,这里也不讲概念,只讲用法。
现在用的是 pnpm workspace,之前是 lerna 已经停止维护了
// pnpm-workspace.yaml
packages:
- 'packages/*'
monorepo 可以共享很多东西,比如在根目录下安装包,那么子项目下都可以直接使用不再需要单独安装,比如 eslint 和 prettier。
比如现在有 components
和 hooks
两个子项目,我可以把双方都依赖的 @types/react
安装到根目录
命令使用上也有一点区别,都是从根目录上使用,不用进入子项目单独处理
# install types as workspace
pnpm i @types/react -w -D
# install
pnpm --filter @example/component i dayjs
# install from workspace
pnpm --filter @example/component i @example/hook
# build all
pnpm run build
# build item
pnpm --filter=@example/hook run build
# publish item
pnpm publish ./packages/components --access=public
需要注意的是子项目互相依赖处理,需要修改 .npmrc 文件,不然 pnpm 默认会先去网络上查找包
link-workspace-packages=true
安装使用的是 workspace 协议引用,在打包发布时才会替换成真实版本
"dependencies": {
"@example/hook": "workspace:^"
}
另外如果需要记录变更日志,有个叫 changeset 的工具不错,可以根据选择自动更新包版本,以及修改更新的日志。
先执行 changeset 会让选择变更的类型,比如大版本小版本,以及输入变更日志,然后会生成一个变更文件,再执行 changeset version 会消费前面生成的文件,自动 patch 到项目的 README 文件以及 package.json 文件更新日志和版本信息。
本地调试/测试
第一个方式是 npm link 创建软链的方式,但是目前 monorepo 使用下来有点不方便
第二种方式是 yalc 工具,可以本地模拟真实的发包下载包过程
第三种方式是利用 alias 直接重定向到组件源码位置