1、调试原理
| 类型 | 原理 |
|---|---|
| 编译型 | cpu 里面有 4 个寄存器可以做硬中断,操作系统提供了系统调用来做软中断。通过机器码替换成 0xcc (INT 3)是把程序断住了,需要释放断点的时候再换原来的机器码 |
| 解释型 | 插入一段代码来断住,支持环境数据的查看和代码的执行 |
比如 js 中支持 debugger 语句,当解释器执行到这一条语句的时候就会断住
2、devtools
| 组成 | 作用 |
|---|---|
| frontend | 连接debugger server(websocket),绘制ui展示 |
| cdp | socket传递的信息格式 |
| backend | 起debugger server,环境信息和脚本执行能力通过socket传递出去 |
- frontend
npm install chrome-devtools-frontend@1.0.672485
可通过live server插件打开devtools_app.html,后面加上 ws=localhost:8080 的参数
- cdp
Chrome DevTools Protocol - backend
const ws = require('ws');
const wss = new ws.Server({ port: 8080 });
wss.on('connection', function connection(ws) {
ws.on('message', function message(data) {
console.log('received: %s', data);
});
});
自己实现 CDP 的交互还是挺麻烦的,chrome 给提供了一个工具包 chrome-remote-interface
3、vue devtools
Vue DevTools 和 React DevTools 就是自己定制的一套协议
4、sourcemap
sourcemap 是关联编译后的代码和源码的,通过一个个行列号的映射。
{
version : 3,
file: "out.js",
sourceRoot : "",
sources: ["foo.js", "bar.js"],
names: ["a", "b"],
mappings: "AAgBC,SAAQ,CAAEA;AAAEA",
sourcesContent: ['const a = 1; console.log(a)', 'const b = 2; console.log(b)']
}
file 是文件名,sourceRoot 是源码根目录,names 是转换前的变量名,sources 是源码文件,sourcesContent 是每个 sources 对应的源码的内容,mappings 就是一个个位置映射
- 一个 bundle.js 就对应了 n 个 sources 源文件
- mappings 部分是通过分号
;和逗号,分隔的:一个分号就代表一行,然后每一行可能有多个位置的映射,用,分隔 - 比如 AAAAA 一共五位,分别有不同的含义:
转换后代码的第几列(行数通过分号 ; 来确定)
转换前的哪个源码文件,保存在 sources 里的,这里通过下标索引
转换前的源码的第几行
转换前的源码的第几列
转换前的源码的哪个变量名,保存在 names 里的,这里通过下标索引
- 各种调试工具一般都支持 sourcemap 的解析,只要在文件末尾加上这样一行
//@ sourceMappingURL=/path/to/source.js.map
参考地址
《JavaScript Debugger 原理揭秘》、 《 玩转 Chrome DevTools》、
《 Webpack 的 sourcemap 配置原理》
欢迎关注我的前端自检清单,我和你一起成长