我是怎么调试 Element UI 源码的

网站建设3年前发布
48 0 0

​上篇文章​​写了怎么调试 antd 的源码,反响很不错:,2023030614023314f430c84842655473375174b8c874238e8d91812,但很多小伙伴是写 Vue 的,可能平时用的是 Element UI 的组件库,所以这篇文章就来讲下怎么调试 Element UI 的源码。,首先,我们用 Vue CLI 创建一个 vue2 的项目:,创建成功后,进入到项目目录,20230306135918874b09d79b21c3bfe13535d08fba3ac3ddb724814,安装 element ui 的库,并在入口引入:,20230306135918e1b7d8a1433cfe2449b393278b75c32dbf5ce3115,然后在 App.vue 里用一下 button 组件,2023030613591925083fe733b28c20c6e5042480dc7f7f648f8c324,之后 yarn run serve 把开发服务跑起来,就可以看到这样的页面:,2023030614023364963c6198b3e5dc7ef295b73ea7811eeef519582,Element UI 的组件正确的显示了。,接下来调试 button 组件的源码,那问题来了,我怎么知道在哪里打断点呢?,我们可以知道的是,这个 button 会处理点击事件,但是却不知道事件处理函数的代码在什么地方。,这种情况可以加一个事件断点:,20230306135919a94957b4391ad5782a22854b49578e5e656c35809,在 sources 面板的 Event Listener Breakponts 里勾选 Mouse 的 click 事件,也就是在所有 click 事件的处理函数处断住。,然后你再点下那个按钮试试看:,2023030614023579a6e59492248a6d0989792cdb853d3dbe46d5137,你会发现它在事件处理函数处断住了。,当你知道这个组件处理了什么事件,但却不知道事件处理函数在哪的时候就可以用事件断点。,当然,这个事件处理函数并不是组件里的,因为 Vue 内部会先做一些处理,然后再交给组件处理。,所以,我们要先走到组件的事件处理函数:,202303061359231264b1e34ceccda579910307ad6a3d73550d49280,单步执行、再进入函数内部,再单步执行、再进入函数内部,代码就会走到组件的事件处理函数:,20230306135922b3b89bc36d9a8f9d6d1008aec0c581f64a97c5993,methods、computed、props,这明显是源码里的了。但你再往上走两步,会发现又不是最初的源码:,2023030613592381fd17e58c24ffeb4cc3403393fbe8d8400903800,template 变成了 render 函数,而且还有其他组件的代码,这明显是被编译打包之后的代码。,从文件名也可以看出来:,202303061359238416c14723e4058d9ab358abdae2131c04ff00578,这是一个把所有组件代码编译后打包到一起的文件。,这样虽然也能调试,但肯定是不爽的,能不能直接调试组件最初的源码呢?就是带 template 的单文件组件那种?,是可以的,这就要用到 sourcemap 了。,sourcemap 是在编译过程中产生的:,20230306140235f8730c5243abd48eb8634168c1e53681684d0a228,里面记录了目标代码和源代码的映射关系,调试的时候可以通过它映射回源码:,20230306140235e5214df37c5aa34cdb98708ccb46009f43f7bc907,但是你去 node_modules 下看看,会发现没有这个文件的 sourcemap:,20230306135924971fc322725cb1c40210118397c383cf6083f7648,那怎么生成它的 sourcemap 呢?,这就要从源码重新编译了。,我们从 github 把它的源码下载下来:,--depth=1 是只下载单个 commit,--single-branch 是下载单个 branch,这样下载速度能快几十倍,是一个加速小技巧。,进入 element 目录,安装依赖,你会遇到一个前端经常头疼的问题,node-sass 安装报错了:,20230306135925f4a48320554bae41f9e763a055583ad23c5b00160,这个问题的解决方案就是把 node 版本切换到 node-sass 版本对应的那个。,package.json 中可以看到 node-sass 是 4.11.0,20230306140236636b6f37673d5158fa9640c36827528dbeee05423,打开 node-sass 的 github 首页:,你会看到这样一个版本对应关系表:,20230306135927866134b477ed62f100d9830ecdd674584ee599257,4.11 对应 node11,那就把 node 切换到 11 就可以了。,然后再次 yarn 安装依赖就能成功了。,之后开始编译,在 npm scripts 中可以找到 dist 命令,这就是构建源码用的:,202303061414420682e9d5071e6a689eb4945d979d39f61cc8ae285,但是我们只需要 element-ui.common.js 这个文件:,202303061359274312390907e3b7d455467511496a862ddc6e54723,其实只需要执行其中的一部分脚本,也就是这个:,202303061359280831b4c4484250040dc95690caaee607c638a1102,所以在项目下执行 npx webpack --config build/webpack.common.js 即可:,2023030613592812c1ddc3941b0f27762968442638313637623b385,然后在 lib 下就可以看到构建产物:,20230306140237a8801ad1355a2eaef784580c3dded0d59bcf78916,但我们的目标是生成带有 source-map 的代码,所以要改下配置:,修改 build/webpack.common.js,配置 devtool 为 cheap-module-source-map:,20230306140237014e43c966649ec3b8a1798e130a4b02ddaf04331,source-map 是生成 sourcemap 并关联,也就是这样:,20230306135930e10ffad91be68d3abd7325b3330a647606b2b1226,module 是把中间 loader 产生的 sourcemap 也给合并到最终的 sourcemap 里,这样才能直接映射到源码。,cheap 是加快编译速度用的,只保留行的映射信息。,改完配置后再次 yarn run dist,就可以看到带有 sourcemap 的产物了:,20230306141408c8feda4874bd2604a7b434131f84b8125144e6686,把这俩文件复制到测试项目的 node_modules/element-ui 下覆盖下之前的:,20230306135931166a4b698402cbfe51e747a3461d3a845a769f782,之后清掉 node_modules/.cache 下的缓存,重新跑 dev server:,20230306135932175d8f67420613da5c4026b007f569fa1550eb769,这时会报错提示你 node 版本太低了,你需要再把 node 版本换回来:,20230306135932f6ea7121452ce7b8ed0058d28f20e099cd0227573,跑起开发服务之后,再次用之前的方式调试 button 组件的源码:,20230306140238a25afb26833caaf3aa64175a2e24747bdc2ad6463,你会发现现在的组件代码是带 template 语法的单文件组件的代码了!,20230306140238465636957e6d124f821315cf91775d1fe79cdc179,这就是 sourcemap 的作用。,之后你会可以在这个组件里打断点然后调试。,有的同学可能会问,通过事件断点进入组件内部,这样有点麻烦,有没有更简单的方式?而且 button 组件有点击事件,但有的组件没有呀,这些组件该怎么调试呢?,确实,有了 sourcemap 之后就有更简单的调试方式了。,你可以在 sources 左边看到 ELEMENT 目录下有很多 vue 文件,这其实就是 Chrome DevTools 解析 sourcemap 之后列在这里的:,202303061359346206f7c733b9187d1e8868e187da32a6318ce3739,你可以直接在里面打断点调试。,比如我们加一个 tabs 组件:,2023030614024158b3663812918dd719b0881798304ea6f0286b208,把前面添加的那个事件断点去掉,在代码里手动打一个断点:,2023030613593516d19c066b3ad36df5d7369ef7e56d3a6bc054783,然后你就会发现,这样就可以调试 Element UI 组件源码了!,2023030613593764c70c321ca472e58bf657e400f6a4d559acb9650,当然,有的组件找不到的时候,还是可以通过事件断点的方式来进入组件内部。,我们是通过 Chrome DevTools 调试的,其实用 VSCode Debugger 来调试它也是一样的,在 Chrome DevTools 里打的断点,在 VSCode Debugger 里同样会断住。,今天我们调试了 Element UI 的源码。,定位到组件的代码,是通过事件断点的方式,因为我们知道它触发了什么事件,但却不知道事件处理函数在哪。,但是组件的代码是被编译打包过的,不是最初的源码。,为了调试最初的源码,我们下载了 Element UI 的代码,build 出了一份带有 sourcemap 的代码。,覆盖项目 node_modules 下的代码,重新跑 dev server,这时候就可以直接调试组件源码了。,有了 sourcemap 之后,Chrome DevTools 会直接把 vue 文件列在 sources 里,我们可以找到对应的 vue 文件来打断点,就不用通过事件断点来找了。,能够调试 Element UI 源码之后,想知道组件内部都有哪些逻辑的话,就可以直接在源码断点调试了,就很香。

© 版权声明

相关文章