前期准备

1. 初始化项目

npx create-react-app react-components --template typescript

2. 安装依赖

  • 使用哪种打包方案:webpack/rollup
**webpack**
* 代码分割:可以将打包后的代码分割成多个*.chunk.js,这些分块可以在用户使用过程中按需加载,这意味着用户可以有更好的交互体验。
* 静态资源导入:图片、CSS 等静态资源可以直接导入到你的 app 中,就和其它的模块、节点一样能够进行依赖管理。因此,我们再也不用小心翼翼地将各个静态文件放在特定的文件夹中,然后再去用脚本给文件 URL 加上哈希串了。
**rollup**
* Tree Shaking:这是rollup提出的一个特性,利用的es6模块的静态特性对导入的模块进行分析,只抽取使用到的方法,从而减小打包体积。
* 配置使用简便,生成的代码相对于Webpack更简洁。
* 可以指定生成生产中使用的各种不同的模块(amd,commonjs,es,umd)。
**异同**
* Webpack更适用于我们实际业务项目的打包,将代码和静态资源进行打包、分割、动态引入无需我们手动处理。
* rollup小巧使用配置方便可以对lib类库进行打包,代码运行效率更高。
* Webpack打包配置相对繁琐,打包出的代码体积相对较大,不同依赖之间执行会有依赖查找的情况,效率不如rollup。
* 简单来说:对于日常单页应用来说有代码和各种静态资源Webpack更适合,对于一些纯js/ts类库项目rollup更适合,rollup打包输入可以指定不同的格式(amd,commonjs,es,umd)应对各个场景引入使用。
  最终选定使用rollup进行打包,并安装rollup以及相关依赖
`yarn add -D rollup rollup-plugin-babel rollup-plugin-commonjs rollup-plugin-node-resolve rollup-plugin-replace @rollup/plugin-image rollup-plugin-terser rollup-plugin-postcss postcss cssnano postcss-nested postcss-simple-vars` 安装好rollup后还需要配置babel,也需要安装babel配置需要的相关插件依赖
`yarn add -D @babel/cli @babel/core @babel/plugin-external-helpers @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators @babel/plugin-proposal-object-rest-spread @babel/plugin-transform-react-jsx @babel/plugin-transform-runtime @babel/preset-env @babel/preset-react @babel/preset-typescript`
  • storybook:用于组件库组件预览、组件测试和文档说明

    快速搭建 storybook react环境

    npx -p @storybook/cli sb init --type react

    Component Story Format (CSF,用于组件测试)

    为了支持typescript,还需要单独安装相关插件依赖

    yarn add -D @storybook/preset-create-react-app @storybook/react

  • eslint和prettier:用于规范代码

    代码检查借助Prettier以及ESLint的扩展,eslint-config-prettier将关闭所有不必要的或可能与Prettier冲突的规则。eslint-plugin-prettier则是添加Prettier格式设置规则的插件。

    yarn add -D eslint prettier eslint-config-prettier eslint-plugin-prettier eslint-plugin-react

  • husky和lint staged:用于规范commit

    Husky 与 Lint Staged来确保每次提交代码的正确性

    yarn add -D husky lint-staged

  • plop:用于组件模板创建

    With plop, you have your "best practice" method of creating any given pattern in CODE. Code that can easily be run from the terminal by typing plop. Not only does this save you from hunting around in your codebase for the right files to copy, but it also turns "the right way" into "the easiest way" to make new files.

    yarn add -D plop

3. 配置环境

  • 打包配置

    在根目录下创建rollup.config.js
