如何从0到1搭建基于antd的monorepo库——使用rollup进行打包、lerna进行版本管理和发布(六)
2025年4月17日 09:58
文章系列
上一章:如何从0到1搭建基于antd的monorepo库——使用dumi进行文档展示(五)
作者有话说
目前已经实现了一部分功能,源代码在 github,欢迎大家 Star 和 PR,一些待实现的功能都在 issue 中,感兴趣的同学可以一起加入进来。
看完这个系列可以收获什么:
- 如何使用 pnpm workspace + lerna 搭建 monorepo 仓库
- antd 的单个组件怎么进行文件结构的设计
- 基于 antd form 实现一个 Json 渲染表单
- antd 的打包方式以及如何使用 rollup 实现
- 如何发布 monorepo 包到 npm
前瞻
组件库技术选型:
- pnpm 10
- node 20
- lerna 8
- react 18
- antd 5
- dumi 2
正片开始
安装依赖
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
文件。
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
中新增脚本。
{
"scripts": {
"build": "rollup -c"
}
}
在父包 package.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
中新增脚本。
{
"scripts": {
"lv": "lerna version"
}
}
运行 pnpm lv
会进入一个对话命令行,选择你想要的版本。
lerna 统一发布
在子包 package.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
中新增内容。
{
"private": true,
"scripts": {
"lp": "lerna publish from-git"
}
}
在父包根目录下运行 pnpm lp
即可发布 npm。
注意事项
- 在发布前需要先登录 npm
- 发布 monorepo 包需要在 npm 组织中发布,且组织名字为 @ 到 / 之间的内容
总结
至此,一个基于 antd 二次封装且使用 pnpm workspace + lerna 的 monorepo 组件库已经完成,想要查看更多内容可以在我的项目查看,如果感兴趣想要一起开发可以查看 issue,里面会有一些未来准备实现的功能。
如果想提前知道更多内容可以直接查看github,欢迎大家 Star 和 PR,如有疑问可以评论或私信。