使用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或者私有源即可

相关推荐
丷丩1 小时前
MapLibre GL JS第20课:更新GeoJSON多边形
前端·javascript·gis·mapbox·maplibre gl js
swipe1 小时前
DeepAgents middleware 工程实战:把复杂 Agent 的运行时基建交给可组合中间件
前端·面试·llm
丷丩1 小时前
MapLibre GL JS第33课:渲染世界副本
javascript·gis·map·mapbox·maplibre gl js
前端环境观察室1 小时前
别让 Agent 浏览器任务无限重试:失败分类、RetryPolicy 与人工复核
前端
bonechips1 小时前
深入理解 JavaScript的历史包袱——变量提升(Hoisting)
javascript·深度学习
喵个咪2 小时前
Headless 后端实践:基于Go的企业级多栈管理系统脚手架
前端·vue.js·react.js
m0_738120722 小时前
渗透测试基础——黑盒测试下的Web漏洞挖掘与利用解析(一)
服务器·前端·网络·安全·php
丷丩2 小时前
MapLibre GL JS第31课:添加实时数据
javascript·gis·map·mapbox·maplibre gl js
candyTong3 小时前
Claude Code 每次调用 API 时,上下文是怎么"拼"出来的?
javascript·后端·架构
小林ixn3 小时前
别再背“变量提升”了!深入编译执行,彻底搞懂 JavaScript 运行机制
javascript