用 Mitosis 来搭建一个多框架支持的前端组件库

2,475 阅读8分钟

大家好,我是馋嘴的猫,今天来给大家介绍一个最近新出的框架 Mitosis

在这篇教程中,除了会介绍 Mitosis 是什么,如何使用 Mitosis,还会借助 Mitosis 框架的转换功能,来实现一个组件库项目,让开发者只需要写一次组件库源码,即可同步生成多个前端框架(React、Vue、Solid)的组件库代码。

是不是心动了?竟然有框架这么厉害,可以省我们好多功夫来支持不同前端框架,快来跟着教程一起学习一下吧~

Mitosis 是什么?

Mitosis 的宗旨,即是为开发者提供一种方式,通过书写符合 mitosis 规范的 JSX 文件,配置需要打包的平台(targets),使用 Mitosis cli 的 build 指令,即可生成指定平台(React、Vue、Solid)的源代码。

开发者可以在不熟悉多种框架的语法的场景下,也能为它们提供源代码级别的支持,这,就是 Mitosis 的独到之处。

在线 Mitosis 转换效果体验:mitosis.builder.io/

体验 Mitosis 的构建

为了方便开发者体验,我这里已经将示例工程提交到 github 仓库,可以克隆下来对照着下面教程观看。

现在,让我们开始 mitosis 框架的引入和构建吧~

步骤

  1. 新建项目,执行以下命令,为项目安装上对应的 mitosis 依赖。
# 这里只列了mitosis的依赖,其他依赖可查看示例工程的package.json
pnpm add @builder.io/mitosis @builder.io/mitosis-cli 
pnpm add @builder.io/eslint-plugin-mitosis -D
  1. 在项目根目录新建一个mitosis.config.js的文件,开始书写 Mitosis 的配置。配置文档点此查看
/** @type { import('@builder.io/mitosis').MitosisConfig } */
module.exports = {
    files: 'src/**',
    targets: ['solid', 'react', 'vue'],
    dest: "dist",
    options: {
        solid: {
            typescript: true,
            stylesType: 'styled-components'
        },
        react: {
            typescript: true,
            stylesType: "style-tag",
        },
        vue3:{
            typescript: true,
        }
    }
};
  1. 配置 tsconfig.json,加上对 Mitosis JSX 的支持。
 // tsconfig.json关于mitosis的配置,完整文件可查看示例工程的tsconfig.json
{
  "compilerOptions": {
    "jsx": "preserve",
    "jsxImportSource": "@builder.io/mitosis"
  }
}
  1. 新建 src 目录,在里面开始书写 Mitosis 支持的 tsx/jsx 代码。注意,保存的时候扩展名必须以.lite.tsx.lite.jsx保存。

注:Mitosis JSX 与普通 React JSX 类似,但不同点如下:

  • 语法限制:文档,可通过 mitosis 的 eslint 插件提醒来规避
  • Hooks:文档
  • 组件规则:文档

在src目录下,我们新建一个image.lite.tsx,并填入以下内容。

//image.lite.tsx
interface ImageProps {
    style?: any;
    children?: any;
    onClick?: () => void;
    src: string;
}

export default function Image(props: ImageProps) {
    return (
        <img
            style={props?.style ?? {}}
            src={props.src}
            onClick={() => {
                props?.onClick?.()
            }}
        >
            {props.children}
        </img>
    );
}
  1. 在 package.json 添加 build 指令。
// package.json
"scripts":{
   "build": "rm -rf dist && mitosis build"
}
  1. 在项目根目录下执行pnpm build指令,由于在我们刚刚的步骤 3 中,配置了 targets 为['solid', 'react', 'vue'],因此,只要 build 命令成功执行,我们即可在 dist 目录里,找到对应的三个框架的文件夹,生成的源码也在其中。
  1. 现在快打开看看,你的代码已经正确产出为对应平台的代码了,是不是很神奇~

以下是 vue3 的源码文件:

//image.vue
<template>
  <img :style="style ?? {}" :src="src" @ click="onClick?.()" />
</template>