// rollup.config.js
// Rollup plugins
// babel插件用于处理es6代码的转换,使转换出来的代码可以用于不支持es6的环境使用
import babel from 'rollup-plugin-babel';
// resolve将我们编写的源码与依赖的第三方库进行合并
import resolve from 'rollup-plugin-node-resolve';
// 解决rollup.js无法识别CommonJS模块
import commonjs from 'rollup-plugin-commonjs';
// 全局替换变量比如process.env
import replace from 'rollup-plugin-replace';
// 使rollup可以使用postCss处理样式文件less、css等
import postcss from 'rollup-plugin-postcss';
// 可以处理组件中import图片的方式,将图片转换成base64格式,但会增加打包体积,适用于小图标
import image from '@rollup/plugin-image';
// 压缩打包代码
import { terser } from 'rollup-plugin-terser';
// PostCSS plugins
// 处理css定义的变量
import simplevars from 'postcss-simple-vars';
// 处理less嵌套样式写法
import nested from 'postcss-nested';
// 可以提前适用最新css特性
import postcssPresetEnv from 'postcss-preset-env';
// css代码压缩
import cssnano from 'cssnano';
// 支持typescript
import typescript from 'rollup-plugin-typescript2';
// 用于打包生成*.d.ts文件
import dts from 'rollup-plugin-dts';
// 引入package
import pkg from './package.json'; const env = process.env.NODE_ENV; const config = [
{
// 入口文件我这里在components下统一导出所有自定义的组件
input: 'src/components/index.tsx',
// 输出文件夹,可以是个数组输出不同格式(umd,cjs,es...)通过env是否是生产环境打包来决定文件命名是否是.min
output: [
{
file: `dist/index.umd${env === 'production' ? '.min' : ''}.js`,
format: 'umd',
name: 'wcpnts',
},
{
file: `dist/index.esm${env === 'production' ? '.min' : ''}.js`,
format: 'esm',
},
{
file: `lib/index${env === 'production' ? '.min' : ''}.js`,
format: 'cjs',
},
],
// 注入全局变量比如jQuery的$这里只是尝试 并未启用
// globals: {
// react: 'React', // 这跟external 是配套使用的,指明global.React即是外部依赖react
// antd: 'antd'
// },
// 自定义警告事件,这里由于会报THIS_IS_UNDEFINED警告,这里手动过滤掉
onwarn: function (warning) {
if (warning.code === 'THIS_IS_UNDEFINED') {
return;
}
},
// 将模块视为外部模块,不会打包在库中
external: ['react', 'react-dom'],
// 插件
plugins: [
typescript(),
image(),
postcss({
plugins: [
simplevars(),
nested(),
// cssnext({ warnForDuplicates: false, }),
postcssPresetEnv(),
cssnano(),
],
// 处理.css和.less文件
extensions: ['.css', '.less'],
}),
// 告诉 Rollup 如何查找外部模块并安装它
resolve(),
// babel处理不包含node_modules文件的所有js
babel({
exclude: 'node_modules/**',
runtimeHelpers: true,
plugins: ['@babel/plugin-external-helpers'],
extensions: ['.js', '.ts', 'tsx'],
}),
// 将 CommonJS 转换成 ES2015 模块
// 这里有些引入使用某个库的api但报未导出该api通过namedExports来手动导出
commonjs({
namedExports: {
'node_modules/react-is/index.js': ['isFragment'],
'node_modules/react/index.js': [
'Fragment',
'cloneElement',
'isValidElement',
'Children',
'createContext',
'Component',
'useRef',
'useImperativeHandle',
'forwardRef',
'useState',
'useEffect',
'useMemo',
],
'node_modules/react-dom/index.js': [
'render',
'unmountComponentAtNode',
'findDOMNode',
],
'node_modules/gojs/release/go.js': [
'Diagram',
'GraphLinksModel',
'Overview',
'Spot',
],
},
}),
// 全局替换NODE_ENV,exclude表示不包含某些文件夹下的文件
replace({
// exclude: 'node_modules/**',
'process.env.NODE_ENV': JSON.stringify(env || 'development'),
}),
// 生产环境执行terser压缩代码
env === 'production' && terser(),
],
},
{
// 入口文件我这里在components下统一导出所有自定义的组件
input: 'src/components/index.tsx',
// 输出文件夹,可以是个数组输出不同格式(umd,cjs,es...)通过env是否是生产环境打包来决定文件命名是否是.min
output: [
{
file: `${pkg.types}`,
format: 'esm',
},
],
plugins: [
dts(),
postcss({
plugins: [
simplevars(),
nested(),
// cssnext({ warnForDuplicates: false, }),
postcssPresetEnv(),
cssnano(),
],
// 处理.css和.less文件
extensions: ['.css', '.less'],
}),
],
},
]; export default config;
  在package.json中添加一下代码
{
"main": "lib/index.js",
"module": "dist/index.esm.js",
"browser": "dist/index.umd.js",
"types": "lib/index.d.ts",
"scripts": {
"rollup-build": "cross-env BABEL_ENV=rollup rollup -c",
"rollup-production-build": "cross-env NODE_ENV=production rollup -c",
},
"files": [
"dist",
"lib"
],
}
  • storybook配置

    安装成功后,会自动在package.json 中添加下面语句:
"scripts": {
...
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook",
}
  为了支持tsx文件,需要在.storybook/main.js中增加配置项和根据自己项目进行部分调整(.storybook目录是运行完storybook init后自动创建出来的)
module.exports = {
"stories": [
"../src/stories/*.stories.mdx",
"../src/stories/*.stories.tsx"
],
"addons": [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/preset-create-react-app", // 用来支持tsx文件
]
}
  • eslint配置
  • prettier配置
  • husky配置:在package.json 中添加下面语句:
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
}
  • lint staged配置:在package.json 中添加下面语句:
"lint-staged": {
"src/**/*.{css,scss,less,json,html,md,markdown}": [
"prettier --write",
"git add"
],
"src/**/*.{js,jsx,mjs,ts,tsx}": [
"prettier --write",
"eslint --fix",
"git add"
]
}
  • plop配置:创建plopfile.js,并创建模板文件(模板文件和要生成的文件路由和名字都可以自定义)
module.exports = function (plop) {
// create your generators here
plop.setGenerator('basics', {
description: 'this is a component',
prompts: [ // 提示问题,可以是多问题,以数组的形式表示
{ // 可以根据输入的name动态创建组件的相关文件
type: 'input',
name: 'name',
message: 'please input component name',
},
],
actions: [ // 命令完成对应的操作,可以是多操作,以数组的形式表示
{
type: 'add', // 创建文件
path: 'src/components/{{name}}/index.tsx', // 生成的文件
templateFile: 'templates/index.tsx', // 模板文件
},
{
type: 'add',
path: 'src/components/{{name}}/index.less',
templateFile: 'templates/index.less',
},
{
type: 'add',
path: 'src/stories/{{name}}.stories.tsx',
templateFile: 'templates/index.stories.tsx',
},
],
});
};
  • 我的模板文件

  • 执行plop命令的过程,根据提示问题输入组件名称Modal

  • 命令执行完成后,plop会自动创建在配置中设定好的目录

组件开发

1. 组件设计思路及规范

  • 初始化组件:创建组件模板plop
  • 打包版本号升级

2. 项目目录设计

所有组件都放到components下,每个组件一个文件夹,首字母大写,在components下创建一个index.tsx文件,用于导出所有组件

3. 组件编写

PR 标题规则:[ bug fix / breaking change / new feature ] 组件名字:修改内容描述

前面方括号用来区分 PR / issue 的类型:bug fix - 组件 bug 修复;breaking change - 不兼容的改动;new feature - 新功能

修改内容尽可能言简意赅,总结 PR 的改动或者描述 issue

描述请用中文

组件名字请用英文,首字母大写

4. 组件测试

组件维护

1. 组件发布

// 将npm源设置为你自己私有库的地址
npm config set registry ****
// 登录npm私有库,根据提示输入用户名、密码、邮箱,如果没有账号需要先在私有库上添加账号
npm login
// 发布包到自己的私有库上
npm publish

2. 组件说明文档

完善CHANGELOG.md

3. 组件变更记录

安装conventional-changelog-cli和cz-conventional-changelog依赖,可以根据commit的信息自动生成CHANGELOG.md

在package.json中添加以下配置

"scripts": {
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
},

遇到的问题

运行storybook时样式文件没有生效

TODO

发布storybook,支持组件在线预览

