←返回笔记列表
01 · NOTES / WebGIS 开发

第 04 节 · 浏览器开发者工具

下载源码包 ⭳
2026 年 9 月 6 日

第 04 节 · 浏览器开发者工具

📌 版本信息:以 Chrome/Edge 最新稳定版为准(两者同为 Chromium 内核,DevTools 界面一致;2026-09-06 核对,本机 Edge 13x) 📚 来源:Chrome DevTools 官方文档 | 高德地图开放平台 | Leaflet 快速开始 🖥️ 配套练习:04-devtools-map.html,使用本地 Leaflet 1.9.4 + 高德栅格瓦片,单文件双击或 Live Server 均可打开。

一、追一次瓦片请求

打开配套练习页,屏幕上看到的是一张可以拖动、缩放的地图。从应用视角看,它像一整张连续的地图;把视角切到 Network 面板,它其实由几十个小请求拼成。

拖动地图或缩放级别时,浏览器不断申请新的小图片、丢弃离开视口的旧图片。地图服务收到的是这样的请求:

https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x=843&y=388&z=10

x=843&y=388&z=10 是这张小图在地图金字塔里的编号。这一节要做的事,就是把“一张地图是怎么拼出来的”这个过程拆开看:抓一次真实请求,读明白编号、状态码、缓存与失败原因。这是 WebGIS 调试的第一项硬功夫。

二、这一节讲什么,学完能做什么

本节以一张最简单的 Web 地图为对象,过一遍浏览器开发者工具的 Elements、Console、Network、Sources 四个面板,重点落在 Network 的瓦片请求分析上。

学完本节能做到:

  1. 说出四个常用面板各自负责什么
  2. 在一张地图页面上抓出瓦片请求,读出 z/x/y、状态码、大小、耗时
  3. 解释 200 / 304 / 403 / 404 在地图场景中各代表什么
  4. 用 Console 执行 JS 并读取结果,把报错原文连同文件行号交给 AI 或搜索引擎
  5. 会用 Sources 打断点,观察当前变量值和调用来源

三、核心概念

3.1 网页是 HTML、CSS、JS 与网络请求的组合

浏览器加载一个页面,先拿到一份 HTML,再把 HTML 里引用的 CSS、JS、图片等资源全部拉下来。JS 运行后还常常发起新请求:地图瓦片、GeoJSON 数据、图片、接口。所以“页面性能差”“地图加载慢”“某块区域空白”这类问题,最后几乎都要落到网络请求上排查。

DevTools 把页面切成四个观察角度:

面板 看什么 典型问题
Elements 页面结构(DOM)与样式 为什么这个元素不显示、样式没生效
Console 运行日志与可在页面上下文执行的 JS 哪行代码报错、某个值现在是什么
Network 所有网络请求 什么资源没加载、状态码、耗时、缓存
Sources 正在执行的代码 程序走到哪一步、变量值和调用链

3.2 瓦片:地图的最小积木

在线底图服务把全球地图按“金字塔”切成固定大小的图片,每张称为一个瓦片(tile),通常是 256×256 像素。缩放级别 z 决定全球地图被切成多少块:在第 z 级,整个地图有 2^z × 2^z 个格子,x 是列号,y 是行号。

z=1      全球被切成 2×2  = 4 张瓦片
z=2      4×4  = 16 张
z=10     1024×1024 = 约 100 万张候选,浏览器只请求视口内的几十张

类比地图集分幅:把世界地图按同样的网格切成同样大小的页面,想看哪一页就请求哪一页;级别越高,页面切得越多,每一页覆盖的范围越小、细节越多。

高德、天地图、OpenStreetMap 等在线底图服务本质都是“按瓦片编号提供 HTTP 图片”的服务,参数写法不同,思想相同。标准化的瓦片服务还会用 WMTS、XYZ 等协议描述,后续模块细讲。

3.3 状态码:服务器对请求的答复

HTTP 状态码是服务器给浏览器的答复编号,看书看值即可:

状态码 含义 地图场景示例
200 成功返回 瓦片正常加载
304 内容没变,用缓存 浏览器再确认一次,服务器说“沿用旧文件”
403 禁止访问 服务需要 key,或 key 过期、域名未授权
404 找不到 该级别、该位置没有瓦片,或地址写错

浏览器还有一层本地缓存:同一张瓦片在有效期内不会重新下载。缓存策略集中在“为什么地图忽新忽旧”“几十分钟后瓦片是否还是旧的”这类问题里,第 18 节讲 HTTP 时会深入。

3.4 为什么网络视角对 WebGIS 特别重要

普通网页优化看接口与静态资源;地图页面里请求主体是瓦片。地图卡不卡、某块区域是空的、底图服务有没有失效,第一现场都在 Network。把“页面 = 资源请求集合”这个镜头练熟,后续分析 GeoJSON 加载、图层请求顺序、瓦片服务性能时,就有一致的分析路径。

四、面板逐个上手

4.1 打开 DevTools

三种打开方式:

  1. 按 F12,或 Ctrl+Shift+I
  2. 页面右键 → 检查
  3. 浏览器菜单 → 更多工具 → 开发者工具

DevTools 可以停靠在页面右侧、底部,也可以独立成窗口;地图页面建议停靠右侧,方便一边看地图一边看请求。注意一个习惯:先在 Network 面板开着的情况下刷新页面,因为面板只记录打开之后发生的请求。

4.2 Elements:看结构和样式

左侧是 DOM 树,也就是 HTML 的实时结构;右侧是选中元素的样式、布局与盒模型。

三个入门动作:

  1. 点左上角箭头(快捷键 Ctrl+Shift+C)后点页面上的任意元素,自动跳转到对应 DOM 节点
  2. 在 Styles 里改任意 CSS 值,页面立即变化;刷新后恢复,适合安全实验
  3. 看 Computed 和盒模型图,理解 margin、padding、border 对布局的影响

对地图页面来说,最常见的用法是选中地图容器,检查它是否真的拿到了预期高度;height: 0 是地图不显示的经典原因。

4.3 Console:命令行与报错台

Console 有两个任务:显示运行日志,接受在页面上下文中执行的 JS。

document.title                        // 返回当前标题:'l4 · 抓一次瓦片请求'
1 + 1                                 // 2,Console 本身就是 JS 运行环境
document.querySelectorAll('img').length  // 页面上当前图片数量

报错以红色显示,末尾通常带文件与行号链接,点击直达源码位置。黄色是警告,不一定致命,但要留意。地图调试中,Console 里常见两类操作:查全局变量(如 map.getZoom())和主动输出调试值(console.log(marker.getLatLng()))。

需要前提:被访问的变量必须存在于当前页面上下文。普通 <script> 里声明的全局变量可以直接访问;后续 Vite 项目的 ES Module 变量不会挂在全局,就要另想办法,这是第 05 节的伏笔。

4.4 Network:请求总览

这是本节的主面板。先认识工具条:

控件 作用
🔴 录制开关 停止录制后页面再发请求也不记录
🚫 清空 把列表清空,重新观察接下来的请求
Disable cache 禁用浏览器缓存,强制每次都向服务器要
过滤器 按 Img / JS / CSS / Fetch/XHR 等类型筛

一行请求的关键列:

列 含义 地图场景里的样子
Name 请求名 瓦片文件名或接口路径
Status 状态码 200 / 304 / 403 / 404
Type 资源类型 image(瓦片)、fetch(GeoJSON 等)
Size 传输大小 瓦片通常几 KB 到几十 KB
Time 耗时 瓦片慢了,地图就跟着转圈

点开任意一行,面板右侧显示详细内容:

  • Headers:完整请求 URL、请求头、响应头、查询参数
  • Preview:图片直接预览,JSON 数据直接查看
  • Timing:请求各阶段耗时,用于定位“网络慢还是服务器慢”

对瓦片,最常做的动作是:筛选 Img,点开一行,在 Headers 里看完整 URL,确认 x/y/z 与 Query String;拖动地图后回到列表,观察新增请求。

