type
status
date
slug
summary
tags
category
icon
password
前期工作
也许你废了好大劲打开的源码是这样的?

这是ant-design的Button组件,你会发现和github源码有很多不一样的地方:
- 它不是tsx文件,没有ts语法,就是个普通js。
- 有编译器生成的/*#__PURE__*/注释。
- React.createElement等函数。
- 一些babel转译后的ES5的语法。
- ···
这些我们会下面意义拆解。现在我们先把调试环境建立起来。
新建项目
这边我们新建一个vite的react+ts的项目
注意:我们这边使用的是普通typescript,不要选typescript+swc。我们后面会基于babel处理。
修改下App.tsx,把它整的赶紧些。
之后把项目跑起来🚀
调试环境

创建一个launch文件
- 类型:chrome。
- url: 你项目对应的服务地址。
好了现在在你的App文件中断点在App函数上,运行调试吧。

这个renderWithHooks函数是react的所有hooks函数的入口,点击看下断点目前的位置

现在指向了App,我们加一个断点条件,也删掉App中的断点。

重新运行,我们发现现在我们找到了Button这个按钮。我们进入函数内部看下。
不出意外的意外发生了,进来之后我们看到的是文章开头展示的那张被编译后的js代码。
好,正文开始!
Ant Design
下载源码
- -depth=1:这个参数用于指定克隆时只获取最近的1次commit记录,这样可以减少下载的数据量。
- -single-branch:这个参数表示只克隆远程仓库的单个分支,默认是master分支。
都是为了快速clone。
观察打包命令
ant-design/package.json


- build命令做了2件事,分别运行了compile和dist
- compile和dist命令又分别通过antd-tools执行的
- dist产出的是UMD的包。
- compile产出的是ESM和CJS的包。
探索antd-tools
ant-design/node_modules/@ant-design/tools
找到tools下面的package.json文件看到bin注册了antd-tools

bin文件指向了cli文件夹(require('../lib/cli')),内容如下:

也就是我们的compile和dist命令。让我们看一下gulp怎么串联流程的。
细品gulpfile
ant-design/node_modules/@ant-design/tools/lib/gulpfile.js
这边主要参与打包的是webpack和tsc+babel。dist对应webpack,compile对应tsc+babel。
先看compile
找到compile的task,分别执行了'compile-with-es', 'compile-with-lib',而他们主要处理逻辑都在compile函数里,区分了模块。

这边用了tsc和babel解析了,所以我们需要对它们分别做source-map处理。

添加source-map配置
- 添加
gulp-sourcemaps
包
这边下包可以下在ant-design这个目录,利用node_modules找包的向上规则,毕竟我们只做调试用,怎么方便怎么来~
- 添加配置


2.1. 添加初始化配置
2.2. 添加babel的sourceMap
2.3. 在写入文件前(dest)加入map文件
- 最后别忘了ts的sourceMap,
ant-design/tsconfig.json
中加入
打包试试
可以看到es和lib目录下都有map文件了

再看dist
这边简单说下dist源码映射的方案,毕竟我们项目90%都是使用的ESM的方式引用的。
同样的找到dist函数的位置,我们发现webpack配置文件是在项目根目录,根目录又指向了
@ant-design/tools/lib/getWebpackConfig
这个文件。

我们目标很明确就是改ts和babel嘛,直接去找loader!

果然是先经过了tsc处理后,之后babel进行转译。

添加sourceMap生成配置。我们刚刚改过tsconfig中的sourceMap,如果没改需要改下。
这边要注意下,我们通过
import { Button } from 'antd'
这种方式引入的是esm的写法,所以这边App.tsx要改下导入语句。来看效果
重新打包生成es/dist文件夹。我们把es/dist项目中替换一下,顺便清理下vite中的缓存。(在node_modules下的.vite文件)

我们重新运行下项目发现,成了!

github源码:

现在你会发现你进入的断点代码和github上的一毛一样,什么es6语法、ts类型、注释全有了!
Pro Components
下载源码
观察打包命令
pro-components/package.json

pro-components是用lerna+pnpm维护的,我们来测试下packages/table组件。
安装好依赖之后,我们给table打个包。
- 注意我们这边包名要去子包的package.json中看下name,并不是table。

我们发现依然是没有sourcemap的,不过所有的pro-components的包都是通过father构建的,这就很方便了。看下father配置~

用的是根路径的father配置,我们添加sourcemap=true。

这边我们只改ESM模块的,之后当然也别忘了开启@ant-design/pro-table中tsconfig的sourcemap。
改下@ant-design/pro-table的打包命令,删除刚刚的es文件夹。
重新运行,我们发现es中多出了map文件。

看效果
同样我们把构建产物移过去,清除下缓存,重新运行!

github源码:

这次不出意外的意外走丢了,完全一样!
总结
梳理下知识点:
- 建立调试环境
- 观察构建命令,得到构建方案
- 针对不同的构建方案,用不同的sourceMap映射,但总体不变的是babel+ts开启sourceMap
- 读懂gulp和lerna+pnpm的组织构建
工作中肯定是首先看文档和TS文件定义,但遇到问题或者好奇想深究的时候这肯定不够的。我们可以通过源码断点的形式去分析组件库的设计。后面我会和大家分享基于此方法的几个案例,希望大家持续关注!
- Author:NotionNext
- URL:https://tangly1024.com/article/ad9c258b-c3d0-4c03-b5ed-a939c267edbd
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!