devtools

引言

自从上周去开了个前端的会议之后,对于前端的一些新技术有了一些新的认识,其中就有关于Chrome本地代码调试的一些新的认识,所以这里就简单的记录一下。这边先贴一个链接:youtube-ChromeDevs

这边要先感谢下chrome的devtools团队,他们的工作真的是太棒了,但是在 jecfish 的前端会议技术分享之前我却并不知道有这么多友好的web调试工具和性能测试手段,所以这里就简单的记录一下,大家要是有兴趣的话可以去看看上面的链接,里面有很多有用的东西,也欢迎给他们团队贴贴关注。

下面将先给出本章的大纲,然后再逐步展开。

ModernWeb

本地代码调试

这边的内容将是有关于本地代码调试,主要是有关于source-map的一些内容,这边将会有一些简单的介绍,然后再给出一些简单的例子。

对源代码映射source-map的需求

这边先给出一个链接:source-map

这个链接是jecfish写的有关于source-map的一些内容要是大家有兴趣的话,可以去里面看看,要是文章太长大家看不下去的话,可以直接看下面的内容。

今天,我们要讨论的是源代码映射,这是一种现代 Web 开发中的重要工具,可大幅简化调试工作。在本文中,我们将探讨源代码映射的基础知识、源代码映射的生成方式以及源代码映射如何改善调试体验。

好嘟,要进入source-map的学习认知,我们得先要对Modern Web有一个最基本的认识。那我们来看看当我说到Modern Web的时候我们该聊些什么?

ModernWeb

我们可以看到控制台打印了一些BaseOn Css样式的一些内容,但我们今天虽然并不准备着重讲这个console的Css样式,但你依然可以在console定义一些样式让你的console打印的更漂亮!

ModernWeb

ModernWeb

时隔15年的时间,我们可以看到chrome开发者模式的调试工具从原来的寥寥几种,到现在的丰富多彩,这其中的变化是非常大的,所以我们今天就来聊聊这32种调试工具在chrome之中具体的应用。

ModernWeb

我们知道浏览器只认识HTML </> CSS {;} JavaScript (,) Wasm(当然是现在浏览器引擎默认都内置了对Wasm模块的支持) 这几种语言,但是我们的前端框架却异常的丰富 ,涉及到的语言:ts、less、sass,框架:Vue、React,Meta 框架:nust.js、next.js,这些框架都是在我们的前端代码中使用的,但是浏览器并不认识这些语言,所以我们需要将这些语言转换成浏览器认识的语言。

我们正在构建更复杂的 Web 应用,您的开发工作流可能会涉及到使用各种工具。例如:

  • 模板语言和 HTML 预处理器:Pug、Nunjucks、Markdown。
  • CSS 预处理器:SCSS、LESS、PostCSS。
  • JavaScript 框架:Angular、React、Vue、Svelte。
  • JavaScript 元框架:Next.js、Nuxt、Astro。
  • 高级编程语言:TypeScript、Dart、CoffeeScript。
    等等。这个名单还在不断加长!

ModernWeb

这些工具需要一个构建流程,以将代码转译为浏览器可以理解的标准 HTML、JavaScript 和 CSS。此外,为了优化性能,通常的做法是压缩(例如,使用 Terser 缩减和破坏 JavaScript)和合并这些文件,以缩减其大小并提高 Web 效率。

而将这众多的模板语言和预处理器、元框架转化成浏览器可以看得懂的 HTML、JavaScript 和 CSS,这个过程就是编译,而编译的过程中就会产生一些中间代码,这些中间代码就是我们的源代码映射,这个 源代码映射 就是我们今天要讲的内容。

例如,使用构建工具,我们可以将以下 TypeScript 文件转译并压缩为一行 JavaScript。这个demo在github上面也有:parcel-demo

/* A TypeScript demo: example.ts */

document.querySelector('button')?.addEventListener('click', () => {
  const num: number = Math.floor(Math.random() * 101);
  const greet: string = 'Hello';
  (document.querySelector('p') as HTMLParagraphElement).innerText = `${greet}, you are no. ${num}!`;
  console.log(num);
});

