Catalyst

Vue3 组件库组织学习(一)

出于学习的目的探究一下 Vue3 组件库的编写,刚好整个新 web app 用得上。写组件本身问题不大,难受的是写文档 |・ω・`) 目前主要探索一下文件组织。

太长了分成上下篇吧,上篇是组织和编写。

一边写一边改的,可能有地方先写了后改的对不上。

建立项目

使用 vue3 + vite + typescript

新建项目

npm init vite-app rect-ui -- --template vue-ts
  • template 里的组件版本可能不是最新的,检查更新下package.json
  • 为了支持摇树优化,更新 tsconfig.jsontargetes6 及以上。

文件组织

参考一下一些大组件库的组织方法:

总结了个我自己能理解的样子 🤨:

.
├── docs/
│   └── docs
└── packages/
    ├── 其他
    ├── components/
    │   └── button/
    │       ├── tests/
    │       │   └── button.test.ts
    │       ├── demo/
    │       │   └── demo.vue
    │       ├── index.vue
    │       ├── index.ts
    │       └── Readme.md
    └── index.ts

事实上没人用 index.vue 这种写法,都直接上组件名。这是为了后期文档生成能偷懒(擦汗)。

按需安装

在使用别的 UI 库的时候经常见到按需安装的条目,可以只安装需要的组件。

需要给每个可以自主安装的组件一个install函数用来调用。

写完后思考了一下,现在的 tree-shaking 这么先进,还有写这种按需安装方法的必要吗?

就当研究一下组件库都有的东西是什么样的好了 😂,下次不写了(还有下次吗)

// packages/components/button/index.ts

import type { App } from "vue";

import RButton from "./index.vue";

const Button = {
  install(Vue: App) {
    Vue.component(RButton.name, RButton);
  },
};

export default Button;
export { RButton };
// packages/components/index.ts
export * from "./button";
export { default as Button } from "./button";

安装所有组件的主函数

// packages/index.ts

import * as components from "./components";
import "./css/color.css";
import "./css/common.styl";

const ComponentLibrary = {
  install(Vue, options = {}) {
    // components
    for (const componentName in components) {
      const component = components[componentName];
      component.install = function (Vue) {
        Vue.component(component.name, component);
      };
      Vue.component(component.name, component);
    }
  },
};

export default ComponentLibrary;
export * from "./components";

测试按需安装成功,但 tree shaking 一直下不来,最后搜索到了 这里,原来在 TS 里要自己加 /*#__PURE__*/…… 😢

修改组件定义为 export default /*#__PURE__*/ defineComponent,打包后用 agadoo 检查,通过了。

不过这样打断后用vue-docgen-cli生成文档就无法识别自定义名字了,所以后来就先打包,再批量改。

测试

Jest

  1. 安装依赖
yarn add -D @babel/preset-env @babel/preset-typescript @testing-library/jest-dom @types/jest @vue/babel-plugin-jsx @vue/test-utils@next @vue/vue3-jest ts-jest jest-environment-jsdom jest
包名说明
@babel/preset-env智能设定,使用最新的 JavaScript。
@babel/preset-typescriptbabel 的 typescript 支持
@testing-library/jest-dom用来添加一些方便 DOM 测试的函数。
@types/jestjest 提供类型定义。
@vue/babel-plugin-jsx添加 Vue JSX 转译支持。
@vue/test-utils@nextvue3 的测试套组。
@vue/vue3-jest用于 Vue 单文件组件 (SFC) 的 Jest transformer。
ts-jest提供 ts 测试支持
jest-environment-jsdom提供 jsdom 测试环境。
jest测试工具。
  1. 新建 jest.config.js 并设置
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
  preset: "ts-jest",
  testEnvironment: "jsdom",
  transform: {
    "^.+\\.vue$": "@vue/vue3-jest", // Update to match your installed version
    "^.+\\js$": "babel-jest",
  },
  testMatch: ["**/tests/*.test.[jt]s?(x)"],
  moduleFileExtensions: ["js", "jsx", "ts", "tsx", "vue"],
  testEnvironmentOptions: {
    customExportConditions: ["node", "node-addons"],
  },
  globals: {
    "ts-jest": { babelConfig: true },
  },
};
  1. 新建 babel.config.js 并设置:
module.exports = {
  presets: [
    ["@babel/preset-env", { targets: { node: "current" } }],
    "@babel/preset-typescript",
  ],
  plugins: ["@vue/babel-plugin-jsx"],
};
  1. 运行测试
npx jest

Vitest

整理完了 Jest 后一搜发现了新的(两眼一黑)。但 Jest 怎么说也是起了个新环境,需要共用设置时能 vite 一把梭还是很好的。vitest 官网,测试用例 API 和 Jest 兼容。

  1. 安装依赖
yarn add -D vitest jsdom

套件没有内置模拟环境,需要自选 jsdom 或者 happy-dom 安装。

  1. 和 vite 共用配置,可以直接将配置写在 vite.confing.js里,其余情况参见 配置
import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    include: ["**/tests/*.test.[jt]s?(x)"],
    environment: "jsdom",
  },
});
参考资料