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

大家好,我是馋嘴的猫,今天来给大家介绍一个最近新出的框架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 依赖。
shell 复制代码
# 这里只列了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 的配置。配置文档点此查看
js 复制代码
/** @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 的支持。
js 复制代码
 // 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,并填入以下内容。

typescript 复制代码
//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 指令。
js 复制代码
// package.json
"scripts":{
   "build": "rm -rf dist && mitosis build"
}
  1. 在项目根目录下执行pnpm build指令,由于在我们刚刚的步骤 3 中,配置了 targets 为['solid', 'react', 'vue'],因此,只要 build 命令成功执行,我们即可在 dist 目录里,找到对应的三个框架的文件夹,生成的源码也在其中。

  1. 现在快打开看看,你的代码已经正确产出为对应平台的代码了,是不是很神奇~

以下是 vue3 的源码文件:

html 复制代码
//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 仓库,可先克隆下来,对照以下教程正文阅读。

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

text 复制代码
|-- 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,填入以下内容。
yaml 复制代码
// pnpm-workspace.yaml
packages:
  - packages/*
  - examples/*
  1. 执行pnpm install安装依赖。
  2. 在根目录新建 packages 目录,再在其下新建一个 mitosis-components 目录。
shell 复制代码
mkdir pacakges packages/mitosis-components
  1. 在 mitosis-components 目录新建 components 目录与一个 index.ts 文件
shell 复制代码
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 组件
ts 复制代码
// components/index.ts
export { default as Image } from './image.lite';
  1. 返回到 components 目录的上一级目录mitosis-components下,新建一个 index.ts,导出所有的 component 目录的组件
ts 复制代码
// 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.jspackage.json代码至 mitosis-components 目录,为仓库提供 eslint 检查功能与配置必要依赖(需执行命令 pnpm install 安装)。
  2. 这个时候,我们已经完成 Mitosis 组件库源码仓库的搭建了。在 mitosis-components 目录,执行以下命令,开始构建源码。
shell 复制代码
pnpm generate:source

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

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

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

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

shell 复制代码
pnpm bundle:all

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

  1. 此时,查看 mitosis-components 目录下的 package.json,可以看到已配置了 Solid 和 React 产物的 export 选项,实现了组件库的导出。
js 复制代码
// 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 组件的引入与使用,具体代码如下:

tsx 复制代码
// 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 组件的引入与使用,具体代码如下:
tsx 复制代码
// 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 来搭建前端组件库的全部介绍啦!

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

相关推荐
你挚爱的强哥42 分钟前
✅✅✅【Vue.js】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本
javascript·vue.js·jquery
y先森1 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy1 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189111 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿2 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡3 小时前
commitlint校验git提交信息
前端
虾球xz4 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇4 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒4 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员4 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js