Mastering Chrome Developer Tools, v4

凭借专业的Chrome DevTools技能,更快地检查、调试和审计Web应用!使用DOM检查器在浏览器中实时原型化UI。超越console.log(),通过单步调试并跟踪内存性能,以识别代码中的瓶颈。利用网络面板并运行Lighthouse报告,确保你的应用性能卓越,并遵循最新的性能、SEO和可访问性最佳实践。

0-introduction

  • 课程介绍
    • 课程名称:Mastering Chrome DevTools (精通 Chrome 开发者工具),第四版。
    • 讲师:Jon Kuperman。
  • 讲师背景
    • 在 TC39 (JavaScript 语言标准机构) 任职,参与制定 JS 新特性。
    • 是 Source Maps 工作组的共同召集人。
    • 在 Bloomberg 工作,负责构建开发者工具,与 Chrome DevTools 团队有紧密集成。
  • 课程资源
    • 代码: GitHub - mastering-devtools-static
    • 幻灯片: 提供了一个 TinyURL 链接
    • 已部署网站: masteringdevtools.com
    • 建议: 可以直接使用已部署的网站 masteringdevtools.com 따라学习,除非你更喜欢在本地环境中操作。
  • 讲师工作背景 (Bloomberg)
    • 构建一个用于金融市场的定制化 C++/JS 浏览器。
    • 专注于实时数据、图表和快速渲染。
    • 深入研究 Chromium 和 Chrome DevTools,并为开源社区做贡献 (如 TC39, C++ 标准委员会等)。
  • 学员对 DevTools 的熟悉程度
    • 新手: 几乎没用过。
    • 中级用户: 常用 Elements (元素)、Console (控制台),偶尔用 Sources (源代码)。这是大多数人的水平。
    • 高级用户: 经常进行性能审计。
  • 学员常用功能反馈
    • Console: 非常常用。
    • Elements: 用于快速原型设计,以绕过漫长的项目构建时间。
    • Sources: 设置断点进行调试。
    • Network: 检查网络请求,关注安全和隐私,或进行图片格式和大小的优化。
    • Lighthouse: 用于发现性能问题,如图片未被正确压缩或尺寸不当。
  • 课程大纲
    1. Essential Chrome DevTools: 熟悉每个面板的基本功能。
    2. Network Optimization: 分析和优化网络请求。
    3. Lighthouse Audits: 深入了解 Core Web Vitals、图片和打包文件优化。
    4. Step-through Debugging: 超越 console.log,学习单步调试技巧。
    5. Performance Profiling: 分析 CPU 密集型任务,如 CSS 变换和动画。
    6. Memory Management: 使用堆快照 (heap snapshots) 检测和定位内存泄漏。
    7. Experiments: 探索 DevTools 中隐藏的实验性功能。

1-why-master-the-chrome-devtools

  • 掌握 Chrome DevTools 的三大理由
    1. 成为 Web 性能专家
      • 提升应用性能总是有价值的,这能让你在团队和公司中脱颖而出。
      • 性能与商业收益直接相关:
        • 雷诺案例: Google 研究发现,网站的 LCP (最大内容绘制) 时间越短,用户转化率越高。LCP 从慢到快,转化率可以从 16% 飙升至 35%。
        • 零售与旅游网站: 即使页面加载速度只提升 0.1 秒,零售网站转化率也能增加 8.4%,旅游网站增加 10.1%。
      • 考虑真实用户场景:
        • 开发时我们通常使用高速网络和高性能电脑,但这不代表真实用户的体验。
        • 必须在平均水平的网络和设备上测试性能,以获得更真实的基准。
        • Twitter 曾实行“限速星期二”,强制工程师在慢速网络下工作,以培养对用户的同理心。
      • SEO 影响:
        • 搜索引擎(如 Google)已将网站速度作为搜索排名的重要因素。
        • 即使你的 SEO 其他方面都做得很好,速度慢于竞争对手也可能导致排名落后。
    2. 高效调试复杂 Bug
      • 对于难以复现或只在特定状态下出现的 Bug,日志记录 (console.log) 往往不够用。
      • DevTools 提供了强大的工具来深入理解你的应用:
        • CPU 和内存分析。
        • 单步调试,可以随时查看调用栈。
        • 能够在不了解源码的情况下,找出导致 UI 变化的原因。
    3. 快速进行原型设计
      • Elements 面板: 快速修改 HTML 和 CSS,实时预览 UI 变化。
      • Console 面板: 快速获取 DOM 元素并执行 JavaScript 操作,实时验证想法。
      • Sources 面板: 直接在浏览器中修改 JavaScript 代码,快速迭代。

2-web-performance-metrics

  • 核心 Web 指标 (Core Web Vitals)
    • 这是由 Google 牵头、现已成为 WhatWG 开放标准的性能衡量体系,旨在量化用户体验的关键方面。
    • Largest Contentful Paint (LCP - 最大内容绘制):
      • 衡量: 加载性能。
      • 含义: 标记视口中最大的图像或文本块完成渲染的时间点。它代表了页面的主要内容何时对用户可见。
    • Interaction to Next Paint (INP - 下次绘制交互):
      • 衡量: 响应速度。
      • 含义: 评估页面对用户交互(如点击、轻触)的整体响应能力。它测量从用户交互开始到下一帧被绘制出来所需的时间。
    • Cumulative Layout Shift (CLS - 累积布局偏移):
      • 衡量: 视觉稳定性。
      • 含义: 量化页面在加载过程中发生的意外布局偏移总量。低的 CLS 分数意味着页面是稳定的,不会因为元素突然移动而给用户带来困扰。
  • 扩展核心 Web 指标
    • 讲师所在公司 (Bloomberg) 为该标准做出了贡献,推动了 Element Timing / Container Timing 的加入。
    • 这个新指标允许开发者精确测量特定目标元素的渲染时间(例如一个金融数据表格),而不仅仅是页面上最大的元素。
    • 这体现了这些标准的开放性,鼓励社区共同完善。
  • RAIL 模型
    • 这是 Google 提出的另一个用于思考性能的框架,它影响了其工具的设计。
    • Response (响应): 应用对用户输入(点击、滚动)的响应速度应该要快。
    • Animation (动画): 动画应该流畅、不掉帧。
    • Idle (空闲): 应用应该有足够的空闲时间来处理下一次用户输入,避免因主线程长时间阻塞而导致卡顿。
    • Load (加载): 页面或操作的加载时间应该尽可能短。
  • 真实用户监控 (Real User Monitoring - RUM)
    • 重要性: 只在开发者的高性能机器上测量性能是不够的,关键是要了解真实用户在他们各自的环境中的体验。
    • 实践: 你可以为全部或部分用户收集“核心 Web 指标”等性能数据。
    • 工具: 可以使用 New Relic、Sentry 等开源或 SaaS 工具来实现。
    • 价值: 这能让你获得更准确的用户体验数据,例如了解用户群中 P99(第 99 百分位)的 LCP 是多少。

3-inspecting-elements-styles

  • 开始前的准备
    • 重要提示: 在进行任何严肃的性能分析前,请禁用 Chrome 扩展或使用无痕模式 (Incognito mode)。因为扩展程序会注入自己的 JS 和 HTML,干扰性能测量结果。
  • Elements 面板 - 概览
    • 左侧 (DOM 树):
      • 以 DOM 结构展示渲染后的 HTML。
      • 可编辑性:
        • 双击可编辑属性(如修改类名)。
        • 右键选择 "Edit as HTML" 可编辑整个 HTML 块。
    • 右侧 (Styles 窗格):
      • 显示选中元素的 CSS 样式。
      • 交互性:
        • 使用复选框可以开启/关闭样式。
        • 直接编辑样式值(如颜色、尺寸)。
        • 使用键盘上下箭头可以微调数值。
        • 点击颜色样本会打开颜色选择器,可以实时预览颜色变化,检查对比度是否符合无障碍标准,或使用预设的调色板(如 Material UI)。
      • 样式来源: 每个样式旁边都显示了其来源文件和行号,点击即可跳转到 Sources 面板。
  • Computed (计算样式) 标签页
    • 显示浏览器经过层叠、继承等一系列计算后,最终应用到元素上的样式。
    • 对于调试 CSS 优先级 (!important) 或样式覆盖问题非常有用。
    • 包含一个可视化的**盒模型 (Box Model)**图,清晰地展示了元素的 margin、border、padding 和 content 尺寸。
  • 其他实用功能
    • 强制元素状态 (:hov):
      • 无需实际交互,即可模拟元素的 :active, :hover, :focus, :visited 等伪类状态。
      • 这对于调试这些状态下的样式非常方便。
    • 添加新样式规则 (.cls / +):
      • 快速为选中元素添加一个新的 CSS 类。
      • 或者创建一个新的样式规则。
    • 渲染模拟:
      • 模拟用户的系统偏好,如深色模式 (prefers-color-scheme: dark/light)。
    • Event Listeners (事件监听器) 标签页:
      • 显示绑定到当前元素及其祖先元素上的所有 JavaScript 事件监听器。