压缩版本如下所示:

/* A compressed JavaScript version of the TypeScript demo: example.min.js  */

document.querySelector("button")?.addEventListener("click",(()=>{const e=Math.floor(101*Math.random());document.querySelector("p").innerText=`Hello, you are no. ${e}!`,console.log(e)}));

不过,这项优化会增加调试难度。如果压缩代码将所有内容放在一行中,并且变量名称较短,则很难查明问题的根源。这正是源映射的用武之地,它们会将编译后的代码映射回原始代码。

ModernWeb

我们现在来具体看一个例子,这个例子是一个用ts代码写的简单的click事件触发的xhr,其中报了404错误。

ModernWeb

哎?发生什么事了,注意看红色箭头处,看来我们浏览器看得懂ts代码?

ModernWeb

ModernWeb

其实不然,看着这贴着的这张图,其实这个ts是从main.js里面解析过来的

了解源代码映射source-map

ModernWeb

这些源映射文件包含关于已编译代码如何映射到原始代码的基本信息,让开发者能够轻松地进行调试。下面是一个源映射的示例。

{
  "mappings": "AAAAA,SAASC,cAAc,WAAWC, ...",
  "sources": ["src/script.ts"],
  "sourcesContent": ["document.querySelector('button')..."],
  "names": ["document","querySelector", ...],
  "version": 3,
  "file": "example.min.js.map"
}

要了解其中每个字段,您可以阅读源映射规范或这篇关于源映射剖析的经典文章。

源映射最重要的方面是 mappings 字段。它使用 VLQ base 64 编码字符串将已编译文件中的行和位置映射到对应的原始文件。可使用 source-map-visualization来源映射可视化等来源映射可视化工具直观呈现此映射。

ModernWeb

左侧的生成的列会显示压缩内容,而原始列会显示原始来源。

可视化工具会以颜色代码对 original 列中的每一行以及 generated 列中的相应代码进行颜色编码。

mapping 部分显示了已解码的代码映射。例如,条目 65-> 2:2 表示:

  • 生成的代码:const 一词在压缩内容中的位置 65 处开始。
  • 原始代码:const 一词从原始内容中的第 2 行和第 2 列开始。

这样一来,开发者便可以快速识别缩减后的代码与原始代码之间的关系,从而使调试过程更加顺畅。

浏览器开发者工具应用这些源代码映射,帮助您直接在浏览器中更快地查明调试问题。

ModernWeb

ModernWeb

ModernWeb

DevTools 怎么知道该隐藏啥?Source maps

ModernWeb

ModernWeb

ModernWeb

实用的chrome调试技巧

请求

ModernWeb

你可以在Network面板中查看请求的详细信息,包括请求头、响应头、请求体、响应体、Cookies、Timing等等。

同时,devTools devtools/overrides 也提供了通过本地覆盖,可以覆盖 HTTP 响应标头和Web 内容(包括XHR 和获取请求)来模拟远程资源,即使您无权访问它们。这使您可以对更改进行原型设计,而无需等待后端支持它们。本地覆盖还允许您在页面加载期间保留在 DevTools 中所做的更改。

这个东西在什么情况特别有用呢?

比如说,前端向后端发起的请求,后端返回的结果,可能还未进行跨域的处理(当然跨域的处理在后端做),那前端拿到的这个结果其实已经访问成功了,拿到了正确的数据,但是由于浏览器的安全策略,将此文件报告为不可信赖,这个时候我们就可以通过本地覆盖,来模拟后端返回的结果,这样就可以在前端进行调试了。

或者说有些数据在后端还未修改,前端拿到的数据是旧的,那我要干巴巴跟后端工程师小眼瞪大眼等着他们把数据改好了我们再进行工作嘛?这样实在是有点蠢hhhhh,我们可以通过重写content进行修改,这样就可以在前端进行调试了。

ModernWeb

