用dumi + umi + lerna 搭建一个组件库项目

122 阅读3分钟

前言

本文章主要是为了自己学习如何使用lerna,如果有什么写的不对,欢迎在评论区指出。

初始化项目

首先要下载lerna,全局安装lerna

npm install --global lerna

创建一个自己的项目

mkdir my-component-library

进入自己的项目

cd my-component-library

然后执行下面的指令

lerna init

如果不想全局安装,也可以在新建好一个项目之后,在项目内部执行下面的这个命令,去创建一个Single Pattern 的单一模式的项目,还有一个Multiple Patterns,这两者之间的区别,可以参考lerna的官网解释

npx lerna init --packages="packages/*"

安装依赖

我想创建的是一个react + typescript组件库的项目,所以我需要在我的项目里面安装一些依赖

npm install --save react react-dom
npm install --save-dev typescript prettier babel-plugin-import @umijs/babel-preset-umi lerna dumi antd @ant-design/icons

配置

在安装完依赖之后,要对typescript和babel进行一些配置,在tsconfig.json中要加下include

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom","ES2015","ESNext"],
    "module": "esnext",
    "moduleResolution": "node",
    "jsx": "react",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "baseUrl": ".",
    "paths": {
      "csstype": ["node_modules/csstype"]
    },
  },
  "include": ["packages/**/*"],
  "exclude": ["node_modules"]
}


设置lerna中的管理包

我下面就以写一个button组件为例展示一下,先要在packages文件夹下创建一个button的文件夹 mkdir packages/button

在button文件夹下,手动创建一个package.json的文件,目前lerna没有创建这个package.json的指令,如果不想自己手动创建,也可以自己尝试写一些脚本去创建

{
  "name": "@my-library/button",          // 包的名称
  "version": "1.0.0",                    // 包的版本
  "main": "lib/index.js",                // 包的 CommonJS 入口文件
  "module": "es/index.js",               // 包的 ES 模块入口文件
  "typings": "es/index.d.ts",            // TypeScript 类型声明文件
  "dependencies": {                      // 生产环境依赖
    "react": "^18.2.0",                  // React 库,版本要求大于等于 18.2.0
    "antd": "^5.1.7"                     // Ant Design 库,版本要求大于等于 5.1.7
  },
  "devDependencies": {                   // 开发环境依赖
    "typescript": "^4.6.4"               // TypeScript,版本要求大于等于 4.6.4
  }
}

组件代码的打包

在button目录下新建一个src/index.tsx文件,在里面简单的写一个button组件

import React from 'react';

const MyButton: React.FC = () => {
  return <button >Click me</button>;
};

export default MyButton;

再在下面创建一个tsconfig.json的文件

{
  "compilerOptions": {
    "target": "es5",
    "module": "esnext",
    "lib": ["dom","ES2015","ESNext"],
    "jsx": "react",
    "declaration": true,
    "outDir": "./lib",
    "esModuleInterop": true,
     "forceConsistentCasingInFileNames": true,  // 启用这个选项
      "baseUrl": ".",
    "paths": {
      "csstype": ["node_modules/csstype"],
      
    },
    "skipLibCheck": true
  },
  "include": ["src/**/*"]
}

组件文档的生成

可以使用dumi来生成组件的文档

npm install --save-dev dumi

在项目的根目录下创建一个.umirc.ts的文件去配置dumi

export default {
  title: 'My Component',
  base: '/my-component/',
  publicPath: '/my-component/',
  logo: 'https://demo.com/logo.png',
  outputPath: 'docs-dist',
  themeConfig: {
    name: 'My Component',
  },
};

添加组件文档

在packages/button 目录下,创建一个README.md的md格式的文件,在里面写一下button这个组件的相关文档,如:

# Button 组件

这是一个简单的按钮组件。

## 使用方法

```tsx
import { Button } from '@my-library/button';

<Button>Click me</Button>

配置npm的脚本

我们写好的组件库需要进行打包、发布等,我们的运行命令都写在根目录下的package.json文件里面

"scripts": {
    "start": "dumi dev", 
    "docs:build": "dumi build", 
    "build": "lerna run build", 
    "prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,json}'", 
    "test": "umi-test", 
    "publish": "lerna publish" 
  },

完整的package.json的配置如下所示:

{
  "name": "root",
  "private": true,
  "workspaces": [
    "packages/*"
  ],
  "scripts": {
    "start": "dumi dev",
    "docs:build": "dumi build",
    "build": "lerna run build",
    "prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,json}'",
    "test": "umi-test",
    "publish": "lerna publish"
  },
  "dependencies": {
    "antd": "^5.1.7",
    "react": "^18.3.1",
    "react-dom": "^18.3.1"
  },
  "devDependencies": {
    "@types/hast": "^3.0.4",
    "@types/react": "^18.3.18",
    "@types/react-dom": "^18.3.5",
    "csstype": "^3.1.3",
    "lerna": "^8.1.9",
    "typescript": "^5.7.3"
  }
}

打包和发布

打包这个项目的指令是npm run build,至于项目的lerna publish的部分,我这里就不做叙述了,可以自己看文档尝试下,和rollup打包的项目发布到npm上是有些相似的

总结

项目组里的旧的组件库是用的rollup打包的,现在新的组件库是用的lerna,比起rollup,lerna有它自己的特点,但是就我目前的使用来说,并没有很深刻的体会到两种打包方式带来的体验之间的优劣,只能说技术在不断的发展,我们还是得紧跟着新的技术持续学习。