使用rollup + react + typescript开发一个组件库

如题,大家在日常开发中针对可复用的ui及逻辑,都会在项目中封装组件,以达到复用的目的。目前市面上也有很多优秀的ui组件库,像antd、vant等,这些框架也给我们日常开发提供了很多的便利,本文使用react框架 搭配rollup来分享一下,如何开发维护一个我们自己的组件库。

技术选型

编译工具

目前市面上的构建工具主要有webpack、vite、rollup以及gulp,rollup总能打出更小体积的包,vite本身也是集成rollup,之后添加更多的功能及插件,但是组件库相对来说不是很需要,所以这里使用rollup进行编译。

文档工具

目前主要使用的是两个,一个是 storybook,现在github star数量是80.8k ,使用更广泛。另外一个是 Dumi和father-build,目前star数量是3.3k,但是阿里出品,中文文档方便一些。这两者都可以自动生成文档,极大提高项目可维护性,这里选用storybook。

包管理工具

这里使用yarn,npm的包管理相对混乱,pnpm在实际使用中,发现安装存在一定问题,经常丢包,所以这里使用yarn作为包管理工具

框架

使用react@18.2进行开发,css预编译工具为scss,typescript版本为@5.2.2,大家可以结合自己的情况自由选择,编译库所用工具为rollup,storybook预览组件项目库时,使用webpack进行编译,node版本为18.17.0,eslint + prettierrc进行代码检测,项目最终目录结构为

lua 复制代码
.
|-- package.json
|-- public
|   |-- favicon.ico
|   |-- index.html
|   |-- logo192.png
|   |-- logo512.png
|   |-- manifest.json
|   `-- robots.txt
|-- readme.md
|-- rollup.config.mjs
|-- src
|   |-- Introduction.stories.mdx
|   |-- assets
|   |   |-- close.svg
|   |   |-- phone.svg
|   |   `-- verify.svg
|   |-- components
|   |   |-- login
|   |   |   |-- AtLogin.tsx
|   |   |   |-- index.scss
|   |   |   |-- login.stories.mdx
|   |   |   |-- login.stories.tsx
|   |   |   `-- index.tsx
|   |   |-- login-popup
|   |   |   |-- AtLoginPopup.tsx
|   |   |   |-- index.scss
|   |   |   |-- index.ts
|   |   |   |-- loginPopup.stories.mdx
|   |   |   |-- loginPopup.stories.tsx
|   |   |   `-- show.tsx
|   |   `-- button
|   |       |-- Button.stories.mdx
|   |       |-- Button.tsx
|   |       `-- index.ts
|   |-- demo
|   |   `-- login
|   |       `-- index.tsx
|   |-- global
|   |   |-- global.scss
|   |   |-- index.ts
|   |   |-- theme-dark.scss
|   |   `-- theme-default.scss
|   |-- index.ts
|   |-- react-app-env.d.ts
|   |-- type.d.ts
|   `-- utils
|       |-- attach-properties-to-component.ts
|       |-- axios.ts
|       |-- index.ts
|       |-- native-props.ts
|       |-- render-imperatively.tsx
|       `-- renderToBody.tsx
|-- tsconfig.json
|-- yarn-error.log
`-- yarn.lock

基础架构搭建

快速开始

使用create-react-app创建一个初始项目,执行命令:

lua 复制代码
npx create-react-app my-component --template typescript

接入storybook

使用storybook,如果你不熟悉storybook,请前往storybook学习了解。

bash 复制代码
cd ./my-component
npx storybook init

执行完成后,此时在项目根目录下执行:

arduino 复制代码
yarn run storybook

将在本地启动 Storybook 并输出地址。

新增组件

在src目录下创建components,并在components目录下,创建button文件夹,添加文件如下图:

其中index.ts文件主要处理一些导入导出及其他必要的公共逻辑,组件文件为Button.tsx,为单纯的组件:

Button.stories.mdx 为文档文件,语法几乎等同markdown语法,如图,可从storybook中导出三个组件

  • Meta // 用于生成文档菜单
  • Story // 用于渲染真正的业务组件
  • Canvas // 用于渲染story组件

在上图中,<Canvas>组件包裹的部分,会在页面真正渲染。

如需进一步完善文档,可在同级目录中添加 stories.tsx 文件,通过增减配置,可以生成可编辑的预览页面,配置可参考如下:

编译

使用rollup进行编译,配合terser进行混淆压缩,以降低代码体积,具体配置可参考如下:

上图中,箭头所指的地方可以实时进行修改,页面实时预览

javascript 复制代码
/* eslint-disable import/no-unresolved */
import commonjs from '@rollup/plugin-commonjs';
import resolve from '@rollup/plugin-node-resolve';
import strip from '@rollup/plugin-strip';
import typescript from '@rollup/plugin-typescript';
import autoprefixer from 'autoprefixer';
import path from 'path';
import externals from 'rollup-plugin-node-externals';
import postcss from 'rollup-plugin-postcss';
import json from '@rollup/plugin-json';
import pluginUrl from '@rollup/plugin-url';
import terser from '@rollup/plugin-terser';

import pkg from './package.json' assert { type: 'json' };

export default [
  {
    input: './src/index.ts',
    output: [{
      dir: path.dirname(pkg.module),
      format: 'es',
      name: pkg.name,
      exports: 'named', // 指定导出模式(自动、默认、命名、无)
      preserveModules: true, // 保留模块结构
      preserveModulesRoot: 'src', // 将保留的模块放在根级别的此路径下
    }],
    plugins: [
      externals({
        devDeps: false,
      }),
      json(),
      resolve(),
      pluginUrl(),
      commonjs(),
      typescript({
        outDir: 'es',
        declaration: true,
        declarationDir: 'es',
        tsconfig: 'tsconfig.json',
      }),
      postcss({
        plugins: [
          autoprefixer(),
        ],
      }),
      terser(), // 压缩
      strip(),
    ],
  },
];

编译后即可得到制品,再方式npm或者私有源即可

相关推荐
小猫由里香几秒前
CSS `filter` 属性详解:图像滤镜效果全解析
前端
ice853 分钟前
LLM流式输出实现
前端·人工智能·面试
柳如烟@8 分钟前
零基础,使用Idea工具写一个邮件报警程序
java·服务器·前端
用户408128120038114 分钟前
音频格式
前端
胡gh14 分钟前
React组件实用,每个组件各司其职,成为信息管理大师
前端·react.js
namehu15 分钟前
从 ESLint 到 Oxlint:一次提速百倍的前端 Lint 工具链升级实战
前端·javascript·eslint
凯心16 分钟前
前端学习 vben 之 axios interceptors
前端·javascript
sophie旭17 分钟前
《深入浅出react》总结之 10.2 渲染阶段流程探秘-completeWork
前端·react.js·源码
拾光拾趣录18 分钟前
单点登录(SSO):实现跨系统无缝访问
前端·后端
程序员老廖19 分钟前
Markdown 功能支持测试文档
前端