使用react搭建组件库:react+typescript+storybook的更多相关文章

  1. beeshell —— 开源的 React Native 组件库

    介绍 beeshell 是一个 React Native 应用的基础组件库,基于 0.53.3 版本,提供一整套开箱即用的高质量组件,包含 JavaScript(以下简称 JS)组件和复合组件(包含 ...

  2. react_app 项目开发 (4)_ React UI 组件库 ant-design 的基本使用

    最流行的开源 React UI 组件库 material-ui 国外流行(安卓手机的界面效果)文档 ant-design 国内流行 (蚂蚁金服 设计,一套 PC.一套移动端的____下拉菜单.分页.. ...

  3. Vitepress搭建组件库文档(上)—— 基本配置

    在 vite 出现以前,vuepress 是搭建组件库文档不错的工具,支持以 Markdown 方式编写文档.伴随着 vite 的发展,vitepress 已经到了 1.0.0-alpha.22 版本 ...

  4. Vitepress搭建组件库文档(下)—— 组件 Demo

    上文 <Vitepress搭建组件库文档(上)-- 基本配置>已经讨论了 vitepress 搭建组件库文档的基本配置,包括站点 Logo.名称.首页 home 布局.顶部导航.左侧导航等 ...

  5. Vue3 企业级优雅实战 - 组件库框架 - 3 搭建组件库开发环境

    前文已经初始化了 workspace-root,从本文开始就需要依次搭建组件库.example.文档.cli.本文内容是搭建 组件库的开发环境. 1 packages 目录 前面在项目根目录下创建了 ...

  6. 从零搭建react+ts组件库(封装antd)

    为什么会有这样一篇文章?因为网上的教程/示例只说了怎么做,没有系统详细的介绍引入这些依赖.为什么要这样配置,甚至有些文章还是错的!迫于技术洁癖,我希望更多的开发小伙伴能够真正的理解一个项目搭建各个方面 ...

  7. React UI 组件库uiw v1.2.8 发布

    uiw 高品质的UI工具包,基于React 16+的组件库.

  8. 从零开始封装React UI 组件库并发布到NPM

    github 开源地址:zswui github 说明文档:wiki 1.新建目录wui (1)进入到 wui 目录 执行 npm init 命令初始化项目.更具提示信息填充将会生成的 package ...

  9. react/redux组件库、模板、学习教程

    开源的有蚂蚁金服的: 1.https://pro.ant.design/index-cn 2.https://pro.ant.design/docs/getting-started-cn 3.http ...

随机推荐

  1. Redis 持久化方案

    目录 持久化简介 什么是持久化? Redis 持久化方案 RDB RDB 简介 save 指令 操作与配置 工作原理 bgsave 指令 操作与配置 工作原理 bgsave 配置执行 相关配置 工作原 ...

  2. Codeforces 288E - Polo the Penguin and Lucky Numbers(数位 dp+推式子)

    题目传送门 似乎我的解法和官方题解不太一样 纪念自己独立做出来的一道难度 2800 的题. 我们记 \(ans(x)\) 为 \([444...44,x]\) 的答案,显然答案为 \(ans(r)-a ...

  3. 这份github上被14万人点赞的Java教程太强了

    前几天有个小伙伴加我之后问了下面的这个问题.我看到后是一脸懵逼的状态,jcombobox?实话说,我已经完全忘了在Java中还有这么个东西. 在网上一番搜索后,才发现原来它是 swing 中的下拉列表 ...

  4. 网易云信 集成UI库登录dologin没有回调

    感谢github上的两位大佬指出问题的解决方法. 解决方法: 在进行ui初始化要在主进程中进行,初始化前进行主进程判断. 若还收不到回调,可尝试将uikit中的base包去掉而在build.gradl ...

  5. linux 实用指令时间日期类

    linux 使用指令时间日期类 data 显示当前日期 基本语法 date 显示当前时间 date+%Y 显示当前年份 date+%m 显示当前月份 date+%d 显示当前是哪一天 date &qu ...

  6. 日常Java 2021/10/26

    HashSet基于HashMap来实现的,是一个不允许有重复元素的集合.HashSet 允许有null 值. HashSet是无序的,即不会记录插入的顺序. HashSet不是线程安全的,如果多个线程 ...

  7. CAD简介

    Computer-aided design (CAD) is the use of computers (or workstations) to aid in the creation, modifi ...

  8. 一起手写吧!ES5和ES6的继承机制!

    原型 执行代码var o = new Object(); 此时o对象内部会存储一个指针,这个指针指向了Object.prototype,当执行o.toString()等方法(或访问其他属性)时,o会首 ...

  9. 学习Vue源码前的几项必要储备(一)

    从接下来的一段时间里,Mg要进行阅读源码的工作.再阅读源码前,梳理一下准备工作. 7项重要储备 Flow 基本语法 发布/订阅模式 ES6+ 语法 原型链.闭包 函数柯里化 event loop 1. ...

  10. android studio 生成aar和引用aar

    以android studio 2.0正式版为例 1.aar包是Android studio下打包android工程中src.res.lib后生成的aar文件,aar包导入其他android stud ...