💡 判断一个请求是不是瓦片:过滤类型后,看 URL 里有没有类似 x/y/z 的分幅参数;高德、天地图、OSM 的参数名不同,但骨架一致。

4.5 Sources:断点调试

Sources 是调试器。基本流程:

  1. 左侧文件树找到目标 JS 文件,或按 Ctrl+P 按文件名搜索
  2. 点击行号设置断点,行号旁出现蓝色标记
  3. 刷新页面或触发点击,代码执行到断点时暂停
  4. 右侧面板查看数据:
    • Watch:手动添加要盯的表达式
    • Scope:当前作用域的所有变量值
    • Call Stack:代码是怎么一层层执行到这里的

工具栏上的 F10 单步执行下一行,F8 继续运行,F11 进入函数内部。

在练习页里的具体做法:在包含 L.marker(...) 的那一行设置断点,按 F5 刷新,程序会先建地图、加载瓦片,在断点处停住;此时 Scope 里能看到 map、tileLayer 等对象,Call Stack 能回答“这段代码由谁触发”。断点是“程序为什么没按预期走”的最直接证据。

五、易错点:为什么错,怎么办

现象 原因 解决
Network 里看不到瓦片请求 页面在面板打开之前已经加载,或录制被关掉 保持面板打开,勾选 Disable cache 后刷新页面
改了代码,刷新页面仍看不到变化 浏览器命中本地缓存 勾选 Disable cache,或 Ctrl+Shift+R 强刷
拖动地图时没有新请求 目标区域瓦片已缓存,服务端直接回 304 或浏览器本地直接命中 勾选 Disable cache 再看;想让 304 出现就取消 Disable cache
页面 A 正常、页面 B 瓦片全灰 底图服务对页面来源有限制,或 key 与域名不匹配 点开请求看 Status;403 就去服务商控制台检查 key、白名单与配额
图片只显示一半或一块缺失 个别瓦片 404 看缺失位置的请求 URL,核对级别是否超过服务上限
报错一串英文看不懂 报错信息里其实包含文件与行号 复制报错原文给 AI 或搜索,不要只复制“页面白屏”这种描述
觉得页面卡,但不知道卡在哪 只看了请求列表,没看加载顺序 用 Performance 面板录制分析,后续性能优化再展开

六、动手练习:抓一次真实的瓦片请求

配套文件:04-devtools-map.html(单文件练习,不需要安装任何包)

练习目标

亲眼看到一张地图由瓦片请求组成:读懂请求里的 z/x/y,用状态码解释加载结果,用 Console 和 Sources 做第一次地图调试。

练习步骤

  1. 在 VS Code 中打开解压后的 04-devtools-map/,编辑 index.html,右键选择 Open with Live Server;直接双击 index.html 用浏览器打开也可以,两者都能看到地图。
  2. 按 F12 打开 DevTools,切到 Network,勾选 Disable cache,刷新页面。
  3. 在过滤器里点 Img,再看页面加载后的请求列表,几十个瓦片请求已经排在里面。
  4. 拖动地图、放大缩小,观察新请求不断进入列表。
  5. 点开一个请求,在 Headers 中看完整 URL,找 x、y、z 三个查询参数,对照地图当前位置,理解编号与位置的关系。
  6. 把过滤切到 All,找 Leaflet 本地脚本请求,确认页面加载的 lib/leaflet/dist/leaflet.js 来自本地而不是 CDN。
  7. 切到 Console,执行 document.querySelectorAll('img').length,和 Network 里的瓦片数量对照。
  8. 在 Elements 里选中地图容器 #map,查看它的高度;再选中弹窗文字,观察 bindPopup 生成的 DOM 结构。

主要代码逐段看

const map = L.map('map').setView([39.9, 116.4], 10);

创建地图实例。L.map('map') 接收容器 id,.setView() 设置初始中心与缩放级别。参数顺序是 [纬度, 经度],与数学坐标里的 x/y 顺序相反。10 是缩放级别,也就是瓦片 URL 里的 z。

L.tileLayer(
  'https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
  { maxZoom: 18, subdomains: ['1', '2', '3', '4'], attribution: '&copy; 高德地图' }
).addTo(map);