<script setup  lang="ts">
interface ImageProps {
  style?: any;
  children?: any;
  onClick?: () => void;
  src: string;
}

const props = defineProps<ImageProps>();
</script>
  1. 至此,我们就完成 Mitosis 构建多端源代码的全流程了。

接下来,我们将会结合 Mitosis 的能力,来搭建一个多框架支持的前端组件库。

搭建组件库

在这个章节中,我们将会聚焦在,如何通过 Mitosis 实现 “写一次代码,输出多份框架源码和产物” 的需求。

同样,为了方便开发者体验,我也已经组件库工程提交到 github 仓库,可先克隆下来,对照以下教程正文阅读。

项目大致目录结构如下,可对照源码查看。

|-- work
    |-- package.json
    |-- pnpm-workspace.yaml
    |-- examples  // 示例工程
    |   |-- react-demo   // React 项目
    |   |-- solid-demo   // Solid 项目
    |-- packages
        |-- mitosis-components   // Mitosis 源码与构建目录
            |-- mitosis.config.js
            |-- tsconfig.json    // Mitosis 构建的 ts 配置
            |-- src     // Mitosis tsx/jsx 源码位置
            |   |-- index.ts  
            |   |-- components
            |       |-- image.lite.tsx
            |       |-- index.ts
            |-- templates    // 框架源代码构建所需的npm依赖和ts配置文件
                |-- react
                |   |-- package.json
                |   |-- tsconfig.json
                |-- solid
                    |-- package.json
                    |-- tsconfig.json
                    |-- tsconfig.node.json

OK,废话不多说,让我们先确定下组件库的目标。

目标

  1. 通过书写 Mitosis TSX,生成 React 和 Solid 的源代码与产物

  2. 新增 React 和 Solid 框架的示例工程,在各自项目中引用 Mitosis 转换生成的产物,并验证组件是否能正常使用

目标定好了,让我们开始吧,实现步骤如下:

步骤

  1. 新建一个目录,拷贝 package.json 至项目的根目录,并新建 pnpm-workspace.yaml,填入以下内容。