那这个devtools/overrides确实是有点牛逼的,那它是怎么运行的:

  • 当您在 DevTools 中进行更改时,DevTools 会将修改后的文件的副本保存到您指定的文件夹中。
  • 当您重新加载页面时,DevTools 会提供本地修改后的文件,而不是网络资源。

覆盖网页内容

设置文件夹
  • 设置本地覆盖。
  • 对文件进行更改并将其保存在 DevTools 中。

例如,您可以在“源”中编辑文件,或在“元素” > “样式”中编辑 CSS,除非 CSS 位于HTML 文件中。

DevTools 保存修改后的文件,在Sources > Overrides 中列出它们,并在相关面板和窗格中显示已保存。被覆盖文件旁边的图标:Elements > Styles、NetworkSources > Overrides

覆盖 XHR 或获取请求以模拟远程资源

通过本地覆盖,您不需要访问后端,也不必等待它支持您的更改。即时模拟和实验:

  • 设置本地覆盖。
  • 在Network中,过滤XHR/fetch requests,找到您需要的请求,右键单击它,然后选择Override content。
  • 对获取的数据进行更改并保存文件。
  • 刷新。 刷新页面并观察应用的更改。

要了解此工作流程,请观看以下视频:

覆盖 HTTP 响应标头

在“网络”面板中,您可以覆盖 HTTP 响应标头,而无需访问 Web 服务器。

通过响应标头覆盖,您可以在本地对各种标头进行原型修复,包括但不限于:

  • 跨源资源共享 (CORS) 标头
  • 权限-策略标头
  • 跨源隔离标头
  • 要覆盖响应标头:

设置本地覆盖并检查。

转到Network,找到请求,右键单击它,然后选择Override headers。DevTools 将带您进入标头>响应标头编辑器

ModernWeb

录制器,有利于调试和测试

基于Chrome DevTools Recorder 的自定义和自动化用户流

ModernWeb

编写自动化测试并不是开发人员生活中最有趣的事情。作为开发人员,事实上确实需要功能、修复错误并改善世界!然而,当我们的工作流程中没有自动化测试时,从长远来看,事情可能会变得相当“错误”。所以,我们也认为编写自动化测试很重要。

使用Chrome DevTools 中的Recorder 面板,您可以录制和重放用户流程,通过不同的第三方扩展和库将其导出为各种格式(例如测试脚本),使用 Puppeteer Replay 库自定义用户流程,并将其与您现有的工作流程。

在这篇博文中,我们将讨论:

  • 如何以编程方式导出和重放用户流。
  • 如何借助 Puppeteer Replay 自定义用户流程。
  • 如何与您的CI/CD工作流程集成。

以编程方式导出用户流并重播

默认情况下,Recorder 使您能够将这些录音导出为PuppeteerPuppeteer Replay脚本,或者导出为纯 JSON 文件。

ModernWeb

使用 Puppeteer Replay 进行重播

将用户流导出为 JSON 文件后,您可以选择将其导入回记录器面板并重播,或使用外部库来重播。Puppeteer Replay库是可用的库之一。

重播扩展允许扩展向 DevTools 添加面板来配置重播并显示重播结果。

Puppeteer Replay 是一个库,可帮助您重播用户流程。它是一个基于 Puppeteer 的库,它允许您在浏览器中重播用户流程,而无需编写任何代码。您可以使用 Puppeteer Replay 重播您的用户流程,以确保您的应用程序在不同的环境中运行良好。

与 CI/CD 管道集成

有多种方法可以做到这一点,并且有很多工具。以下是使用GitHub Actions自动执行此过程的示例:

# .github/node.js.yml

name: Replay recordings

on:
  push:
    branches: [ "main" ]
  schedule:
    - cron: '30 12 * * *' # daily 12:30pm

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Use Node.js
      uses: actions/setup-node@v3
      with:
        node-version: 18.x
        cache: 'npm'
    - run: npm install puppeteer
    - run: npm run replay-all
    - run: npm run start

在此示例中,我们将在以下情况下重播用户流:

新的变更推送到main分支
每天中午 12:30
除了 GitHub Actions 之外,您还可以与您最喜欢的云提供商集成。