4-using-the-network-tab

  • Network 面板 - 基础
    • 显示页面加载过程中发起的所有 HTTP 请求。
    • 简化视图: 可以通过右键点击表头,自定义显示的列,隐藏不常用的信息以保持界面整洁。
    • 查看请求详情: 点击任意一个请求,可以查看:
      • Headers: 请求头和响应头。对于调试缓存策略 (Cache-Control)、跨域 (CORS) 或 E-tags 等问题非常有用。
      • Response: 服务器返回的实际内容。
      • Timing: 请求各阶段(如 DNS 查询、建立连接、等待响应等)的耗时详情。
  • 关键信息和功能
    • 摘要栏 (底部):
      • 显示总请求数、总传输数据量、总资源大小、DOMContentLoaded 时间和 Load 时间等关键指标。
      • Transferred vs Resources: Transferred 包含上传和下载,而 Resources 仅为下载资源大小。两者可能因缓存或上传数据而不同。
    • 请求发起者 (Initiator):
      • 按住 Shift 键并悬停在某个请求上,会高亮显示是哪个资源发起了这个请求。这有助于追踪依赖关系链。
    • 排序:
      • 如果排序被打乱,可以右键点击表头,选择 "Sort by" -> "Waterfall",恢复到默认的时间线排序。
    • Disable cache (禁用缓存):
      • 勾选此项后,浏览器将忽略本地缓存,强制从服务器重新获取所有资源。
  • Screenshots (截图) 功能
    • 可以在页面加载过程中,捕获一系列可视区域的截图,形成一个加载过程的影片。
    • 重要提醒:
      • 如果 DevTools 是停靠在浏览器窗口的侧边或底部,它会遮挡部分网页内容。
      • Chrome 出于性能优化考虑,不会渲染被遮挡的部分。
      • 这会导致截图不完整,也会影响性能测试的准确性。
    • 解决方案: 在进行性能剖析或截图时,务必将 DevTools 弹出到独立的窗口,确保整个网页视口都被完整渲染和测量。

5-measuring-performance

  • Performance 面板 - 介绍
    • 这是 DevTools 中最强大但也最复杂的面板之一,用于深入分析运行时性能。
    • 面板初始界面会显示核心 Web 指标 (LCP, CLS, INP) 的实时数据。
    • 基本用法: 点击“录制”(Record) 按钮,在页面上进行一些操作(如滚动、点击),然后点击“停止”(Stop)。
  • 理解火焰图 (Flame Chart)
    • 主要关注点: 对于大多数 Web 应用,你的焦点应该在 Main thread (主线程) 上,因为应用的 JavaScript 代码主要在这里运行。
    • 其他线程简介:
      • Workers: 运行在 Web Worker 中的 JavaScript,用于执行耗时任务而不阻塞主线程。
      • GPU: 处理 GPU 加速的任务,如 CSS 动画、变换和 WebGL 渲染。
    • 导航:
      • 左右滚动鼠标可以平移时间轴。
      • Cmd/Ctrl + 鼠标滚轮可以缩放时间轴,以聚焦于某个特定时间段。
  • 解读主线程图表
    • X 轴 (横轴): 代表时间。一个任务块的宽度表示它执行了多长时间。
    • Y 轴 (纵轴): 代表调用栈。任务块的堆叠关系表示函数的调用关系(上层是被下层调用的)。
    • 颜色编码:
      • 黄色 (Scripting): 执行 JavaScript。
      • 紫色 (Rendering): 计算样式和布局。
      • 绿色 (Painting): 将像素绘制到屏幕。
      • 灰色 (System): 浏览器内部的其他任务。
  • 分析任务块:Total Time vs Self Time
    • 当你点击一个任务块时,下方的详情面板会显示其耗时。
    • Total Time (总耗时): 指的是该函数及其所有子函数执行所花费的总时间。
    • Self Time (自耗时): 指的是仅在该函数本身执行所花费的时间,不包括它调用的其他函数。
    • 性能优化技巧:
      • 在调用栈中,你应该寻找最底层的那个宽任务块 (the last wide block)
      • 这个任务块的 Self Time 很长,意味着它本身就是性能瓶颈,而不是因为它调用了其他耗时函数。这才是你需要优化的目标。
    • 上下文:
      • Performance 面板展示的是 Chrome 进程级别的信息,不会深入到操作系统内核。你看到的最底层信息是 Chrome 内部任务。

6-console-sources-tabs

  • Console (控制台) 面板
    • 功能完备的 REPL (交互式解释器):
      • 可以执行任意 JavaScript 代码,声明变量,进行计算。
    • 与 DOM 交互:
      • 可以使用标准的 DOM API,如 document.getElementsByClassName('main-nav')
      • 当鼠标悬停在控制台输出的 DOM 元素上时,页面上对应的元素会高亮显示。
    • 便捷指令 ($0, $1 等):
      • $0 代表在 Elements 面板中当前选中的元素。
      • $1 代表上一个选中的元素,以此类推。
      • 这提供了一个强大的工作流:先在 Elements 面板中直观地选中一个元素,然后切换到 Console 面板使用 $0 对它进行编程操作(例如 $0.textContent = 'new text')。
    • 过滤与视图:
      • 显示 console.log、警告和错误信息。
      • 可以按信息级别(Verbose, Info, Warnings, Errors)进行过滤。
      • Issues 标签页: 以更易读的方式列出页面中存在的问题,例如缺少文档类型声明 (doctype) 导致页面进入怪异模式等。
  • Sources (源代码) 面板
    • 一个内嵌的 IDE:
      • 可以查看项目的源文件(HTML, CSS, JS)。
      • 可以在浏览器中直接编辑代码。
    • Workspaces (工作区 - 持久化修改):
      • 过去,可以将网络资源映射到本地文件,从而实现在 DevTools 中做的修改直接保存到磁盘。
      • 现代开发的挑战: 随着打包工具(如 Webpack, Vite)的普及,浏览器中运行的代码是经过编译和打包的,与源码存在差异。这使得 DevTools 很难将修改映射回原始文件,因此该功能在现代工作流中用处不大。
    • 单步调试 (Step-Through Debugging):
      • 这是如今 Sources 面板最核心的用途。
      • 当代码执行到 debugger; 语句或预设的断点时,执行会暂停。
      • 调试工具栏和右侧窗格提供了强大的调试功能:
        • Watch (监视): 监控特定表达式的值。
        • Breakpoints (断点): 管理所有断点,包括条件断点和事件断点。
        • Scope (作用域): 查看当前作用域中的所有变量(局部、闭包、全局)。
        • Call Stack (调用栈): 查看函数的调用层级,可以点击切换到任意上层函数的作用域。
        • 高级断点: 不仅可以设置在代码行上,还可以设置在特定事件上,如“当某个 DOM 元素的属性被修改时暂停”或“当某个网络请求发起时暂停”。

7-browsing-storage-memory-usage

  • Application (应用) 面板
    • 用于检查和管理浏览器端的所有存储类型。
    • 支持的存储类型:
      • Local Storage (本地存储)
      • Session Storage (会话存储)
      • IndexedDB
      • Cookies
    • 功能: 你可以查看、编辑甚至删除这些存储中的数据,例如查看 Local Storage 中的键值对。
    • 最常用功能: "Clear site data" (清除站点数据) 按钮。这个功能非常实用,可以一键清除当前网站的所有存储、缓存和服务工作线程,让应用恢复到“全新”状态。这对于调试登录状态或缓存问题特别有效。
    • Service Workers:
      • 管理已注册的 Service Worker。
      • 模拟离线状态。
      • 注销 Service Worker。
    • Progressive Web App (PWA):
      • 检查 Web App Manifest (manifest.json) 文件,查看应用的图标、主题色等配置。
  • Memory (内存) 面板
    • 用于分析应用的内存使用情况,是查找内存泄漏的关键工具。
    • Heap Snapshot (堆快照):
      • 这是最核心的功能。点击 "Take snapshot" 按钮可以捕获当前 JavaScript 堆的内存状态。
      • 快照会显示当前内存中存在的所有对象、它们的大小以及它们被谁引用(这有助于判断为什么一个对象没有被垃圾回收)。
      • 在快照中,被括号 () 包围的条目通常是浏览器内部的系统对象,而非你应用代码直接创建的。
    • 高级功能:
      • 可以检查 WebAssembly (Wasm) 模块(例如由 C++ 或 Rust 编译而来)的内存使用情况。
      • 也可以检查 Typed Arrays (类型化数组) 的内存。
    • 注意: 内存分析是课程后面会深入讲解的复杂主题。

8-lighthouse-reports-device-simulation

  • Lighthouse 面板
    • 一个自动化的审计工具,用于对网页进行全面的评估并生成报告。
    • 配置选项:
      • Mode (模式):
        • Navigation (导航): 默认模式,分析一次完整的页面加载。
        • Timespan (时间跨度): 记录一段用户交互流程(例如,开始录制 -> 在游戏中玩一关 -> 停止录制)。
        • Snapshot (快照): 分析页面当前的状态,不重新加载。
      • Device (设备): 可以在移动设备或桌面设备之间进行模拟切换。
      • Categories (类别): 选择要运行的审计项目:
        • Performance (性能)
        • Accessibility (无障碍)
        • Best Practices (最佳实践)
        • SEO (搜索引擎优化)
    • 结果: 运行后,Lighthouse 会生成一份详细的报告,包含各项得分以及可操作的改进建议。
  • 设备模拟工具 (Device Toolbar)
    • 位于 DevTools 左上角的工具栏。
    • 视口模拟:
      • 可以从预设的设备列表(如 iPhone, Pixel)中选择,或设置自定义的响应式分辨率,来测试你的页面布局在不同尺寸屏幕下的表现。
    • 网络限速 (Network Throttling):
      • 模拟不同的网络环境(如 Fast 3G, Slow 3G, Offline)。
      • 最佳实践: 将设备模拟和网络限速结合使用,可以更真实地测试用户体验(例如,“我的网站在一部旧款 iPhone 上使用慢速移动网络时性能如何?”)。
  • 其他实用工具
    • 元素选择器 (左上角的箭头图标):
      • 点击此图标后,在页面上移动鼠标即可轻松选中特定元素,单击后会在 Elements 面板中定位到该元素。
      • 这比在复杂的 DOM 树中手动展开节点去寻找一个元素要高效得多。
    • 原生应用调试:
      • Chrome DevTools 也可以连接到原生的 Android 应用进行调试。虽然课程不深入讲解,但提供了相关文章链接作为参考。