// pnpm-workspace.yaml
packages:
  - packages/*
  - examples/*
  1. 执行pnpm install安装依赖。
  2. 在根目录新建 packages 目录,再在其下新建一个 mitosis-components 目录。
mkdir pacakges packages/mitosis-components
  1. 在 mitosis-components 目录新建 components 目录与一个 index.ts 文件
cd packages/mitosis-components
mkdir components
touch index.ts
  1. 在 components 目录下新建一个 image.lite.tsx,使用 Mitosis JSX 语法书写逻辑。具体内容可拷贝 github 仓库源码

注:Mitosis JSX 语法与普通 JSX 类似,但文件需以.lite.tsx 结尾,具体规则可以阅读文档了解。

  1. 在 components 目录新建一个 index.ts,导出 image 组件
// components/index.ts
export { default as Image } from './image.lite';
  1. 返回到 components 目录的上一级目录mitosis-components下,新建一个 index.ts,导出所有的 component 目录的组件
// mitosis-components/index.ts
export * from './components';
  1. 在 mitosis-components 目录下,新建一个 templates 目录,并新建两个目录:react 和 solid,从 github 仓库拷贝对应的 package.json 和 tsconfig.json。

这个步骤的意义:为后面生成的 React、Solid 源代码提供编译产物必须的 npm 依赖与 tsconfig 配置。

  1. 拷贝 Github 仓库的.eslintignore .eslintrc.js package.json 代码至 mitosis-components 目录,为仓库提供 eslint 检查功能与配置必要依赖(需执行命令 pnpm install 安装)。
  2. 这个时候,我们已经完成 Mitosis 组件库源码仓库的搭建了。在 mitosis-components 目录,执行以下命令,开始构建源码。
pnpm generate:source

构建成功后,对应框架的源码可以在 mitosis-components 的 dist 目录下查看到。

注:可以看到,在步骤 8 创建的 templates 目录下放置的 react 与 solid 目录的 package.json 和 tsconfig.json,在执行命令后也被一并拷贝了过来,为下一个步骤的构建做准备。

  1. 回到我们一开始的目标,我们需要实现一个组件库,但直接提供源码给别人集成是一种不太好的方式。因此,我们还需要打包为 js,再通过 npm 包的方式,提供一个完整的组件库,类似 Ant design,Element 等。

在根目录,执行以下命令,构建 js 产物。

pnpm bundle:all

构建成功后,对应框架的 js 产物与类型定义可以在 mitosis-components 的 dist 目录下查看。

  1. 此时,查看 mitosis-components 目录下的 package.json,可以看到已配置了 Solid 和 React 产物的 export 选项,实现了组件库的导出。
// package.json
"exports": {
  "./react": {
    "import": "./dist/react/dist/index.js",
    "types": "./dist/react/dist/types/index.d.ts"
  },
  "./solid": {
    "import": "./dist/solid/dist/index.js",
    "types": "./dist/solid/dist/types/index.d.ts"
  }
},
  1. 至此,我们就完成了 Mitosis 组件库的所有部分代码。接下来,我们需要在具体的项目中引用并体验效果了

  2. 在 examples 目录,新建solid-demoreact-demo,将 github 对应代码拷贝至对应目录。

    1. solid-demo 源码:点此查看
    2. react-demo 源码:点此查看
    3. 拷贝完两个目录后,再在根目录下执行pnpm install安装依赖。
  3. 查看 react-demo/app/page.tsx,实现了 React 组件库 Image 组件的引入与使用,具体代码如下:

// page.tsx
import {Image as MitosisImage} from 'mitosis-component-library/react'
return (
    // 省略其他视图代码
    <MitosisImage src={"/vercel.svg"}/>
)

在 react-demo 目录下执行命令pnpm dev, 访问http://localhost:3000,验证 Image 组件渲染结果,结果是完全 ok 的~

  1. 查看 solid-demo/src/page.tsx,也实现了 Solid 组件库 Image 组件的引入与使用,具体代码如下:
// page.tsx
import {Image} from 'mitosis-component-library/solid';
return (
    // 省略其他视图代码
    <Image src={solidLogo} style={{"width":"8em","height":"8em"}} />
)

在 solid-demo 目录下执行命令pnpm dev, 访问http://localhost:5173,验证 Image 组件渲染结果,结果也是完全 ok 的~

  1. 至此,我们完成了组件库在实际项目(React、Solid 框架)的验证。

总结

在以上的教程中,我们实现了以下几点功能点:

  1. 通过 Mitosis-cli 配合 Mitosis tsx 文件的书写,实现了写一份组件代码,即可生成多个前端框架的组件源码

  2. 通过 Mitosis 生成好的前端源码,再配合自动化的打包工序,生成对应框架的 js 产物,并以 npm 包的形式提供给其他开发者,实现了多框架支持的前端组件库

  3. 在示例项目中引用前端组件库的组件并展示,验证了多端组件的一致性

Mitosis 在开发过程中,也是优缺点兼有,开发者可以根据自己的需要选择是否采用。

优点

  1. 只需要写一次 Mitosis JSX,即可以支持多达 20 多种框架源码输出,支持的平台可点此查看
  2. Mitosis 的打包配置非常齐全,开发者可以自由配置比如语法格式(比如 Vue3 的 Options API 或 Composition API),样式库(Styled Component 或 Emotion CSS prop)等等,适合各种业务场景的需求。
  3. 在遇到尚未支持的框架或框架新语法尚未被 Mitosis 官方支持时,可以根据官方文档实现定制 Plugin,或者 fork mitosis 仓库实现新的 generator(因 Mitosis 官方暂无提供手动配置新 generator 的方法)

缺点

  1. 为了适应多种框架,Mitosis JSX 语法限制较多,在使用时可以配合 eslint 插件提示,参考文档

  2. Mitosis 打包后只会输出源码,默认情况下不能直接执行打包,比较繁琐。开发者可参照上面的组件库教程与github仓库源码,实现在 Mitosis 输出源码后后自动进行打包操作。

好的,以上就是对如何使用 Mitosis 来搭建前端组件库的全部介绍啦!

欢迎多多点赞,有问题也欢迎在评论区交流~