从0到1搭建react组件库-开发方案篇

832 阅读4分钟

前言

相关文章链接:

从0到1搭建react组件库-项目规范篇

从0到1搭建react组件库-文档篇

# React文档深扒:useState背后的真相!

开发环境配置

下文中的pnpm i在任何目录下都可以执行,pnpm会识别所有的子包。(如果文章中有错误内容,欢迎大家交流指正。)

typescript

  1. 打开根目录的package.json文件。
  2. 然后在devDependencies字段中添加typescript以及最新的版本号。
// 根目录 package.json
{
 
  "devDependencies": {
    ...
    "typescript": "5.6.2"
  }
}
  1. 在命令行中运行pnpm i, 下载安装typescript的依赖。
  2. 在根目录中新建一个ts.config.json文件,用来配置typescript的基本内容(子包的ts继承于根目录tsconfig即可)。
// 根目录 tsconfig.json
{
  "compilerOptions": {
    "target": "ES2015",
    "lib": ["DOM", "ESNext"] ,
    "module": "CommonJS",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "jsx": "react-jsx",
  },
}

react

  1. 打开命令行,进入packages/ui的目录下。
  2. 通过命令npm init -y生成package.json文件。
  3. 修改package.json文件的内容。
    • 主要增加react和react的类型的依赖,注意此时react的依赖添加值peerDependencies, 表明对其他库的兼容声明。
    • 修改name字段,将其修改为“@mini-ui/ui”。
    • 具体文件内容参照下面内容:
      // packages/ui/package.json
        {
          "name": "@mini-ui/ui",
          "version": "1.0.0",
          "description": "",
          "main": "index.js",
          "scripts": {
          },
          "keywords": [],
          "author": "",
          "license": "ISC",
          "devDependencies": {
            "@types/react": "18.3.7"
          },
          "peerDependencies": {
            "react": "18.3.1"
          }
        }
      
  4. 在命令行中进入packages/ui目录下, 运行命令pnpm i, 安装全部依赖。

less

less的配置,主要是通过esbuild的插件实现打包时的转化,具体实现参照打包方案内容。

打包方案

打包方案有很多,比如常见的webpack、vite、rollup等常见打包工具,但是在这里选用了tsup作为打包工具,首先它在对esbuild进行封装后,不仅直接支持了ts的打包,并且打包速度极快。而且tsup几乎不需要怎么配置就可以直接上手使用。

tsup

  1. 首先进入到packages/ui 的目录下。
  2. 修改package.json文件的内容。
    • 这里主要是增加tsup,以及esbuild的less插件(tsup支持直接使用esbuild插件),提供对ts以及less的处理方案。
    // packages/ui/package.json
        {
          "name": "@mini-ui/ui",
          "version": "1.0.0",
          "description": "",
          "main": "index.js",
          "scripts": {
          },
          "keywords": [],
          "author": "",
          "license": "ISC",
          "devDependencies": {
            "tsup": "8.3.0",
            "esbuild-plugin-less": "1.3.9",
            "@types/react": "18.3.7"
          },
          "peerDependencies": {
            "react": "18.3.1"
          }
        }
    
  3. 下载安装tsup以及esbuild-plugin-less, 在当前目录执行pnpm i
  4. 安装之后,创建tsup.config.ts, 对当前打包以及插件进行配置。
// packages/ui/tsup.config.ts
import { defineConfig } from "tsup";
import {lessLoader} from "esbuild-plugin-less";
export default defineConfig({
  entry: ["src"], // 打包入口文件
  splitting: true, 
  sourcemap: true, // 是否开启sourcemap, 这里可以关闭。
  clean: true, 
  outDir: "dist", // 打包文件输出目录
  dts: true, // 是否打包ts类型
  format: ["esm"], // 打包规范
  esbuildPlugins: [
      lessLoader()
  ]
})
  1. 在ui目录下新建一个src目录,并新建一个index.ts文件作为tsup打包的入口文件。

  2. 在package.json下增加具体的打包命令,同时声明esm规范下的项目入口,以及typescript类型的入口。

    // packages/ui/package.json
    {
      "name": "@mini-ui/ui",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "module": "./dist/index.mjs",  // esm规范下的项目入口
      "types": "./dist/index.d.mts", // typescript类型的入口
      "scripts": {
        "dev": "tsup --watch",
        "build": "tsup"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "tsup": "8.3.0",
        "esbuild-plugin-less": "1.3.9",
        "@types/react": "18.3.7"
      },
      "peerDependencies": {
        "react": "18.3.1"
      }
    }
  1. 测试, 在packages/ui目录下,执行pnpm run build, 即可打包出对应的dist文件。
    pnpm build

image.png

测试

声明Button

  1. 进入ui/src目录下创建compoents/Button目录,在内部创建Button.tsx、index.ts、interface.ts、style/index.less文件,分别对应button组件文件,导出出口,类型声明, 样式文件。

    • Button.tsx
      // packages/ui/src/components/Button/Button.tsx
      import {ButtonProps} from "./interface";
      import "./style/index.less"
      export const Button = (
          props: ButtonProps
      ) => {
        return <button className="mini-btn">this is a button</button>
      }
      
    • index.ts
      // packages/ui/src/components/Button/index.ts
      export * from "./Button";
      
    • interface.ts
      // packages/ui/src/components/Button/interface.ts
      import { ReactNode } from "react";
      export interface ButtonProps {
        children?: ReactNode;
      }
      
    • style/index.less
      .mini-btn {
        color: #1a1a1a;
        background-color: #fff;
      }
      
  2. 然后在ui/src/components目录下的新建index.ts文件中导出Button组件的内容。

    // packages/ui/src/components/index.ts
        export * from "./Button";
    
  3. 然后在ui/src/目录下的index.ts文件(tsup配置的第5步)中导出components下的所有内容。

    // packages/ui/src/index.ts
        export * from "./components";
    
  4. 在package/ui下运行pnpm build命令, 重新打包。

  5. 最终目录结构如下图:

image.png

playground中引入组件

  1. 进入apps目录下,然后运行pnpm create vite playground --template react-ts(这里使用的是vite,其他的脚手架也是一样的)创建一个新的react项目。
  2. 修改playground目录下的package.json, 添加组件库的包,这里使用的是pnpm-workspace的语法, 具体参考下面的内容:
// apps/playground/package.json
{
  "name": "demo",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc -b && vite build",
    "lint": "eslint .",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "@mini-ui/ui": "workspace: *"  // 引入刚才打包的组件库,注意需要和目标package.jsonname保持一致
  },
  "devDependencies": {
    "@eslint/js": "^9.9.0",
    "@types/react": "^18.3.3",
    "@types/react-dom": "^18.3.0",
    "@vitejs/plugin-react": "^4.3.1",
    "eslint": "^9.9.0",
    "eslint-plugin-react-hooks": "^5.1.0-rc.0",
    "eslint-plugin-react-refresh": "^0.4.9",
    "globals": "^15.9.0",
    "typescript": "^5.5.3",
    "typescript-eslint": "^8.0.1",
    "vite": "^5.4.1"
  }
}
  1. 在playground目录下运行pnpm i命令,更新安装包。
  2. 启动react项目的服务,然后在playground的目录下,引入组件库的文件, 若无报错,像下图button组件正常展示,即说明目前配置正常。
// apps/playground/src/App.tsx
import { Button } from "@mini-ui/ui"
import "@mini-ui/ui/dist/index.css"

function App() {

  return (
    <>
      <Button></Button>
    </>
  )
}

export default App

image.png

项目地址

未完待续

后续补充文档方案(rspress)。