tileLayer() 接收瓦片服务的 URL 模板。{z}、{x}、{y} 是占位符,Leaflet 会根据视口算出真实数字;{s} 对应 subdomains 数组里的值,把请求分散到 webrd01 到 webrd04 四个子域,绕开单个域名并发请求限制。maxZoom: 18 告诉地图这个服务最多支持到多少级;超出上限的请求会得到 404,这是易错点之一。addTo(map) 把底图图层挂到地图实例上。

L.marker([39.9042, 116.4074])
  .addTo(map)
  .bindPopup('你好,WebGIS!<br>这是第一个标记')
  .openPopup();

在地图上放一个点。bindPopup() 绑定点击时弹出的内容,HTML 标签在弹窗中会正常渲染;.openPopup() 让弹窗默认展开,方便在 Elements 里找到它。这个标记对应 GIS 里的“点要素”,后续模块会系统展开。

为什么用高德栅格瓦片,不用 OSM 官方瓦片

高德瓦片在国内直连快、免 key,适合学习环境;OSM 官方瓦片服务器在欧洲,国内首次拉取经常很慢,只适合与国外数据对照。底图的差异不影响本节目标:抓请求、看 z/x/y。另外,高德底图用的是 GCJ-02 坐标,与 Leaflet 默认的 WGS-84 坐标存在几百米偏移,所以如果标记位置看起来不完全贴路,这是正常现象,模块 05-leaflet 会专门处理坐标系。

💡 看到“标记偏离道路”先别急着改坐标,先确认底图坐标类型;坐标系问题在 WebGIS 里几乎是必踩的一课。

验收标准

  • Network 中出现一组 style=8&x=...&y=...&z=10 的图片请求
  • 能指着一个请求说出它对应地图的哪一小块,并读出 z/x/y
  • 能说出 200 与 404 的差别
  • 勾选 Disable cache 后继续拖动,能看到新增请求
  • Console 成功输出页面图片数量
  • 能解释本地 leaflet.js 与在线瓦片请求为什么不在同一个地址

可以自己试的修改

把 .setView([39.9, 116.4], 10) 改成 .setView([30.5728, 104.0668], 12),刷新后可以看到成都地区,并且 Network 里的 z 变成 12;把 Marker 坐标改成 [30.657, 104.066] 附近,继续观察坐标与底图的关系。每次只改一行,保存后用强刷查看结果。

七、自测题

  1. 瓦片 URL 里 z、x、y 分别表示什么?为什么一张地图加载时会同时出现几十个瓦片请求?
  2. 状态码 200、304、403、404 在地图场景里分别对应什么情况?
  3. 为什么勾选 Disable cache 后再刷新,能更清楚地看到请求?
  4. Sources 断点停下来后,想看“当前变量值”和“代码怎么执行到这里”,分别看哪个区域?
  5. Console 里直接执行 map.getZoom() 需要什么前提?在后续 Vite 的模块化项目里为什么不一定能用?

参考答案

  1. z 是缩放级别,x 是列号,y 是行号;视口跨越多个瓦片格子,浏览器只拉取覆盖当前视口的那一批,所以一次加载几十张。
  2. 200 瓦片成功返回;304 内容未变化,浏览器沿用缓存;403 服务拒绝访问,通常是 key 或域名白名单问题;404 该级别或该位置没有这张瓦片,可能是超过最大级别或地址写错。
  3. 浏览器会复用本地缓存,命中后不再发请求;禁用缓存后每次拖动都能看到真实请求,便于分析 URL 组成。
  4. 变量值看 Scope(或 Watch),调用来源看 Call Stack。
  5. 前提是当前页面上下文里存在全局 map 变量;普通 <script> 全局声明可以直接访问,模块化项目的模块变量不在全局作用域,需要先导出或在合适位置调试。

八、下一步

单文件练习能看清页面结构,但项目会越写越多:多个页面、模块化 JS、共享样式、第三方库。手写一堆 HTML 并靠复制粘贴维护,很快失控 → 第 05 节:Vite 快速上手,把单文件接进开发服务器与构建流水线。