如何从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,如有疑问可以评论或私信。

相关推荐
恋猫de小郭4 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅10 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606111 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了11 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅11 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅12 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅12 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment12 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅12 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊12 小时前
jwt介绍
前端