使用Vite构建cjs和esm格式的React组件库

背景

React 有很多现成的组件库,例如 Material UI 和 Ant Design 等都可以拿来直接用。为什么还要自己搭建 React 的组件库?

其实我们现实中会出现很多定制化的需求,并不能完全直接使用组件库的组件完成,多或少都会对上面的组件进行修改或者二次封装;这些定制化的需求,可能会应用到现实中的所有相同类型的项目当中,把这部分公共的组件抽离出来就更加有必要了。

思路

实现 TypeScript 类型支持的 React 组件库思路

  1. *.tsx 文件导出并打包成 esmcjs 等结构的 *.js 文件。
  2. 生成 *.d.ts 类型文件,让组件库支持 TypeScript 类型。
  3. *.css 样式文件与 *.tsx 文件分离,有利于实现组件和样式的按需加载。

实现

一. 初始化项目

方法一:

首先,确保您在机器上已经安装了Node.js。然后,在终端中执行以下命令来全局安装Vite:

js 复制代码
npm install -g create-vite

接下来,使用Vite初始化一个新的React项目:

arduino 复制代码
create-vite my-component-library --template template-react-ts

方法二(推荐):

js 复制代码
# npm 7+, extra double-dash is needed:
npm create vite@latest my-component-library --template template-react-ts

# yarn
yarn create vite my-component-library --template template-react-ts

# pnpm
pnpm create vite my-component-library --template template-react-ts

# Bun
bunx create-vite my-component-library --template template-react-ts

这个命令将会创建一个名为my-component-library的目录,并在其中生成一些初始化的React项目文件。

二、组件开发和导出

进入到my-component-library目录中,您可以开始编写属于您组件库的React组件。

lua 复制代码
|-- src
    |-- components
        |-- Button.tsx
        |-- Input.tsx
    |-- main.js

例如,您可以在src目录下创建一个Button.tsx文件,编写一个简单的按钮组件:

js 复制代码
import React from 'react';

function Button({ text, onClick }) {
  return (
    <button onClick={onClick}>
      {text}
    </button>
  );
}

export default Button;

在这里,我们编写了一个Button组件,并通过export default语句进行导出。

三、配置Vite

配置Vite构建选项 在my-component-library目录下,找到并打开vite.config.js文件。在文件中添加以下配置选项:

php 复制代码
// vite.config.js
import { defineConfig, loadEnv } from "vite";
import react from "@vitejs/plugin-react-swc";
import { resolve, join } from "path";
import { visualizer } from "rollup-plugin-visualizer";

export default defineConfig({
  plugins: [react(), visualizer() as any],
  build: {
    lib: {
      entry: 'src/main.ts', // 组件库的入口文件
      name: 'MyComponentLibrary', // 组件库的全局变量名
      fileName: format => `my-component-library.${format}.js`, // 构建输出的文件名
    },
    rollupOptions: {
      external: ['react', 'react-dom'], // 外部依赖
      output: [
      // ES Module 模块格式的编译
        {
            format: "es",
            entryFileNames: "[name].mjs",
            preserveModules: true,
            exports: undefined,
            dir: resolve(__dirname, `es`),
            preserveModulesRoot: "src",
       },
       // CommonJS 模块格式的编译
       {
            format: "cjs",
            entryFileNames: "[name].js",
            //让打包目录和我们目录对应
            preserveModules: true,
            exports: "named",
            //配置打包根目录
            dir: resolve(__dirname, `lib`),
            preserveModulesRoot: "src",
	},
    ],
    },
  },
});

在上述配置中,我们使用build.lib.entry来指定组件库的入口文件(例如src/main.ts),build.lib.name来指定组件库的全局变量名(例如MyComponentLibrary),build.lib.fileName指定构建输出的文件名,可以根据需要使用不同的格式(例如escjs)。此外,我们还配置了外部依赖(如reactreact-dom)和对应的全局变量名。

四、配置tsconfig.build.json

my-component-library目录下新建一个tsconfig.build.json文件。

js 复制代码
// tsconfig.build.json
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "declaration": true,
    "emitDeclarationOnly": true,
    "outDir": "./es",
    "noEmit": false
  },
  "include": [
    "src"
  ]
}

五、配置package.json

js 复制代码
...
"name": "my-component-library",
"version": "1.0.0",
"scripts": {
+ "build": "rimraf es && tsc && vite build && tsc --project tsconfig.build.json",
},
"main": "lib/index.js",
"module": "es/index.mjs",
"typings": "es/index.d.ts",
...

六、构建组件库

完成组件开发和Vite配置后,使用以下命令来构建组件库:

arduino 复制代码
npm run build

Vite将会根据vite.config.js中的配置选项,生成构建输出的文件并保存在eslib目录下。

七、使用组件库

构建完成后,您可以将eslib目录下生成的文件直接用于其他项目中,例如通过npm包管理工具进行安装和引入。

在您的目标项目中,您可以使用import或require语法来导入组件库的组件:

  • ES模块中使用import:
javascript 复制代码
import Button from 'my-component-library/es/index.mjs';
  • CommonJS模块中使用全局引用:
xml 复制代码
<script src="my-component-library/lib/index.js"></script>

注意:上述示例中的文件路径根据实际构建生成的文件名和文件路径进行调整。

结论

通过使用Vite构建工具,我们可以快速构建React组件库,并实现同时支持cjsES模块化导出。通过适当的配置,我们可以生成适用于不同模块系统的构建文件,并轻松地在其他项目中使用我们的组件库。希望本文对您有所帮助!

Q&A

  • Q: 有源码吗?

当然有,地址如下:github.com/027xiguapi/...,有兴趣的话可以大家一起探讨,同时也欢迎大家forkstar

相关推荐
会飞的鱼先生8 分钟前
vue3自定义指令来实现 v-copy 功能
前端·javascript·vue.js
陈天伟教授21 分钟前
Web前端开发 - 制作简单的焦点图效果
java·开发语言·前端·前端开发·visual studio
_殊途32 分钟前
前端三件套之html详解
前端·html
不思念一个荒废的名字1 小时前
【黑马JavaWeb+AI知识梳理】后端Web基础03 - MySQL概述
前端·数据库·mysql
谢尔登2 小时前
【React Native】快速入门
javascript·react native·react.js
进取星辰2 小时前
32、跨平台咒语—— React Native初探
javascript·react native·react.js
橙子199110162 小时前
谈谈 Kotlin 中的构造方法,有哪些注意事项?
java·前端·kotlin
*neverGiveUp*3 小时前
本地分支git push 报错 fatal: The current branch XXXX has no upstream branch.
前端·git·gitea
AaronZZH3 小时前
为什么现代CSS应该选择OKLCH:从颜色科学到设计系统革新
前端·css
CaseyWei3 小时前
JS实现直接下载PDF文件
前端·javascript