9-history-of-devtools

  • 开发者工具出现之前的 Web 开发
    • 可用工具:
      • 查看页面源代码 (View page source): 只能看到原始的 HTML 文本,没有交互、没有语法高亮、也没有 CSS 样式的应用。
      • alert() 语句: 这是早期唯一的调试信息输出方式。
    • alert() 的问题:
      • 它会阻塞页面,并且难以关闭。
      • 只能处理原始值(字符串、数字)。当试图打印数组或对象时,只会显示 [object Object]
      • 开发者需要写循环来遍历对象的键并逐个 alert() 出来,非常低效。
  • Web 开发者工具的演进史
    • 1993: Web 诞生,只有“查看源代码”和 alert()
    • Netscape: 首次引入了 console.log,在一个单独的 JavaScript 控制台标签页中显示信息。
    • 2006: Firebug (for Firefox) - 被认为是所有现代开发者工具的精神鼻祖。它的界面和功能与今天的 Chrome DevTools 非常相似。
    • 后续发展 (第一版总结):
      • Google 推出自己的 Chrome DevTools。
      • Source Maps 出现,以应对代码打包和转译带来的调试难题。
      • 新的面板如 Performance (性能) 被添加。
      • 2017: Firefox 重构了其开发者工具,引入了创新的 3D 视图等功能。
      • Edge 浏览器采用 Chromium 内核,使得 Chrome DevTools 成为事实上的标准。
  • 更完整的历史 (经过社区补充)
    • Firebug 之前:
      • Venkman: 一个为 Firefox 打造的工具集,包含了源代码查看、控制台日志和单步调试的早期理念。
      • Charles Proxy: 独立的 HTTP 流量监控工具,允许拦截和调试网络请求。
      • DOMi: 一个 DOM 检查器。
    • 更早期的历史:
      • 1998: Microsoft Script Debugger - 实际上比 Mozilla 的工具更早,是一个独立的 Windows 应用,可以用于脚本调试。
      • Firefox Web Developer Toolbar: 一个在 Firebug 之前很流行的工具栏,提供了查看脚本等多种功能。
      • YSlow: 独立推出的第一个页面分析器,是 Lighthouse 的前身。
      • WebKit: 很早就推出了自己的 Web Inspector。
      • Dynatrace: 制作了首个 Ajax 编辑器,用于可视化异步 JavaScript 调用。
      • Google PageSpeed Analyzer: Lighthouse 之前 Google 自己的页面速度分析工具。
    • 近期发展:
      • 2018-2019: 出现了专注于开发者体验的浏览器,如 Sizzy 和 Polypane。
  • 结论
    • 开发者工具的演进是一个渐进的过程,由微软、Mozilla、Google 和社区中的许多人共同推动,而不是某个天才的单次发明。
    • Firebug 在 2006 年的设计奠定了现代开发者工具的基础,其布局(左边 DOM,右边样式)至今仍在使用。

