第二篇:dumi + yarn workspaces + chageset 搭建前端组件库

131 阅读2分钟

概况:

       在组件库开发流程中,father 和 dumi 通常会协同工作。开发者使用 dumi 编写和预览组件文档,确保组件的使用方式和效果能清晰展示。当组件开发完成并测试通过后,使用 father 对组件库进行打包,生成可发布的产物

       yarn workspaces       依赖管理:能在根目录统一管理所有子项目的依赖,避免不同子项目重复安装相同依赖,节省磁盘空间和安装时间

       chageset       用于管理版本和生成变更日志、发布管理的工具

1、用dumi脚手架创建项目:

$ mkdir myapp && cd myapp  #建个空目录:myapp
$ npx @umijs/create-dumi-lib --site # 初始化一个站点模式的组件库开发脚手架

2、将脚手架生成的项目源码目录src ---> packages, 同时修改以下3个地方:

.fatherrc.ts

import { defineConfig } from 'father';

// 定义子包配置
const subPackages = ['ui-components'];

const umdConfigs = subPackages.map(pkg => ({
  umd: {
    name: `common-packages-${pkg}`,
    entry: `packages/${pkg}/src/index.ts`,
    output: `dist/umd/${pkg}`
  }
}));

export default defineConfig({
  // 配置 ESM 构建
  esm: {
    platform: 'browser', // 可按需调整为 'node'
    transformer: 'babel',
    input: 'packages', // 指定源码目录
    output: 'dist/esm'
  },
  // 配置 CJS 构建
  cjs: {
    platform: 'node',
    transformer: 'babel',
    input: 'packages', // 指定源码目录
    output: 'dist/cjs'
  },
  // 合并 UMD 配置
  ...umdConfigs.reduce((acc, curr) => ({
    umd: {
      ...acc.umd,
      ...curr.umd
    }
  }), { umd: {} })
});

.umirc.ts

import { defineConfig } from 'dumi';

export default defineConfig({
  title: 'myapp',
  favicon:
    'https://user-images.githubusercontent.com/9554297/83762004-a0761b00-a6a9-11ea-83b4-9c8ff721d4b8.png',
  logo: 'https://user-images.githubusercontent.com/9554297/83762004-a0761b00-a6a9-11ea-83b4-9c8ff721d4b8.png',
  outputPath: 'docs-dist',
  mode: 'site',
  resolve: {
    includes: ['packages', 'docs'],
  },
  // more config: https://d.umijs.org/config
});

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "jsx": "react",
    "esModuleInterop": true,
    "types": ["jest"],
    "strict": true,
    "skipLibCheck": true,
    "declaration": true
  },
  "include": ["packages/**/*.js", "packages/**/*.jsx", "packages/**/*.ts", "packages/**/*.tsx"],
  "exclude": ["node_modules", "lib", "es", "dist", "typings"]
}

上面改完后,执行: yarn, yarn完再执行:yarn build, 然后可以看到根目录多出了dist目录

没有build的话,推送到私库后,别的项目在引用这个组件库的组件时会报ts错误

3、修改 package.json 启用 workspace 模式

package.json
{
  "private": true,
  "name": "myapp",
  "version": "1.0.0",
  "workspaces": ["packages/*"],  // 启用Yarn Workspace
  "scripts": {
    "start": "dumi dev",
    "docs:build": "dumi build",
    "docs:deploy": "gh-pages -d docs-dist",
    "build": "father build",
  },
  "devDependencies": {}
}

初始化 changeset 配置:

bash
yarn add @changesets/cli -D -W
yarn changeset init

从这里开始就可以愉快的编写组件库了,把原先的packages目录里面的内容删掉,在packages目录新建两个demo目录,business-components、ui-components 组件包配置示例

package.json
{
  "name": "ui-components",
  "version": "1.0.0",
  "scripts": {
    "build": "father build",
    "dev": "father dev"
  }
}

!!!注意:

    ```
    "private": false,
    "main": "dist/cjs/index.js",
    "module": "dist/esm/index.js",
    "types": "dist/esm/index.d.ts",
    "files": [
        "dist"
    ],

根目录的package.json要添加上面配置,不然后面 npx changeset publish 推送到私库后,别的项目引用包时会有问题,会看不到dist目录,只有package.json文件

当别的项目下载你当前这个的组件库后,正常的目录结构会依据 package.json 和 father 构建配置来呈现,别的项目看到的这个组件库的结构应该是下面这样的:

node_modules/
└── myapp/
        ├── dist/
        │   ├── cjs/
        │   │   ├── ui-components/
        |   |            |── src
        |   |            |── package.json 
        │   ├── esm/
        │   │   ├── ui-components/
        |   |            |── src
        |   |            |── package.json
        │   └── umd/
        │   │   ├── ui-components/
        |   |            |── src
        |   |            |── package.json
        ├── node_modules
        ├── package.json
        └── ... 其他可能的文件(如 LICENSE、README.md 等)
# 创建组件包
mkdir -p packages/ui-components/src/Button

src/Button/index.tsx

import React from 'react';

interface ButtonProps {
  children: React.ReactNode;
}

const Button = ({ children }: ButtonProps) => (
  <button style={{ padding: '8px 16px' }}>{children}</button>
);

export default Button;
----------------------------------------------------
src/Button/index.md

---
title: Button 按钮
nav:
  title: 组件
  path: /components
group:
  title: 基础组件
  order: 1
---

<!-- 文档内容 -->

---------------------------------------------------
src/index.ts

export { default as Button } from './Button';

然后执行:

$ yarn build
然后执行:npm publish,会提示:Remove the 'private' field from the package.json to publish it.
根目录的package.json里面的  "private": true,改成:"private": false,
再次执行:npm publish   就可以把包发到本地私库了

或者可以用changeset发布

运行以下命令创建变更集:
$ npx changeset

运行该命令后,会有一系列交互提示:

-   选择需要发布新版本的包(若为单包项目,直接选择该包)。
-   为每个包选择版本升级类型(`patch`、`minor`、`major`)。
-   输入本次变更的描述信息。

创建变更集后,运行以下命令更新项目中各包的版本号并生成变更日志:
$ npx changeset version

最后,运行以下命令将更新后的包发布到 npm:
$ npx changeset publish

上面可能会报错:error an error occurred while publishing ui-components: EUNSCOPED Can't restrict access to unscoped packages.

解决方法:.changeset/config.json 里面的"access": "restricted" 改为 "access": "public"

此命令会自动将所有需要发布的包按照更新后的版本号发布到 npm 仓库。

然后,

在别的项目中引用时,直接yarn myapp@1.0.0,之后:

1、修改tsconfig.json, 添加字段:

"paths": {
    "@myapp/*": ["node_modules/myapp/dist/esm/*"],
 },

2、在需要引用的地方引用如下即可,

import Button  from '@myapp/ui-components/src/Button';

================================================================ 至此,搭建本地私库,然后0-1搭建组件库,再到把组件库提供给其它项目使用的全过程就结束了。 谢谢大家的阅览,感谢!!!