对于要学习vue3
源码的前端小伙伴来说,通过调试vue3源码来学习是一种不错的方法,本期来介绍下调试方法。
一、下载vue3源码
先使用git clone
命令把vue3源码从远程仓库克隆本地。
git clone https://github.com/vuejs/core.git
如果出现克隆失败,可以直接download
源码的压缩包,下载完后解压即可。
二、安装依赖
vue3
采用的是Monorepo + pnpm
的方式来管理仓库的,所以我们需要通过pnpm install
来安装依赖,如果没有安装pnpm
,需要先运行npm install pnpm -g
安装下pnpm
,注意node版本需要在16以上。
pnpm install
三、开发环境打包
安装完依赖之后,执行npm run dev
命令进行开发环境打包。
打包后会生成两个文件:
core/packages/vue/vue.global.js
:以global方式打包后的vue文件core/packages/vue/vue.global.js.map
:生成的源码映射文件,这样我们调试的时候就能映射到对应真实源码中的各个文件了。
这里其实还有
npm run build
命令,为啥要用npm run dev
呢,主要有两个原因:
- 相比而言,
npm run dev
生成的文件更少,速度更快, npm run dev
支持热更新,也就是我们可以手动修改vue源码后,会重新打包,这样可以很方便的在源码中增加debugger
四、编写vue代码,开始调试
我们可以在core/packages/vue/examples
路径下增加一个test.html
文件,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>计数:{{ count }}</h1>
<button @click="handleClick(1)">+1</button>
<button @click="handleClick(-1)">-1</button>
<button @click="reset()">reset</button>
</div>
<script src="../dist/vue.global.js"></script>
<script>
const { ref, createApp } = Vue
const App = {
setup() {
const count = ref(0);
const handleClick = () => {
debugger;
count.value++
}
const reset = () => {
count.value = 0
}
return {
count,
handleClick,
reset,
}
}
}
createApp(App).mount('#app');
</script>
</body>
</html>
渲染页面如下:
我们点击
“+1”
按钮后,浏览器就会在debugger
那里停住,这样就可以开始调试vue源码了。
前面说过,执行npm run dev
是有热更新功能的,我们直接找到ref
对应的源码文件/core/packages/reactivity/src/ref.ts
,找到对应的ref
方法,增加debugger
。
增加代码并保存文件之后,会发现热更新生效了,重新打包了一次,生成了新的vue.global.js
和vue.global.js.map
文件,再回来我们之前的页面进行刷新,会看到浏览器就会停在我们刚刚增加的断点位置。
五、如何在vscode中调试vue3源码?
假如你不太喜欢在浏览器调试,你还可以在vscode
中调试。
这里需要先启动一个静态服务,这里我直接用http-server
来实现,如果没安装的话先执行npm i http-server -g
安装一下。
它的用法很简单,直接在对应的目录执行http-server
命令就好了,这里我直接在根目录
启动静态服务。
然后在vscode
中调试配置文件launch.json
中增加如下调试程序:
{
"version": "0.2.0",
"configurations": [
+ {
+ "type": "chrome",
+ "request": "launch",
+ "name": "debugger vue source",
+ "url": "http://localhost:8080/packages/vue/examples/test.html",
+ "webRoot": "${workspaceFolder}"
+ },
]
}
这里注意把url
配置成你需要调试的文件路径,端口也在与你之前启动的静态服务的端口对应上,我这里配置的url是http://localhost:8080/packages/vue/examples/test.html"
。
然后我们就可以点击开始按钮进行调试了:
vscode
会启动浏览器,并访问我们配置的网页url
路径,而且断点也生效了。
这样的话,我们打断点也会很方便,直接利用vscode
文件行号左边的小红点
就好了,这里就不多说了。
六、实战:如何在实际vue项目中调试vue3源码?
如果我们想在实际vue项目中调试vue源码,要怎么做呢?
6.1、创建vue项目
我们先使用vue-cli
创建一个vue3
项目:
- 执行
vue create vue3-demo
命令创建项目,选择vue3版本 - 通过
npm run serve
把项目跑起来。
需要修改下devtool配置:
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
+ configureWebpack: config => {
+ config.devtool = 'source-map';
+ }
})
6.2、增加断点
在App.vue
中增加如下代码:
import { onMounted } from 'vue';
onMounted(() => {
debugger;
})
6.3、创建调试文件
然后创建vscode
的调试文件,如下所示。
{
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "debugger vue3 source",
"url": "http://localhost:8080",
"webRoot": "${workspaceFolder}",
}
]
}
6.4、开始调试
通过断点进入vue源码后,发现调试的文件是E:/code/vue3-demo/node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js
,这显然是打包后的文件,不符合我们的预期,我们需要调试的是代码源文件。
6.5、修改vue源码中rollup.config.js
默认通过pnpm run build
打包是不生成sourcemap
,我们需要修改下rollup.config.js
中的配置文件,使其产出sourcemap
。
// rollup.config.js
- output.sourcemap = !!process.env.SOURCE_MAP
+ output.sourcemap = true
然后执行pnpm run build
命令。
可以看到带有.map
后缀的sourcemap
文件已经生成了。
随后将生成的E:\code\vue3-demo\node_modules\@vue\runtime-core\dist
目录,替换掉我们之前项目里的文件目录
,我这里是E:/code/vue3-demo/node_modules/@vue/runtime-core/dist
。
替换完毕后,重新跑下npm run serve
,然后重新跑下调试。
虽然进到了通过sourcemap
进入到了源码文件,但这个路径明显不是本地的路径,导致这个文件仅仅是readonly
可读的,这样对调试也不太友好。
这里显示的路径的E:/code/src/apiLifecycle.ts
,而我们真实的文件路径是E:\code\core\packages\runtime-core\src\apiLifecycle.ts
,没对应上,自然就只读了。
我们需要通过rollup
的output.sourcemapPathTransform
修改下生成的sourcemap文件路径:
// rollup.config.js
+ output.sourcemapPathTransform = (relativeSourcePath, sourcemapPath) => {
+ const newSourcePath = path.join(
+ path.dirname(sourcemapPath),
+ relativeSourcePath,
+ )
+ return newSourcePath
+ }
这里就拿我们上面提到的apiLifecycle.ts
文件来说,relativeSourcePath
、sourcemapPath
、newSourcePath
分别为:
- relativeSourcePath:
..\..\runtime-core\src\apiLifecycle.ts
- sourcemapPath:
E:\code\core\packages\vue-compat\dist\vue.runtime.esm-browser.prod.js.map
- newSourcePath:
E:\code\core\packages\runtime-core\src\apiLifecycle.ts
然后重新执行npm run build
,再把之前说的dist
文件再替换一次。
再次重新运行npm run serve
之前,需要清空下babel-loader
缓存:rm -rf node_modules/.cache/babel-loader/
。
这样就ok了,对应上了本地的源码文件,这个文件也能修改了。
6.6、调试 create-vite 创建的 vue 项目
如果通过vite
跑的vue项目,需要注意两点:
- 需要修改vite.config.ts
export default defineConfig({
plugins: [vue()],
+ optimizeDeps: {
+ exclude: ['vue']
+ }
})
加这个配置项,是为了不让vue
在vite
预编译时被esbuild
处理,否则路径会出问题。
- 如果已经被处理过,需要
rm -rf node_modules/.vite
清除缓存
七、小结
上述介绍了如何在各种场景中调试vue3源码
,主要包括以html文件demo
的方式,以及在实际项目中如何调试vue3源码
,希望对大家学习vue3源码和调试bug有帮助!