如何从0到1搭建基于antd的monorepo库——使用rollup进行打包、lerna进行版本管理和发布(六)

文章系列

上一章:如何从0到1搭建基于antd的monorepo库------使用dumi进行文档展示(五)

作者有话说

目前已经实现了一部分功能,源代码在 github,欢迎大家 Star 和 PR,一些待实现的功能都在 issue 中,感兴趣的同学可以一起加入进来。

看完这个系列可以收获什么:

  1. 如何使用 pnpm workspace + lerna 搭建 monorepo 仓库
  2. antd 的单个组件怎么进行文件结构的设计
  3. 基于 antd form 实现一个 Json 渲染表单
  4. antd 的打包方式以及如何使用 rollup 实现
  5. 如何发布 monorepo 包到 npm

前瞻

组件库技术选型:

  1. pnpm 10
  2. node 20
  3. lerna 8
  4. react 18
  5. antd 5
  6. dumi 2

正片开始

安装依赖

bash 复制代码
pnpm add -D rollup @rollup/plugin-typescript rollup-plugin-dts @rollup/plugin-babel @rollup/plugin-commonjs @rollup/plugin-node-resolve rollup-plugin-peer-deps-external rollup-plugin-postcss rollup-plugin-terser

配置 rollup

在子包根目录下新增 rollup.config.mjs 文件。

js 复制代码
import babel from '@rollup/plugin-babel';
import commonjs from '@rollup/plugin-commonjs';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import typescript from '@rollup/plugin-typescript';
import { defineConfig } from 'rollup';
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
import postcss from 'rollup-plugin-postcss';
import { terser } from 'rollup-plugin-terser';

const DIR_MAP = {
  ESM: 'es',
  CJS: 'lib',
  UMD: 'dist',
};

// 处理 Ant Design 样式按需加载
const antdStyles = () => ({
  name: 'antd-styles',
  transform(code, id) {
    if (/node_modules\/antd/.test(id) && id.endsWith('.js')) {
      return code.replace(/import\s+['"].*\.less['"]/, '');
    }
    return null;
  },
});

const baseConfig = (tsConfig) => ({
  external: ['react', 'react-dom', 'antd', 'tslib'],
  input: 'src/index.ts',
  plugins: [
    peerDepsExternal(),
    nodeResolve({
      modulesOnly: true,
      extensions: ['.ts', '.tsx', '.js', '.jsx'],
      preferBuiltins: true,
    }),
    commonjs(),
    typescript(tsConfig),
    babel({
      babelHelpers: 'bundled',
      extensions: ['.ts', '.tsx'],
      presets: [
        '@babel/preset-react',
        ['@babel/preset-env', { modules: false }],
      ],
    }),
    postcss({
      extract: true, // 分离 CSS 文件
      modules: false,
      use: ['less'],
      minimize: true,
    }),
    antdStyles(),
  ],
});

const esmConfig = {
  ...baseConfig({
    declaration: true,
    declarationDir: DIR_MAP.ESM,
  }),
  output: {
    dir: DIR_MAP.ESM,
    format: 'esm',
    preserveModules: true,
    preserveModulesRoot: 'src',
  },
};

const cjsConfig = {
  ...baseConfig({
    declaration: true,
    declarationDir: DIR_MAP.CJS,
  }),
  output: {
    dir: DIR_MAP.CJS,
    format: 'cjs',
    exports: 'named',
    preserveModules: true,
    preserveModulesRoot: 'src',
  },
};

const umdConfig = {
  ...baseConfig(),
  output: [
    {
      file: DIR_MAP.UMD + '/index.js',
      format: 'umd',
      name: 'KcComponents',
      globals: {
        react: 'React',
        'react-dom': 'ReactDOM',
        antd: 'antd',
      },
      sourcemap: true,
    },
    {
      file: DIR_MAP.UMD + '/index.min.js',
      format: 'umd',
      name: 'KcComponents',
      plugins: [terser()],
      sourcemap: true,
    },
  ],
};

export default defineConfig([esmConfig, cjsConfig, umdConfig]);

新增 build 脚本

在子包 package.json 中新增脚本。

json 复制代码
{
  "scripts": {
    "build": "rollup -c"
  }
}

在父包 package.json 中新增脚本。

json 复制代码
{
  "scripts": {
    "build": "pnpm clean:dist && lerna run build",
    "clean": "lerna clean --yes",
    "clean:dist": "lerna exec -- rm -rf dist es lib"
  }
}

打包构建

在父包或者子包运行 pnpm build 即可进行打包,产物有三份,分别用于 ESM、CMJ、UMD:

lerna 版本管理

在父包 package.json 中新增脚本。

json 复制代码
{
  "scripts": {
    "lv": "lerna version"
  }
}

运行 pnpm lv 会进入一个对话命令行,选择你想要的版本。

lerna 统一发布

在子包 package.json 中新增内容。

json 复制代码
{
  "sideEffects": false,
  "main": "lib/index.js",
  "unpkg": "dist/index.min.js",
  "module": "es/index.js",
  "typings": "es/index.d.ts",
  "files": [
    "es",
    "lib",
    "dist"
  ],
  "publishConfig": {
    "access": "public",
    "registry": "https://registry.npmjs.org/"
  }
}

在父包 package.json 中新增内容。

json 复制代码
{
  "private": true,
  "scripts": {
    "lp": "lerna publish from-git"
  }
}

在父包根目录下运行 pnpm lp 即可发布 npm。

注意事项

  1. 在发布前需要先登录 npm
  2. 发布 monorepo 包需要在 npm 组织中发布,且组织名字为 @ 到 / 之间的内容

总结

至此,一个基于 antd 二次封装且使用 pnpm workspace + lerna 的 monorepo 组件库已经完成,想要查看更多内容可以在我的项目查看,如果感兴趣想要一起开发可以查看 issue,里面会有一些未来准备实现的功能。

如果想提前知道更多内容可以直接查看github,欢迎大家 Star 和 PR,如有疑问可以评论或私信。

相关推荐
不听话坏3 小时前
Ignition篇(下 一) 动态执行前的事情
开发语言·前端·javascript
likeyi073 小时前
require 和 import的区别
开发语言·前端
pany3 小时前
做 AI 友好的开源 Vue3 模板 🌈
前端·vue.js·ai编程
小二·4 小时前
React 19 + Next.js 15 现代前端开发实战:App Router / Server Components / 流式渲染
前端·javascript·react.js
谙忆10245 小时前
前端图片直传对象存储:OSS/S3 预签名 URL、STS 临时凭证与回调校验
前端
CHNE_TAO_EMSM6 小时前
Android studio 打开文件时自动下载源码
前端·javascript·android studio
一孤程7 小时前
Airtest自动化测试第五篇:小程序与Web测试——跨平台自动化全覆盖
前端·自动化测试·小程序·自动化·测试·airtest
IT_陈寒7 小时前
SpringBoot自动配置不是你以为的那样的智能
前端·人工智能·后端
yume_sibai8 小时前
大屏数据可视化 - 边框红绿呼吸灯实现详解
前端·信息可视化·typescript
Hyyy8 小时前
很多Desktop都在上的Computer Use是什么
前端·llm