10-elements-console-source-maps

  • Elements 面板:HTML 与 DOM 的区别
    • HTML: 是你通过 "View Source"(查看源代码)看到的原始文本文件。
    • DOM (Document Object Model): 是 Elements 面板中显示的内容。它不是静态的文本,而是一个活的、可交互的对象树
    • DOM 的形成过程: 浏览器首先解析 HTML 文本,然后应用 CSS 样式,最后执行 JavaScript 代码。JavaScript 可能会动态地修改 DOM(添加、删除或更改元素)。
    • 因此,Elements 面板展示的是经过所有这些处理后最终渲染出来的页面结构,包含了尺寸、位置、属性和事件监听器等丰富信息。
  • CSS 特性 (Specificity)
    • 问题背景: 当多个 CSS 选择器应用到同一个元素上并定义了相同的属性时(例如,都设置 color),浏览器需要一套规则来决定到底应用哪个样式。
    • 解决方案: CSS Specificity (特性或优先级)。这是一套标准化的规则,用于确定哪个选择器的权重更高。
    • 基本规则:
      • 选择器越具体,其优先级越高。
      • 例如,一个 ID 选择器 (#my-id) 的优先级高于一个类选择器 (.my-class),而类选择器的优先级又高于一个元素选择器 (div)。
      • !important 声明拥有最高的优先级,会覆盖其他所有样式。
    • 在 DevTools 中的体现:
      • 在 Styles 面板中,如果一个样式因为优先级较低而被覆盖,它会被划上删除线
      • 这有助于你快速诊断为什么某个样式没有生效。
  • Source Maps
    • 问题背景: 现代 Web 开发中,我们在浏览器中运行的代码(例如,经过 TypeScript 转译、Webpack 打包、Terser 压缩后的代码)与我们编写的原始源代码差异巨大。
    • 解决方案: Source Maps。它是一个映射文件,建立起了运行代码源代码之间的桥梁。
    • 作用:
      • 当你在 DevTools 中调试时,即使浏览器正在执行的是压缩和混淆过的代码,Source Maps 也能让你看到并断点在你编写的、可读的原始源代码上。
      • 这极大地简化了在现代构建流程下的调试工作。

11-making-quick-edits

  • CSS 特性 (Specificity) 实践
    • DevTools 会直观地展示 CSS 优先级的应用结果。
    • 当一个样式被更高优先级的规则覆盖时,它会在 Styles (样式) 面板中显示为被划掉的状态。
    • Computed (计算样式) 面板中,你可以看到最终生效的样式。点击旁边的小箭头,可以直接跳转到定义该样式的具体规则。
  • 快速编辑技巧
    • CSS 编辑:
      • 直接修改属性名和属性值。
      • 点击复选框可以快速启用/禁用某条样式。
      • 点击颜色方块会弹出强大的颜色选择器。
    • HTML 编辑:
      • 双击标签名(如 nav)可以直接修改标签类型(如改为 h1)。
      • 编辑属性(如 class)或元素内容。
      • 右键选择 "Edit as HTML" (以 HTML 格式编辑) 可以对整个代码块进行自由修改。
    • scroll into view (滚动到视图中):
      • 这是一个非常实用的功能,尤其在处理长列表时。
      • 在 Elements 面板中右键点击一个在当前视口不可见的元素,选择 scroll into view,页面会自动滚动到该元素的位置。
    • 控制台快捷方式 ($0):
      • 在 Elements 面板选中一个元素后,按 Esc 键可以打开一个迷你的 Console (控制台) 窗口。
      • 在控制台中使用 $0 可以直接引用你刚刚选中的那个元素,并对其进行编程操作。
    • 隐藏/显示元素:
      • 选中一个元素后,按 H 键可以快速切换其显示和隐藏状态(相当于添加 visibility: hidden;)。
    • 模拟状态与偏好:
      • 使用 :hov 按钮可以强制元素进入 :hover, :focus 等伪类状态,方便调试这些状态下的样式。
      • 可以模拟用户的系统偏好,如深色模式 (prefers-color-scheme: dark)。
  • 高级调试功能
    • DOM Change Breakpoints (HTML 断点)
      • 这是一个强大的“魔法”功能,用于追踪是什么代码导致了 UI 的变化。
      • 在 Elements 面板中右键点击一个元素,选择 "Break on" (中断于...),可以设置三种类型的断点:
        1. subtree modifications: 当该元素的子节点被添加、删除或移动时中断。
        2. attribute modifications: 当该元素的属性(如 class, style)被修改时中断。
        3. node removal: 当该元素即将被从 DOM 中移除时中断。
      • 当断点被触发时,DevTools 会自动暂停在导致这一变化的 JavaScript 代码行上。
    • 查找事件监听器 (Event Listeners)
      • 选中任意元素,切换到 "Event Listeners" 标签页,可以看到绑定在该元素上的所有事件监听器,并可以点击跳转到定义该事件的源代码。
    • 颜色格式转换和主题
      • 颜色选择器可以让你在不同颜色格式(如HEX, RGB, HSL)之间轻松转换。
      • 它可以自动提取你项目中定义的 CSS 变量,让你在调试时可以方便地从预设的主题色中选择。

12-viewing-accessibility-information

  • 无障碍颜色选择器 (Accessible Color Picker)
    • 这是一个实验性功能,需要手动开启,但非常实用。
    • 它可以帮助你确保文本颜色和背景颜色之间的对比度符合无障碍标准。
  • 如何启用
    1. 点击 DevTools 右上角的设置图标 (齿轮状)
    2. 进入 Experiments (实验) 标签页。
    3. 勾选与 "accessibility color contrast" (无障碍颜色对比度) 相关的选项。
    4. 关闭设置,DevTools 会提示需要重新加载,确认即可。
  • 如何使用
    1. 在 Elements 面板中,选择一个包含文本内容的元素(关键点)。
    2. 在 Styles 面板中,找到 color (字体颜色) 属性,并点击颜色样本。
    3. 在弹出的颜色选择器中,你会看到一个新的区域,名为 Contrast ratio (对比度)
      • 它会显示一个比率值,并用图标(✔ 或 ✗)标明当前颜色组合是否符合 AA 或 AAA 级的无障碍标准。
      • 在颜色选择区域内,会出现一条分界线。线一侧的颜色是符合对比度要求的,另一侧则不符合。
    4. 重要提示: 对比度的要求与字体大小相关。同一个颜色组合,对于大号字体可能是合规的,但对于小号字体可能就不合规。这个工具会自动将当前元素的字体大小考虑在内。
  • 总结
    • 这是讲师一直开启的实验性功能,可以帮助开发者在设计和调试阶段就确保颜色的可访问性。

13-quick-edits-exercise

  • 练习任务
    1. 将页面上的一个有序列表 (<ol>) 更改为无序列表 (<ul>)。
    2. 一个密码输入框禁止了粘贴操作。绕过这个限制,并将一个长字符串设置为其密码。
    3. 找出一个 ID 为 12345678 的卡片,并(理论上)更改其边框颜色。思考一下如果这是一个无限滚动的列表,该如何操作。
  • 解决方案
    1. 修改列表类型:
      • 右键检查该列表,定位到 <ol> 标签。
      • 在 Elements 面板中双击标签名 ol,将其改为 ul。DevTools 会自动更新对应的闭合标签。
    2. 绕过禁止粘贴:
      • 方法一 (修改 Class): 检查输入框,发现它有一个名为 .disallow-paste 的类。移除这个类,就可以正常粘贴了。
      • 方法二 (直接修改值): 检查输入框,直接在 HTML 中编辑其 value 属性,将密码字符串粘贴进去。
      • 方法三 (修改事件监听器): 右键检查输入框,切换到 "Event Listeners" 标签页,找到 paste 事件。点击进入源代码,注释或删除掉调用 event.preventDefault() 的那行代码。
    3. 查找特定 ID 的元素:
      • 方法一 (搜索): 在 Elements 面板中按 Cmd/Ctrl + F,在搜索框中输入 ID 12345678 即可定位。
      • 方法二 (控制台): 在 Console 中执行 document.getElementById('12345678')。然后右键点击返回的元素节点,选择 "Reveal in Elements panel" (在元素面板中显示),即可跳转过去。
      • 如果元素不在当前视口中(例如在无限滚动列表中),可以在定位到它之后,右键选择 scroll into view,页面就会自动滚动到该元素的位置。
  • 哲学思考:前端安全
    • 提问:如何构建一个无法被开发者工具轻易绕过的功能?
    • 回答:你做不到。 前端代码和环境完全由用户控制。任何重要的安全验证、权限检查等,必须在服务器端 (back-end) 完成
    • 试图在前端禁止右键、禁用开发者工具或阻止粘贴等行为,不仅总有办法被绕过,而且通常会损害用户体验(例如,阻止密码管理器)。
    • 核心理念是:后端必须能够处理来自前端的任何不可信的请求。

14-network-optimizations

  • 网络请求的瀑布流模型 (Waterfall)
    • 典型网站的加载顺序如下:
      1. 文档 (Document): 首先下载 index.html 文件。
      2. 关键资源 (Critical Assets): 浏览器解析 HTML 的 <head> 标签,发现 CSS (<link>) 和 JavaScript (<script>) 的引用,并立即开始下载这些资源。
      3. 主体内容与异步请求: 接着解析 <body> 标签,下载图片等资源,并执行 JavaScript,可能会触发异步的 API 调用 (fetch/XHR)。
  • HTTP 请求与响应
    • 网络通信是基于客户端与服务器之间的请求-响应模式进行的。
    • 请求和响应都由请求行/状态行头部 (Headers)主体 (Body) 组成。
    • DevTools 的 Network 面板可以让你清晰地看到每一次通信的这些组成部分。
  • 浏览器渲染流程
    • 浏览器的工作不仅仅是下载文件,它是一个组装过程:
      1. 下载 HTML -> 解析成 DOM 树。
      2. 下载 CSS -> 解析成 CSSOM 树。
      3. 执行 JavaScript -> 可能会修改 DOM 和 CSSOM。
      4. 将 DOM 和 CSSOM 合并成 Render Tree (渲染树)
      5. Layout (布局): 计算每个节点在屏幕上的确切位置和大小。
      6. Paint (绘制): 将节点实际绘制到屏幕上。
    • 性能瓶颈: 浏览器必须等待 CSS 和 JavaScript 加载并执行后才能知道最终的页面布局,这常常是加载性能的瓶颈。
  • 浏览器缓存 (Browser Caching)
    • 对于静态资源(如 CSS、JS、图片),可以设置缓存策略,让浏览器将它们存储在本地。
    • 当用户再次访问时,浏览器会直接从缓存中读取,而无需再次发起网络请求,从而极大地提升加载速度。
    • Network 面板会显示资源是从缓存加载还是从网络加载。
  • 资源压缩 (Compression)
    • 概念: 在将文件通过网络发送前,对其进行压缩,以减小传输体积。浏览器接收到后会先解压再使用。
    • 常用算法:
      • Gzip: 最流行、兼容性最好的压缩算法。
      • Brotli: 更新的算法,通常能提供比 Gzip 更高的压缩率(文件更小),但压缩过程本身耗时更长。解压速度很快。
    • 有损 (Lossy) vs 无损 (Lossless):
      • 像 Gzip 和 Brotli 用于压缩源代码(HTML, CSS, JS)的是无损压缩,解压后能 100% 还原原始内容。
      • 图片压缩则通常是有损压缩,会牺牲一些图像质量来换取更小的文件体积。

15-browser-priority-preloading-prefetching

  • 浏览器优先级 (Browser Priority)
    • 背景: 浏览器在同一时间能够并行下载的资源数量是有限的。当页面有大量资源需要加载时,浏览器必须决定先下载哪些,后下载哪些。
    • 默认规则: 浏览器有一套内置的、标准化的优先级规则。
      • 例如,HTML 文档的优先级最高。<head> 里的 CSS 和同步 JS 优先级也很高。而页面下方(below the fold)的图片优先级则较低。
    • DevTools: 在 Network 面板中,你可以看到每个资源被浏览器分配的优先级(Highest, High, Medium, Low)。
  • 开发者控制优先级:Preload & Prefetch
    • 我们可以通过特定的 HTML 标签向浏览器提供“提示”,来覆盖默认的优先级。
    • preload (预加载):
      • 用途: 用于加载对当前页面渲染至关重要的资源。
      • 效果: 告诉浏览器“这个资源非常重要,请以最高优先级立即开始下载”。
      • 典型案例: 预加载一个自定义字体文件,以避免页面初次渲染时出现字体闪烁(FOUT - Flash of Unstyled Text)。使用了 preload 后,字体文件会和 CSS 一起被优先下载。
    • prefetch (预取):
      • 用途: 用于加载用户未来可能访问的页面或资源。
      • 效果: 告诉浏览器“当网络空闲时,请以最低优先级在后台下载这个资源,以备后用”。
      • 典型案例: 在一个搜索结果页,可以根据算法预测用户最可能点击的那个链接,并对其进行 prefetch。如果用户真的点击了,页面会因为资源已被预取而瞬间加载完成。
  • 使用注意事项
    • “优化一切等于没有优化”: 不要滥用这些技术。如果你把所有东西都标记为 preload,反而会造成资源竞争,阻塞更重要的资源。
    • 可能造成浪费: 如果 prefetch 的资源用户最终没有访问,那么这次下载就浪费了带宽。
    • 测量是关键: 在使用这些高级技术后,一定要通过 DevTools 测量性能,确保它们 действительно 带来了正面效果,而不是引入了新的瓶颈。
  • 关于打包 (Bundling) 的现状
    • 尽管 HTTP/2 和 HTTP/3 提升了并行请求的能力,但目前我们仍然生活在一个需要打包的世界里。将所有小文件直接提供给浏览器通常不是最佳选择。
    • 现代框架和构建工具提供了代码分割(code-splitting)等技术,可以智能地将代码拆分成块,并结合 preload 等技术进行优化加载。

16-using-the-network-devtools

  • Network 面板实战
    • 打开 Network 面板并刷新页面,可以看到所有资源的加载情况。
    • 常见工作流:
      • Size (大小) 排序,快速找出页面上最大的文件(通常是图片或 JS 包)。
      • 使用网络限速 (Throttling) 功能(如 Slow 3G)来模拟真实用户的慢速网络环境,这能暴露出在高速网络下不易发现的性能问题。
      • 使用 Disable cache (禁用缓存) 复选框来确保每次都是从服务器全新加载,便于调试。
    • 重要提醒: 务必记得关闭限速和禁用缓存,否则可能会在后续工作中对自己造成困扰(例如,提交一个“网站加载极慢”的乌龙 bug)。
  • 深入分析单个请求:Timing 标签页
    • 这是 Network 面板中一个非常强大但常被忽视的功能。
    • 点击任意一个请求,然后选择 Timing 标签页,可以看到该请求从发起队列到完成下载的完整生命周期分解图。
    • 关键阶段解读:
      • Queuing (排队): 请求在被浏览器实际发送前等待的时间。可能是因为优先级低,或是有更高优先级的请求正在处理。
      • Stalled (停滞): 因达到同源最大连接数限制等原因而停滞的时间。
      • DNS Lookup: DNS 查询耗时。
      • Initial connection / SSL: 建立 TCP 连接和进行 SSL/TLS 握手所需的时间。
      • Request sent: 发送请求本身所需的时间。
      • Waiting (TTFB - Time To First Byte): 等待服务器响应第一个字节的时间。这个时间很长通常意味着后端处理慢
      • Content Download: 下载响应内容本身所需的时间。这个时间很长通常意味着资源太大或用户网络慢
    • 价值: 通过这个视图,你可以精准定位到网络请求的瓶瓶颈究竟是出在前端(请求被阻塞)、网络(连接慢)还是后端(服务器响应慢)。
  • JavaScript 的真实成本
    • 下载只是开始: 我们常常只关注文件大小和下载时间,但这具有误导性,尤其是对于 JavaScript。
    • 一个 3KB 的 JS 文件和一个 10KB 的图片,哪个成本更高?
      • 图片下载后,浏览器只需解码并显示它,成本较低。
      • JavaScript 文件下载后,浏览器还必须解析 (Parse)、编译 (Compile) 和执行 (Execute) 它。这个过程会占用大量 CPU 时间,尤其是在性能较差的移动设备上。
    • 结论: 减少 JavaScript 的体积 (通过代码分割、移除无用代码等方式) 对页面加载性能的提升,远比单纯通过压缩获得的收益要大,因为它同时减少了下载时间和 CPU 执行时间。

17-lighthouse-web-audits

  • Lighthouse 简介
    • Lighthouse 是一个强大的自动化审计工具,是进入性能分析领域的最佳切入点。
    • 它不仅局限于观察(如 Network, Elements),而是主动分析并给出应用的性能报告。
  • 历史与演变
    • YSlow: 最早流行的页面分析工具之一,以浏览器扩展的形式存在。它基于一系列规则集对网站进行评估并打分。
    • Google PageSpeed Insights: Google 早期的在线分析工具。
    • 局限性: 这些早期工具通常需要一个公开可访问的 URL,无法用于本地开发项目,也难以在特定条件下复现测试。
    • Lighthouse 的优势: 被集成到 Chrome DevTools 中,使得开发者可以在任何环境下(包括本地)对应用进行审计。
  • Lighthouse 的功能模式
    • 设备模拟: 可以选择模拟移动设备或桌面设备。
    • 类别选择: 可以选择运行性能、无障碍、最佳实践和 SEO 四大类中的任意组合。
    • 审计模式:
      • Navigation (导航): 分析一次完整的页面加载。
      • Snapshot (快照): 分析当前页面的状态,不刷新。
      • Timespan (时间段): 分析一段时间内的用户交互,比如玩一局游戏。
  • 四大审计类别详解
    1. Performance (性能)
      • 关注点: 页面加载速度和响应能力。
      • 测量指标:
        • Web Core Vitals: FCP (首次内容绘制), LCP (最大内容绘制), CLS (累积布局偏移)。
        • Time to Interactive (TTI): 页面变得可完全交互所需的时间。
        • Total Blocking Time (TBT): 主线程被长任务阻塞的总时间。
      • 分析对象: 资源(JS, 图片, 字体)是否阻塞渲染,主线程是否被阻塞等。
      • 自定义指标: 大公司可能会定义自己的性能指标,如 Twitter 的 "Time to First Tweet"。
    2. Accessibility (无障碍)
      • 关注点: 网站与辅助技术(如屏幕阅读器)的兼容性。
      • 检查项:
        • 是否正确使用 ARIA 角色。
        • 颜色对比度是否足够。
        • 图片是否有 alt 属性。
        • 表单元素是否有对应的标签。
      • 重要提示: 自动化测试无法替代真实用户的测试。
    3. Best Practices (最佳实践)
      • 关注点: 代码质量和安全性。
      • 检查项:
        • 是否全站使用 HTTPS。
        • 是否使用了已废弃的 API。
        • 是否存在跨站脚本 (XSS) 等安全风险。
        • 是否使用了更高效的图片格式。
    4. SEO (搜索引擎优化)
      • 关注点: 网站在搜索引擎中的可发现性。
      • 检查项:
        • 页面是否可被爬虫抓取。
        • 是否对移动设备友好。
        • 是否有正确的元标签 (<meta>)。
      • 灵活性: 如果你的项目(如内部工具)不需要关心 SEO,可以在运行时关闭这一类别,以加快报告生成速度。

18-exploring-a-lighthouse-audit

  • 运行 Lighthouse 审计
    1. 打开 DevTools,切换到 Lighthouse 面板。
    2. 根据需要配置模式(Navigation)、设备(Desktop/Mobile)和类别。
    3. 点击 "Analyze page load" 开始审计。
    4. 在等待时,Lighthouse 会显示一些关于性能优化的有趣提示,帮助建立同理心(例如,“你上次在 2G 网络下测试你的应用是什么时候?”)。
  • 解读 Lighthouse 报告
    • 总体得分: 报告顶部会显示四个主要类别的得分(0-100)。
    • Performance (性能) 部分:
      • Metrics (指标): 直观展示了核心 Web 指标的测量值,如 FCP, TBT 等。
      • Screenshots (截图): 以幻灯片形式展示页面加载过程中的视觉变化。
      • Opportunities (优化建议): 这是最有价值的部分。它会列出具体的、可操作的优化项,并预估完成这些优化后可以节省的时间或数据量。例如:
        • “Minify JavaScript (压缩 JS)” 可以节省 56KB。
        • “Enable text compression (启用文本压缩)” 可以节省 5KB。
        • “Properly size images (适当调整图片大小)”。
      • Diagnostics (诊断信息): 提供更多关于页面性能的上下文信息。
      • 链接到文档: 每个建议项旁边都有一个链接,点击后可以跳转到 Google 的官方文档,详细了解该问题的原因和解决方法。
    • Accessibility (无障碍) 部分:
      • 列出通过和未通过的检查项。
      • "Additional items to manually check": 提供一个清单,列出 Lighthouse 无法自动检测,需要人工检查的无障碍项目。
    • Best Practices (最佳实践) 部分:
      • 指出常见问题,如页面未使用 <!DOCTYPE html> (会导致怪异模式 Quirks mode)、缺少 CSP (内容安全策略) 等。
    • SEO (搜索引擎优化) 部分:
      • 指出影响 SEO 的问题,如缺少 <meta name="description"><title> 标签。
  • 总结
    • Lighthouse 是进行性能分析的绝佳起点
    • 它能快速为你提供一个网站健康状况的概览,并指出最需要关注的“低垂的果实”(即投入少、收益大的优化项)。
    • 它的报告清晰易懂,并提供了丰富的学习资源链接。

19-lighthouse-audit-exercise

  • 练习目标
    • 对一个故意做得非常慢的页面运行 Lighthouse 审计。
    • 阅读并理解报告中提出的问题。
    • (可选,本地环境)根据建议修改源代码,重新运行审计,观察分数提升。
  • Lighthouse vs PageSpeed Insights
    • Lighthouse 是更新、更现代、贡献者更多的版本,是 PageSpeed Insights 的演进。
    • 如果你正在开始一个新项目或建立新的工作流,优先选择 Lighthouse
    • 如果你现有的 CI/CD 流程已经集成了 PageSpeed Insights 并且运行良好,则没有必要立刻迁移。
  • 审计结果分析 (示例)
    • 性能问题 (Performance):
      • JS 问题: 未压缩、包含大量未使用的代码。
      • 图片问题: 图片尺寸过大,未使用 WebP 等现代格式。
      • 缓存问题: 静态资源没有设置缓存策略。
    • 无障碍问题 (Accessibility):
      • <body> 上使用了 aria-hidden="true",导致整个页面对屏幕阅读器不可见。
      • 标题 <h1> 等元素没有内容。
      • 缺少 <title> 元素。
    • 最佳实践问题 (Best Practices):
      • 禁止用户在输入框中粘贴内容,损害了用户体验。
    • SEO 问题:
      • 缺少 <title><meta name="description"> 标签。
  • 性能、无障碍和 SEO 的协同效应
    • 这三者之间存在大量重叠。优化其中一项往往能同时改进另外两项。
    • 示例:
      • 添加 <title> 标签,既满足了无障碍要求(屏幕阅读器需要知道页面标题),也满足了 SEO 要求(搜索引擎需要知道页面标题)。
      • 使用语义化的 HTML(如 <button> 而不是 <div>),既提升了可访问性,也可能因为浏览器内建优化而提升性能。
  • 代码覆盖率 (Coverage) 工具
    • Lighthouse 只会告诉你“存在未使用的代码”,但如果你想深入了解具体哪些代码行未被使用,可以使用 DevTools 的 Coverage 工具。
    • 如何打开:
      1. 在 DevTools 中按 Esc 键,打开下方的抽屉面板。
      2. 点击左上角的三点菜单,选择 "Coverage"。
    • 如何使用:
      1. 点击 "Start instrumenting coverage and reload page"(那个圆形的重新加载图标)。
      2. 页面刷新后,Coverage 面板会列出所有加载的 JS 和 CSS 文件。
      3. 它会显示每个文件的总大小、未使用的字节数以及百分比。
      4. 点击任意文件,它会在 Sources 面板中打开,并用红色绿色标记出未使用和已使用的代码行。
    • 注意事项: Unused 并不等同于 Useless。某些代码可能在当前页面加载时未使用,但在用户进行某个操作(如打开一个弹窗)后才会被使用。因此,不能简单地删除所有标记为红色的代码。

20-debugging-javascript-code

  • 单步调试 (Step-Through Debugging) 简介
    • 单步调试是一种强大的调试技术,它能让你在代码执行的任何时刻暂停下来,检查当时的状态。这比 console.log 提供了更丰富、更深入的信息。
    • 其他编程语言(如 Java, C++)的开发者对此非常熟悉,它是 IDE 的核心功能之一。
  • 核心概念
    • 断点 (Breakpoints): 你可以在代码的任意位置设置一个“暂停点”。当代码执行到这里时,会自动暂停。
    • 暂停与继续 (Pause & Resume): 可以随时暂停或让暂停的代码继续执行。
    • 单步操作 (Stepping):
      • Step Into (步入): 如果当前行是一个函数调用,此操作会进入该函数内部的第一行。
      • Step Over (步过): 如果当前行是一个函数调用,此操作会一次性执行完整个函数,然后停在下一行代码。你不需要关心函数内部的细节。
      • Step Out (步出): 如果你已经步入了一个函数,此操作会执行完该函数余下的部分,然后停在调用该函数之后的那一行。
    • 检查状态:
      • Scope (作用域): 查看当前作用域内所有变量的值。
      • Call Stack (调用栈): 查看函数的调用层级关系,了解代码是如何一步步执行到当前位置的。
  • 一个重要的限制:不是时间旅行
    • 单步调试允许你暂停向前执行,但你不能向后退
    • 你可以沿着调用栈“回溯”查看之前的函数状态,但这只是查看快照,并不能让时间倒流。一旦代码执行过了某一行,就无法撤销。
    • 解决方案: 如果确实需要时间旅行调试,可以考虑使用 Replay.io 这类工具,它能录制完整的执行会话,并允许你来回穿梭。

21-using-the-script-debugger

  • Sources (源代码) 面板是主战场
    • 单步调试的所有操作都在 Sources 面板中进行。
    • 左侧是文件树,中间是代码编辑器,右侧是调试工具栏(包含 Watch, Call Stack, Scope 等)。
  • 设置断点的方式
    1. 点击行号: 在 Sources 面板中,直接点击代码左侧的行号即可设置或取消一个断点。
    2. debugger; 语句: 在你的 JavaScript 代码中直接写入 debugger; 这行代码。
      • 如果 DevTools 未打开,这行代码会被忽略。
      • 如果 DevTools 已打开,代码执行到这里时会自动暂停,就如同设置了一个断点。
      • 注意: 记得在提交代码前移除 debugger; 语句。大多数 Linter 都会对此发出警告。
  • 调试工具栏详解
    • Watch (监视):
      • 可以添加你关心的变量或表达式。
      • 当代码暂停时,它会实时显示这些表达式的当前值。
      • 它的内容会根据你在调用栈中选择的不同层级而动态更新。
    • Call Stack (调用栈):
      • 显示了从代码开始执行到当前断点的函数调用链。
      • 点击调用栈中的任意一行,可以“穿越”到那个函数的上下文中,查看当时的作用域和变量值。这在某种意义上实现了“时间旅行”式的回溯查看。
    • Scope (作用域):
      • 显示当前断点位置所有可访问的变量,包括局部变量(Local)、闭包变量(Closure)和全局变量(Global)。
      • 这是理解作用域链和变量状态最直观的方式。
    • 单步操作按钮:
      • Resume/Pause: 继续执行/暂停。
      • Step Over: 步过。
      • Step Into: 步入。
      • Step Out: 步出。
  • 高级断点
    • 条件断点 (Conditional Breakpoints):
      • 右键点击一个已设置的断点,选择 "Edit breakpoint"。
      • 可以输入一个条件表达式(例如 url === 'my-api-endpoint')。
      • 只有当该表达式为 true 时,断点才会触发。
      • 这对于调试在循环中或被频繁调用的函数非常有用。
    • 其他类型的断点:
      • Fetch/XHR Breakpoints: 当发起符合特定 URL 模式的网络请求时暂停。
      • DOM Change Breakpoints: 当 DOM 元素发生变化时暂停(在前几节已介绍)。
  • 处理压缩/转译代码
    • 最佳方案: 确保有 Source Maps。DevTools 会自动利用 Source Maps,让你在原始、可读的源代码上进行调试。
    • 次优方案 (Ignore List):
      • 在 DevTools 的设置中,有一个 "Ignore List" (忽略列表)。
      • 你可以添加模式(如 node_modules/react.js)来告诉调试器忽略这些文件。
      • 这样,当你进行单步调试时,它会自动跳过这些库的代码,只停留在你自己的应用代码中。
    • 注意: 浏览器扩展的代码也会出现在调试器中,使用忽略列表可以帮助过滤掉这些干扰。

22-step-through-debugging-exercise

  • 练习场景
    • 页面本应显示一个宝可梦进化列表,但现在什么都没有,并且控制台报了两个错误。
    • 目标不是简单地修复 bug,而是熟练运用调试器来理解问题发生的过程
  • 调试过程分解
    1. 第一个错误: "Cannot read properties of undefined (reading 'species')"`
      • 定位: 点击控制台中的错误链接,直接跳转到 Sources 面板的出错代码行 chain = chain.species.name
      • 设置断点: 在出错行的上一行设置一个断点。
      • 刷新页面: 页面重新加载并在断点处暂停。
      • 检查变量: 鼠标悬停在 chain 变量上,或在 Watch/Scope 面板中查看,发现它的值是 undefined
      • 回溯调用栈: 点击 Call Stack (调用栈) 的上一层,查看调用该函数的代码。发现传入的 evolutionData.chain 就是 undefined
      • 发现根源: 进一步检查 evolutionData,发现它不是一个 JSON 对象,而是一个 Response 对象。这是因为 fetch API 返回的是一个 Promise,需要先调用 .json() 方法来解析 body。
      • 修复: 在两个 fetch 调用后添加 .then(res => res.json()) 来正确解析数据。
    2. 第二个错误: "Cannot read properties of null (reading 'appendChild')"`
      • 定位: 修复第一个问题后刷新,控制台出现新错误,点击链接定位到出错代码行 evolutionSequence.appendChild(...)
      • 设置断点与检查: 在该行设置断点并刷新。检查 evolutionSequence 变量,发现它的值是 null
      • 分析代码: 向上追溯 evolutionSequence 的定义,发现它来自 document.getElementById('pokemon-evolutions')。这说明在执行这行代码时,DOM 中还不存在 ID 为 pokemon-evolutions 的元素。
      • 发现根源: 查看代码逻辑,发现创建了 evolutionSequence (一个 div),但没有将它添加到页面的 DOM 树中。
      • 修复: 添加代码将 evolutionSequence 附加到页面的某个父元素上。
  • 总结与反思
    • 这个练习展示了相比于 console.log,单步调试的优势:
      • 提供完整的上下文: 你可以随时查看整个调用栈和所有作用域内的变量。
      • 检验假设: 你可以一步步地执行代码,验证你对代码行为的假设是否正确。
    • 调试器的适用场景:
      • 复杂 bug: 当问题涉及多个函数或异步流程时。
      • 构建时间长的项目: 避免了为添加 console.log 而反复等待漫长的编译过程。
      • 学习代码库: 通过设置断点和单步执行,可以快速理解一个陌生代码库的运行流程。
    • console.log 依然有价值: 对于简单的场景和快速反馈,console.log 仍然是一个高效的工具。两者应结合使用。

23-measure-performance-with-rail

  • Performance (性能) 面板概览
    • 这是一个功能强大但初看起来令人生畏的工具。
    • 关键信号:红色标记
      • 当你在性能录制的结果中看到红色的条块时,这是一个重要的警示信号。
      • 红色代表“页面卡顿 (Page Jank)”,意味着掉帧 (Dropped Frames)
  • 理解页面卡顿 (Page Jank) 和掉帧
    • 刷新率 (Refresh Rate): 大多数显示器的刷新率为 60Hz,意味着屏幕每秒会刷新 60 次。
    • 帧 (Frame): 为了实现流畅的动画或滚动,浏览器需要在每次屏幕刷新时都提供一个新的画面(即一帧)。
    • 掉帧的原因: 如果在两次屏幕刷新之间的时间内(约 16.6ms),浏览器的主线程因为执行耗时的 JavaScript 或复杂的样式计算而过于繁忙,它就无法按时生成并提交新的帧。这时,屏幕就会继续显示上一帧的内容,直到浏览器忙完为止。
    • 用户体验: 频繁的掉帧会导致用户感觉页面滚动不流畅、动画卡顿,甚至完全无响应。
  • 基于人类感知的 RAIL 模型时间阈值
    • RAIL 模型不仅是一个概念,它还基于人类对延迟的感知定义了一些关键的时间阈值。
    • 0 - 16ms (约 60fps):
      • 这是实现流畅动画的目标。只要浏览器能在这个时间内生成一帧,用户就会觉得动画是完全平滑的。
    • 0 - 100ms:
      • 这是实现即时交互反馈的目标。当用户点击一个按钮时,如果页面在 100ms 内给出响应(例如,按钮状态变化、出现加载指示器),用户会感觉操作是立即生效的。
    • 100ms - 1000ms (1 秒):
      • 用户能感觉到延迟,但如果提供了加载指示(如 spinner),他们通常还能保持耐心,感觉任务正在进行中。
    • > 1 秒:
      • 用户的注意力开始涣散,可能会感到不耐烦,甚至放弃操作。
    • > 10 秒:
      • 用户会感到非常沮丧,很可能会离开你的网站。
  • 主线程阻塞与输入延迟
    • 即使一个操作本身很快(例如,一个点击事件的处理函数只需要 50ms),但如果用户点击时主线程正在忙于执行一个长任务,那么这个点击事件就会被排队等待
    • 总延迟 = 排队时间 + 执行时间
    • Performance 面板可以清晰地展示出这种排队和执行的时间分配,帮助你找到阻塞主线程的元凶。
  • 适用场景
    • 大多数网站主要关注页面加载时的性能。
    • 对于计算密集型应用(如在线游戏、金融数据分析工具),持续监控应用在稳定运行状态 (steady state) 下的性能,避免卡顿,就变得至关重要。

24-avoiding-page-jank-requestanimationframe

  • JavaScript 的真实成本 (再次强调)
    • 同样大小的 JavaScript 文件和图片文件,它们的性能成本是完全不同的。
    • 图片: 成本主要是下载时间,后续的解码和渲染非常快。
    • JavaScript: 成本包括下载、解析、编译和执行四个阶段,后三者会消耗大量 CPU 资源。
  • 避免页面卡顿 (Page Jank) 的核心
    • 16ms 预算: 考虑到 60Hz 的刷新率,浏览器大约有 16.6ms 的时间来完成一帧的所有工作。
    • 10ms 实际预算: 除去浏览器自身的开销,留给应用开发者的实际预算大约只有 10ms
    • 关键点: 任何阻塞主线程超过 10ms 的单次操作都可能导致掉帧和卡顿。
    • 解决方案: 将长任务分解成多个小任务(Chunking),或者将它们放到 Web Worker 中执行。
  • 读/写操作与强制同步布局
    • 在 JavaScript 中,我们频繁地对 DOM 进行读操作(如 element.offsetWidth)和写操作(如 element.style.width = '100px')。
    • 性能陷阱: 当你进行了一个写操作(改变了样式),然后立即进行一个读操作(读取布局相关的属性如宽度、高度、位置),浏览器为了给你一个准确的值,不得不立即重新计算整个页面的布局(Layout)。这个过程被称为强制同步布局 (Forced Synchronous Layout),它非常耗时。
    • 糟糕的模式: 在循环中交替进行读写操作 (read-write-read-write) 会导致浏览器在每次循环中都强制重新计算布局,从而引发严重的性能问题和页面卡顿。
    • 理想的模式: 将所有读操作和写操作分批进行(先完成所有的读,再完成所有的写),这样浏览器就可以在一次性的、优化的流程中完成布局计算。
  • 现代框架的作用
    • 现代前端框架(如 React, Vue, Angular)的渲染机制在很大程度上帮助我们解决了这个问题。它们会在内部将 DOM 操作进行批处理 (batching),以避免强制同步布局。
  • 原生 API 解决方案
    1. requestAnimationFrame (rAF)
      • 作用: 这是一个浏览器提供的 API,它允许你将一个回调函数注册到下一次浏览器重绘之前执行。
      • 工作原理: 你告诉浏览器:“嘿,在你准备绘制下一帧画面之前,请先执行我的这个函数。”
      • 优势:
        • 浏览器会将所有在同一帧内注册的 rAF 回调函数集中执行,这天然地形成了一种批处理机制。
        • 它是进行流畅动画的最佳选择,因为它能确保你的动画逻辑与浏览器的刷新率同步。
      • 应用: 将所有会触发布局变化的 DOM 写操作都放到 requestAnimationFrame 的回调中,是避免卡顿的有效手段。
    2. CSS 变换 (Transforms) 和合成 (Compositing)
      • 概念: 尽量使用 CSS 的 transform (translate, scale, rotate) 和 opacity 属性来实现动画。
      • 优势: 现代浏览器可以将这些属性的动画计算完全 offload 到 GPU 上处理,这个过程被称为合成 (Compositing)
      • 效果: 由于这些动画不再占用主线程,即使主线程正在执行耗时的 JavaScript,动画也能保持流畅。
      • 应用: 对于位置移动、缩放、旋转等动画,优先使用 CSS Transforms,而不是通过 JavaScript 直接修改 top, left, width, height 等会触发布局(Layout)和重绘(Paint)的属性。

25-on-page-performance-profiling

  • 开始性能分析
    1. 打开 DevTools,进入 Performance (性能) 面板。
    2. 点击 Record (录制) 按钮。
    3. 在页面上进行一些交互(如滚动、悬停)。
    4. 点击 Stop (停止) 完成录制。
  • 解读性能图表
    • 长任务 (Long Tasks):
      • 在火焰图中,带有红色三角标记的任务块代表“长任务”。
      • 这并不一定意味着页面卡顿 (jank),但它是一个警告,表明该任务的执行时间超过了浏览器渲染一帧的预算(约 16ms)。
    • 页面卡顿 (Page Jank):
      • 真正的页面卡顿,即掉帧,会在时间线上方的 Frames (帧) 泳道中以红色的帧来表示。
      • 如果没有红色帧,即使有长任务,也可能没有造成用户可感知的卡顿。
    • 理解应用行为:
      • 通过观察主线程中任务的名称,即使不看源代码,也能推断出应用的大致工作方式。例如,看到 Animation Frame FiredframeLoop,可以推断出应用正在使用 requestAnimationFrame 来驱动一个循环。
    • 从图表到源码:
      • 点击火焰图中的任意一个任务块,下方的摘要面板会显示其调用栈。
      • 点击调用栈中的函数名,可以直接跳转到 Sources (源代码) 面板中的对应代码行。
  • 性能分析后的 "Pro-Tip"
    • 函数耗时标注:
      • 当你完成一次性能录制后,再切换回 Sources 面板查看你的 JavaScript 文件,你会发现一个新的列被添加到了行号旁边。
      • 这一列会显示每个函数在本次录制中的平均执行耗时
      • 这是一个非常强大的功能,它将性能数据直接叠加在了你的源代码上,让你能一目了然地看到哪些函数是性能热点。
  • 如何进行一次好的性能录制 (Best Practices)
    • 弹出窗口: 始终将 DevTools 弹出到独立的窗口,以避免其遮挡页面而影响渲染和测量。
    • 控制录制时长: 尽量将录制时间控制在 5 秒以内。时间太长会导致数据量过大,难以分析。
    • 进行交互: 在录制期间与页面进行一些交互,以捕捉真实使用场景下的性能表现。
    • 专注单一场景 (Test-driven approach): 像测试驱动开发一样,每次只专注于分析一个特定的交互或场景,避免在一次录制中混合太多不相关的操作。
  • 多视图分析 (Bottom-up, Call Tree)
    • Performance 面板提供了多种视图来分析同一份录制数据。
    • Bottom-up (自下而上) 视图:
      • 这个视图非常有用,它会列出所有被执行的函数,并按其 Self Time (自耗时)Total Time (总耗时) 进行排序。
      • 你可以快速找到那些自身执行时间最长的函数,它们通常是性能瓶颈的根源。
    • Call Tree (调用树) 视图:
      • 以调用层级的树状结构展示任务,帮助你理解函数的调用关系。
    • 联动高亮: 这些视图是相互联动的。当你在一个视图(如 Bottom-up)中选中一个函数时,主时间线上的对应任务块也会被高亮显示。

26-performance-profiling-exercise

  • 练习目标
    • 对一个包含明显卡顿动画的页面进行性能分析。
    • 对比其“未优化”和“已优化”版本下的性能表现差异。
    • 目标是熟悉性能分析工具的使用,而不是深入理解动画优化的具体代码。
  • 性能分析过程
    1. 分析未优化版本:
      • 打开 DevTools 的 Performance 面板,录制几秒钟的动画。
      • 观察火焰图:
        • 可以看到大量的红色标记(长任务)和红色帧(掉帧),直观地确认了性能问题的存在。
        • 主线程被大块的黄色 (Scripting) 任务占据,说明性能瓶颈是 CPU 密集型的 JavaScript 计算。
        • 通过观察调用栈,可以定位到耗时最长的函数是 moveBalls
      • 查看源码: 点击 moveBalls 跳转到源码,可以看到它在循环中进行了大量的读写操作,导致了布局抖动 (Layout Thrashing)
    2. 分析优化版本:
      • 点击页面上的 "Optimize" 按钮,然后再次录制性能。
      • 观察火焰图:
        • 黄色的任务块变得显著变窄,执行时间大大缩短。
        • 红色标记和红色帧大幅减少,甚至消失。
        • 动画变得流畅。
    3. 对比分析:
      • 最直观的方式是进行一次“混合录制”:先录制未优化版本,然后点击优化按钮,再继续录制优化版本。
      • 在最终的火焰图中,可以清晰地看到从宽大的黄色任务块到窄小任务块的突变,直观地证明了优化的效果。
  • 性能剖析文件的分享与协作
    • 导出与导入:
      • 你可以点击 Performance 面板上的下载按钮,将一次性能剖析(profile)保存为一个 .json 文件。
      • 团队中的其他人可以点击上传按钮,加载这个文件,从而看到和你完全一样的性能图表。
    • 应用场景:
      • 当一个 bug 难以复现时,可以让报告者录制一份性能剖析文件。
      • 在 GitHub issue 或内部工单中附上剖析文件,可以极大地帮助开发者定位问题。
  • 总结
    • 不管业务逻辑多复杂,性能分析的最终目标是找到瓶颈
    • 通过 Performance 面板,你可以将模糊的“我的应用很慢”转变为精确的陈述:“我的应用很慢,因为 moveBalls 函数的 CPU 占用过高,导致掉帧”。
    • 这种精确的诊断是进行有效优化的第一步。

27-identifying-memory-leaks

  • JavaScript 中的内存泄漏
    • JavaScript 是一种垃圾回收 (Garbage Collected) 语言,意味着开发者不需要手动分配和释放内存。
    • 然而,内存泄漏依然会发生。当代码中无意地持有了不再需要的对象的引用时,垃圾回收器就无法回收这些对象,从而导致内存占用持续增长。
  • 常见的内存泄漏模式
    1. 意外的全局变量:
      • 在非严格模式下,如果忘记使用 var, let, const 声明变量,该变量会被创建为全局变量(挂载到 window 对象上),从而永远不会被回收。
    2. 被遗忘的闭包:
      • 闭包会使其外部函数的作用域保持活动状态。如果在闭包中引用了一个外部作用域的大对象,即使这个大对象在其他地方已不再需要,它也会因为闭包的存在而无法被回收。
    3. 被遗忘的事件监听器:
      • 如果为一个 DOM 元素添加了事件监听器,但在该元素被移除后没有显式地移除这个监听器,那么监听器本身以及它闭包中引用的任何变量(包括那个 DOM 元素)都将无法被回收。
    4. 被遗忘的定时器:
      • setIntervalsetTimeout 如果没有被 clearIntervalclearTimeout 清除,它们的回调函数以及回调函数所引用的作用域将一直存在于内存中。
    5. 分离的 DOM 节点 (Detached DOM nodes):
      • 当你在 JavaScript 中创建了一个 DOM 元素并将其保存在一个变量中,然后又从 DOM 树中移除了这个元素,但没有清除对它的 JavaScript 引用时,这个元素节点虽然在页面上看不到了,但它仍然存在于内存中。
  • 框架提供的解决方案
    • 现代框架(如 Angular, React)提供了生命周期钩子来帮助管理这些问题。
    • 例如,在 Angular 的 ngOnDestroy 或 React useEffect 的返回函数中,是清理事件监听器、定时器等资源的最佳时机。这是编写高性能、健壮组件的关键实践。

28-understanding-garbage-collection

  • 如何初步判断是否存在内存泄漏
    1. Chrome 任务管理器 (Task Manager):
      • 路径: Chrome 菜单 -> 更多工具 -> 任务管理器。
      • 用法:
        • 右键点击表头,确保勾选了 "JavaScript memory" (JavaScript 内存)。
        • 观察你的应用标签页,在它处于静止状态 (steady state) 时,其 JavaScript 内存占用应该保持稳定。
        • 如果内存占用在无任何操作的情况下持续增长,这强烈暗示着存在内存泄漏。
    2. Performance 面板的内存记录:
      • 用法: 在运行性能剖析时,勾选 "Memory" 复选框。
      • 结果: 录制完成后,你会在性能图表中看到一个内存占用随时间变化的图表 (JS Heap)
      • 健康模式: 内存占用呈现锯齿状,即内存使用量上升,然后垃圾回收器运行时下降,总体基线保持平稳。
      • 泄漏模式: 内存占用的基线持续上升,每次垃圾回收后,内存占用都比上一次回收后的更高。这形成了所谓的**“锯齿上升”**模式,是内存泄漏的典型特征。
  • 内存泄漏源分析
    • 内存图表不仅显示总内存,还能细分出不同类型的内存占用,如:
      • JS Heap (JavaScript 堆)
      • Documents (文档)
      • Nodes (DOM 节点)
      • Listeners (事件监听器)
      • GPU Memory (GPU 内存)
    • 通过观察是哪种类型的内存在持续增长,可以帮助你缩小排查范围。例如,如果 Nodes 持续增长,很可能是分离的 DOM 节点问题。

29-memory-heap-snapshots

  • Memory (内存) 面板
    • 这是用于深入分析内存问题的核心工具。
    • Heap snapshot (堆快照) 是其主要功能,它能捕获某一时刻 JavaScript 堆中所有对象的完整快照。
  • 关键概念:Shallow Size vs Retained Size
    • 这与性能分析中的 Self Time/Total Time 类似。
    • Shallow Size (浅层大小): 对象自身占用的内存大小。
    • Retained Size (保留大小): 如果该对象被垃圾回收,能够被释放的总内存大小。这包括了该对象自身,以及那些仅被该对象引用的其他对象。
    • 排查技巧: 排序时应重点关注 Retained Size 大的对象,因为它们是内存占用的主要“罪魁祸首”。
  • 垃圾回收 (GC) 基础:标记-清除 (Mark-and-Sweep)
    • JavaScript 引擎会定期进行垃圾回收。
    • 它从一组“根”对象(如全局 window 对象)开始,遍历所有可达的对象,并标记 (Mark) 它们。
    • 遍历结束后,所有未被标记的对象都被认为是“不可达”的垃圾,引擎会清除 (Sweep) 它们并回收内存。
    • 内存泄漏的本质就是,不再需要的对象因为仍被某个可达对象意外引用,导致它在标记阶段被错误地标记为“可达”,从而无法被回收。
  • 最有效的内存泄漏排查工作流
    1. 捕获基线快照: 打开应用,进入一个稳定状态,然后点击 "Take snapshot",捕获第一个堆快照 (Snapshot 1)。
    2. 执行可疑操作: 在应用中执行你怀疑会导致内存泄漏的操作(例如,反复打开和关闭一个弹窗)。
    3. 捕获最终快照: 操作完成后,再次点击 "Take snapshot",捕获第二个堆快照 (Snapshot 2)。
    4. 进行对比 (Comparison):
      • 在 Memory 面板的视图选择器中,选择 "Comparison" (对比)。
      • 将对比范围设置为 "Snapshot 2" 与 "Snapshot 1"。
    • 分析对比结果:
      • 这个视图只会显示两个快照之间的差异,即在你的操作过程中新增的对象。
      • 这极大地减少了噪音,让你能专注于分析泄漏的对象。
      • Size Delta (大小增量) 排序,可以快速找到增长最快的对象类型。
  • 挑战:从快照到源代码
    • Memory 面板能精准地告诉你什么类型的对象在泄漏(例如,HTMLDivElementArray),以及泄漏了多少。
    • 但是,它通常无法直接把你链接到导致泄漏的那一行具体的源代码。
    • 下一步工作: 你需要根据泄漏的对象类型,结合你的操作流程,去代码中进行推理和排查。例如,如果发现 HTMLDivElement 在泄漏,你就要去检查在你的操作中,哪些代码创建了 div 元素但可能没有正确地清理它们。

30-memory-leak-exercise

  • 练习目标
    • 使用前面学到的工具(任务管理器, Performance 面板, Memory 面板)来分析一个存在内存泄漏的页面。
    • 目标是熟练运用这些工具来识别和量化内存泄漏,而不是必须找到导致泄漏的具体代码行。
  • 分析过程回顾
    1. 使用任务管理器:
      • 打开 Chrome 任务管理器。
      • 反复点击页面上的 "Add items" 按钮。
      • 观察到该页面的 JavaScript 内存占用显著且持续地增长。初步确认存在泄漏
    2. 使用 Performance 面板:
      • 勾选 "Memory" 选项并开始录制。
      • 反复点击 "Add items" 按钮。
      • 停止录制后,观察到 JS Heap 图表呈现出典型的**“锯齿上升”**模式,即每次垃圾回收后,内存基线都比上一次要高。进一步确认泄漏,并定位到泄漏源是 JS Heap
    3. 使用 Memory 面板进行堆快照对比:
      • 拍摄第一个快照作为基线。
      • 反复点击 "Add items" 按钮。
      • 拍摄第二个快照。
      • 切换到 "Comparison" 视图,对比两个快照。
      • 分析结果:
        • 发现两次快照之间新增了大量的 (array) 对象。
        • 展开这些数组,可以看到它们包含了大量的性能条目 (PerformanceEntry)。
        • 推断: 每次点击按钮时,代码都在创建一个巨大的数组并将其存储在某个地方,而没有释放旧的数组。
  • 关于真实用户监控 (RUM) 和异步代码
    • RUM for Memory: 目前主流浏览器没有提供直接的 API 让网站可以获取当前精确的 CPU 或内存使用情况。因此,现有的 RUM 工具通常只能通过一些间接指标(如 DOM 节点数量)来估算内存状况,但无法做到像 DevTools 那样精确。
    • Promises 与内存泄漏: 异步代码(如 Promises)本身不会让内存泄漏更难追踪。无论代码是同步还是异步,只要对象被保留在内存中,堆快照就能捕获到它们。

总结: 这个练习流程(任务管理器 -> 性能面板 -> 内存快照对比)是一个从宏观到微观、逐步深入的黄金工作流,用于系统地诊断和分析前端内存泄漏问题。

31-experimental-features-ai

  • Chrome DevTools 实验性功能 (Experiments)
    • 访问方式: DevTools 设置 -> Experiments 标签页。
    • 内容: 这里包含了大量处于开发阶段的新功能。它们可能不稳定,甚至会改变或被移除。
    • 示例:
      • Font Editor (字体编辑器): 启用后,可以在 Styles 面板中获得一个专门用于调整字体属性(如 font-family, font-size, fallback 字体)的 UI。
      • Full accessibility tree: 提供一个更完整的无障碍树视图。
    • 保持更新: 对于想了解 DevTools 最新动态的开发者来说,定期查看实验性功能和关注 developer.chrome.com 上的 "New in DevTools" 系列博客是很好的方式。
  • AI 创新功能
    • 访问方式: DevTools 设置 -> AI innovations,需要手动开启。
    • 目前主要包含两个功能:
    1. Console Insights (控制台洞察):
      • 功能: 当控制台出现错误时,旁边会多出一个“用 AI 理解此错误”的按钮。
      • 效果: AI 会尝试解释错误发生的原因,并给出可能的修复建议。
      • 评价: 目前还比较初级,有时解释很啰嗦,给出的修复方案也可能不完全正确,但可以作为一个获取初步思路的辅助工具。
    2. AI Assistant in Elements Panel (元素面板中的 AI 助手):
      • 功能: 在 Elements 面板的 Styles 窗格中,会出现一个 AI 助手按钮(星状图标)。
      • 核心优势: 上下文感知 (Context-aware)。当你打开 AI 助手时,它已经知道了你当前选中的是哪个 DOM 元素。
      • 应用示例:
        • 选中一个列表项 (<li>),然后向 AI 提问:“为什么我的项目符号离文本那么远?怎么让它们更近一点?”
        • AI 能理解你的意图,并结合当前元素的上下文,给出正确的 CSS 解决方案 (list-style-position: inside;)。
      • 危险但有趣的功能: AI 的建议旁边会附带一个可执行的代码片段,你可以一键复制到控制台来应用这个修改。
      • 扩展应用: 这个 AI 助手也可以用于解释性能问题。例如,在 Performance 面板中选中一个耗时很长的函数,可以右键询问 AI:“为什么这个函数这么慢?” AI 可能会分析出存在布局抖动等问题,并给出优化建议。
  • 总结
    • DevTools 正在积极地集成 AI 能力。
    • 目前来看,最实用的 AI 功能是其强大的上下文感知能力,能显著提升 CSS 调试和性能问题理解的效率。

32-wrapping-up

  • 浏览器 DevTools 的差异
    • Chromium 系: Chrome, Edge, Brave, DuckDuckGo 等浏览器都使用 Chromium 内核。因此,它们的开发者工具基本完全相同,可能只存在版本上的微小差异。
    • Firefox: 拥有自己独立开发的、功能强大的开发者工具。
    • WebKit 系: Safari 和 Opera 使用 WebKit 内核,它们的开发者工具 (Web Inspector) 是一套。
  • 关于代码覆盖率 (Coverage) 分析
    • 问题: 是否可以汇总多个页面的代码覆盖率数据?
    • 答案:
      • Coverage 标签页: 不行。这个标签页只显示当前页面的覆盖率。
      • Performance 面板: 可以实现。
        • 开始一次性能录制。
        • 在录制期间,依次访问你想要分析的所有页面。
        • 停止录制后,在录制结果中可以看到整个过程中所有脚本和样式的代码覆盖率信息。
  • 感谢与结语
    • 讲师感谢所有参与者和提出的问题。