前言
最近在做的项目需要实现一个可拖拽、可设置大小、并且在指定范围内才可以移动的需求,在翻了一些组件后,发现需要三样都满足,并且能满足项目定制化需要的插件几乎没有~,于是自己动手实现了该插件,整体效果如下:
在写完之后,突然想到可以放到 NPM 库中,以后维护该组件更加方便版本管理,于是趁五一长假,终于将包发布上去了~
在发布 NPM 时踩了一些坑,比如脚手架打包后 TS 提示消失、比如 NPM 的官方源换成了 HTTPS 让发包失败等等因素导致整个过程非常不顺。
为了避免自己未来继续踩同样的坑,或许同时还能够帮助别人节省一点时间,于是才有了这篇博客。
-
如果你希望未来想用 React+TypeScript 完成一个组件库并发布到 NPM
-
如果你想了解我在发布时踩了哪些坑
那么这篇博客适合你,阅读时长大约五分钟。
下面是正题。
脚手架工具
采用 React+TypeScript 实现的组件需要借助打包工具将代码打包好才能够被引入,我在查了一些资料后发现有以下三款工具:
这三款工具都预设好了打包工具,比如 dumi 用的 webpack
、tsdx 用的 parcel
,而且也基本实现了 0 配置,我们只需要根据官方文档就可以很快地完成组件编写、用例测试、打包等环节。
其中create-react-library
已经很少维护了,所以我没试过它。
tsdx 和 dumi 带给我的体验差不太多,而且发布最重要的其实是写文档,两款工具都有对应的文档工具,tsdx 内置的是 storybook,我写的第一个组件库就是用的它,但是实在太难配插件了~
tsdx 的问题
一开始我用的 tsdx,但是发现几个问题:
问题一:
我的组件在测试用例时,无法触发 ts 的提示,然后我发现它打包后的声明文件中需要将:
import react from 'react'
修改成:
import * as react from 'react
我的组件才能够有类型提示。
问题二:
tsdx 中修改组件源代码后,需要手动再次打包,然后删掉 example 文件夹内的 node_modules
文件以及.parcel_cache
文件夹生成新的 dist 目录,才会有效果。换言之它的 watch
模式貌似有问题?
dumi 的问题
于是我试了一下 dumi
,dumi写文档的方式对我而言要比 tsdx 的 storybook 方便,不过它也有一点缺陷:
即使用了官方推荐的 ts-in-markdown
插件,在写组件 demo 时,也是没有api智能提示的,只能提示有没有语法错误之类的。
这个缺陷就使得写 demo 时没有办法知道当别人用你的组件时,有没有代码自动提示。(自动提示props真的很重要啊!!)
不过最终我找到了解决这个问题的方法,方法在【本地测试组件】。
我最终选择 dumi
从结果来说使用 dumi 打包完的组件还是有类型提示的,不需要我手动改 dist 目录。
我的组件文档首页目前是这样的:
基本满足了我的需求,所以下面讲讲如何使用 dumi 的发布过程。
一些微不足道的经验
如何使用 dumi 这里就不多说,看官方文档就好,我在这里讲一下我遇到的问题以及解决方法:
-
当组件的 props 类型与外部引入的组件的 props 类型合并后,写 API 时会默认将所有props 的api都展示出来。
这一点我们需要在
.umirc.ts
中配置apiParser
:
apiParser: {
propFilter: {
// 是否忽略从 node_modules 继承的属性,默认值为 false
skipNodeModules: true,
// 需要忽略的属性名列表,默认为空数组
skipPropsWithName: [],
// 是否忽略没有文档说明的属性,默认值为 false
skipPropsWithoutDoc: false,
},
},
- 当配置
publicPath
或base
后,如果logo
和favicon
用的本地图片,一定要在前面加上publicPath
或base
的路径。
favicon: '/react-drag-resizable/lightbulb.png',
logo: '/react-drag-resizable/lightbulb.png',
base: '/react-drag-resizable/',
publicPath: '/react-drag-resizable/',
否则部署后logo 和 favicon 的图片会引入失败。(这点在开发环境下发现不了)
- dumi官方给的 github-pages-action 自动部署的yml文件有问题 官方给的 yml 文件是这样写的:
name: github pages
on:
push:
branches:
- master # default branch 这里有问题,需要改成 main
- main # 这才是正确的
jobs:
deploy:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- run: npm install
- run: npm run docs:build
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs-dist
- 官方给的自定义导航、分组和标题写法有问题
官方写法如下:
---
title: 自定义页面名称
nav:
path: /自定义导航路由
title: 自定义导航名称
order: 控制导航顺序,数字越小越靠前,默认以路径长度和字典序排序
group:
path: /自定义分组路由,注意,分组路由 = 导航路由 + 自己
title: 自定义分组名称
order: 控制分组顺序,数字越小越靠前,默认以路径长度和字典序排序
---
有效的写法:
---
title: 自定义页面名称
nav:
path: /自定义导航路由
title: 自定义导航名称
order: 控制导航顺序,数字越小越靠前,默认以路径长度和字典序排序
group:
path: /自定义分组路由,注意,分组路由 = 导航路由 + 自己
title: 自定义分组名称
order: 控制分组顺序,数字越小越靠前,默认以路径长度和字典序排序
---
看出差别了吗?😏
- 已经将必要的模块导出,但写 docs 时引入该模块依然报错
比如我已经在
src/index.ts
中导出组件内的类型声明和导出组件了:
export type { RectProps, DragResizableBoxProps } from './react-drag-resizable';
export { default as DragResizableBox } from './react-drag-resizable';
但是在写 doc 时,正常引入RectProps
,还是报错了。
执行npm run build
打包出一个 dist 文件夹,然后重启 vscode 解决。
使用github-actions自动化部署
我们可以使用 github-actions 自动化将 dumi 的组件文档部署到 github-pages 中,实现步骤如下:
-
在 github 建一个代码仓库
-
到github 的个人主页申请一个 token
- 选择token 的 note和过期时间
- 权限选择
- 最后生成 token,将token 复制到你的个人仓库的
setting/secrets
中
我在这里使用的是 ACCESS_TOKEN
,也可以自己写,不过这里的名字需要跟后面的 yml 文件保持一致。
- 在你的项目根目录中创建目录和 yml 文件
.github
└── workflows
└── gh-pages.yml
yml文件中这样写
name: github pages
on:
push:
branches:
- main # default branch
jobs:
deploy:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- run: npm install
- run: npm run docs:build
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.ACCESS_TOKEN }}
publish_dir: ./docs-dist
注意最后的secrets.ACCESS_TOKEN
里面的ACCESS_TOKEN
就是你在 github 仓库中设置的token名字。
- 在项目的
package.json
中配置homepage
字段
"homepage": "https://[github username].github.io/[github repository]",
-
将代码推送到远程仓库,actions 会自动下载依赖并打包
-
最后打开你配置的
homepage
就可以看到部署好的文档,我的文档地址是这样的
本地测试组件
在发包前最好再测试一下。由于写 docs 时提示不对,我们没办法做到全面的测试。
所以这里运行 npm link
命令创建软链接到全局的 node_modules 下。你会得到一串字符
/Users/xxx/.nvm/versions/node/v12.14.0/lib/node_modules/xxx -> /Users/xxx/Job/xxx
然后在项目根目录创建一个 test
的目录,用来写测试案例。
在 test 中创建example.tsx
,然后在 test 目录下运行npm link xxx
将测试目录的组件库xxxxxxx链接到全局,注意这里的xxx
修改成你自己的。
然后我们就可以在example.tsx
里面引入我们的组件了。
import { DragResizableBox } from 'react-drag-resizable';
然后你就可以在这里测试一下有没有代码提示之类的诸如docs
无法做到的测试。
发布到 NPM
-
在 www.npmjs.com/ 中注册一个账号
-
package.json
中配置一些内容
"private": false,// 表示非私有
"name": "react-drag-resizable",// 包名
"description": "React component, which can be used to drag and resize, with location limits",// 描述
"author": "qiuyanxi",//作者
"license": "MIT",// 许可
"version": "1.1.0",// 版本
"keywords": [
"React",
"drag",
"resize"
],// 关键字
"homepage": "https://18888628835.github.io/react-drag-resizable",// 主页地址
"repository": {
"type": "git",
"url": "https://github.com/18888628835/react-drag-resizable.git"
},// 仓库地址
"files":["dist"],// 要发哪些文件到 NPM 包中
"main": "dist/index.js",// 引入的来源
"module": "dist/index.esm.js",
"typings": "dist/index.d.ts",// 类型
上面的配置是我收集到的,如果不是非常特殊的情况,我们只需要将 name、description、author、version、keywords、homepage、repository修改成自己的就可以了,其他可以不动。
- 修改 README 一个 NPM 包,好的 README 能够快速让用户知道这个包能够干什么,如何使用等。
这里有一个 github 高 star 的项目,教人怎么写 README,并提供了模板。
地址在这:standard-readme中文
同时我们可能还需要徽章,这里有一个徽章生成的工具网站,可以根据 NPM 或者 github 来生成徽章,我们只需要拷贝到 README 就可以生成徽章
徽章生成:shields.io/
在 README 中的徽章生成示例代码:
[![standard-readme compliant](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme)
我们只需要拷贝代码,并将生成的链接覆盖掉这串代码上的链接就行
- 在项目中输入命令行发布 登陆 npm,并根据提示输入注册时的 username、password, email
$ npm login
npm镜像源,记得还原为官方,官方的源已经换成了 https 协议了
$ npm config set registry https://registry.npmjs.org/
设置完了也可以再看一眼
$ npm config get registry
执行 npm 打包,此时会出来 dist 文件
$ npm run build
一般来说我们只需要将 dist
传到 npm
就行了,不需要传源码,这时候你可能需要再看一眼 package.json
中的 files
字段是不是设置正确了
"files":["dist"],// 要发哪些文件到 NPM 包中
发包
$ npm publish
后面更新包的代码时,需要同步更新包的版本,这个字段在 package.json
中
"version": "1.1.0",// 版本
每次都需要跟上一次不一样,否则会发包失败。
同时发包时,也可以修改其他package.json
的内容,但不要改name噢。
最后
推广一下本人长期维护的 github 博客
1.从学习到总结,记录前端重要知识点,涉及 Javascript 深入、HTTP 协议、数据结构和算法、浏览器原理、ES6、前端技巧等内容。
2.在 README 中有目录可对应查找相关知识点。
如果对您有帮助,欢迎star、follow。
完结,撒花🌹✿✿ヽ(°▽°)ノ✿