第 04 节 · 浏览器开发者工具
下载源码包 ⭳第 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 的瓦片请求分析上。
学完本节能做到:
- 说出四个常用面板各自负责什么
- 在一张地图页面上抓出瓦片请求,读出 z/x/y、状态码、大小、耗时
- 解释
200/304/403/404在地图场景中各代表什么 - 用 Console 执行 JS 并读取结果,把报错原文连同文件行号交给 AI 或搜索引擎
- 会用 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
三种打开方式:
- 按
F12,或Ctrl+Shift+I - 页面右键 → 检查
- 浏览器菜单 → 更多工具 → 开发者工具
DevTools 可以停靠在页面右侧、底部,也可以独立成窗口;地图页面建议停靠右侧,方便一边看地图一边看请求。注意一个习惯:先在 Network 面板开着的情况下刷新页面,因为面板只记录打开之后发生的请求。
4.2 Elements:看结构和样式
左侧是 DOM 树,也就是 HTML 的实时结构;右侧是选中元素的样式、布局与盒模型。
三个入门动作:
- 点左上角箭头(快捷键
Ctrl+Shift+C)后点页面上的任意元素,自动跳转到对应 DOM 节点 - 在 Styles 里改任意 CSS 值,页面立即变化;刷新后恢复,适合安全实验
- 看 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 是调试器。基本流程:
- 左侧文件树找到目标 JS 文件,或按
Ctrl+P按文件名搜索 - 点击行号设置断点,行号旁出现蓝色标记
- 刷新页面或触发点击,代码执行到断点时暂停
- 右侧面板查看数据:
- 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 做第一次地图调试。
练习步骤
- 在 VS Code 中打开解压后的
04-devtools-map/,编辑index.html,右键选择 Open with Live Server;直接双击index.html用浏览器打开也可以,两者都能看到地图。 - 按
F12打开 DevTools,切到 Network,勾选 Disable cache,刷新页面。 - 在过滤器里点 Img,再看页面加载后的请求列表,几十个瓦片请求已经排在里面。
- 拖动地图、放大缩小,观察新请求不断进入列表。
- 点开一个请求,在 Headers 中看完整 URL,找
x、y、z三个查询参数,对照地图当前位置,理解编号与位置的关系。 - 把过滤切到 All,找 Leaflet 本地脚本请求,确认页面加载的
lib/leaflet/dist/leaflet.js来自本地而不是 CDN。 - 切到 Console,执行
document.querySelectorAll('img').length,和 Network 里的瓦片数量对照。 - 在 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: '© 高德地图' }
).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] 附近,继续观察坐标与底图的关系。每次只改一行,保存后用强刷查看结果。
七、自测题
- 瓦片 URL 里
z、x、y分别表示什么?为什么一张地图加载时会同时出现几十个瓦片请求? - 状态码
200、304、403、404在地图场景里分别对应什么情况? - 为什么勾选 Disable cache 后再刷新,能更清楚地看到请求?
- Sources 断点停下来后,想看“当前变量值”和“代码怎么执行到这里”,分别看哪个区域?
- Console 里直接执行
map.getZoom()需要什么前提?在后续 Vite 的模块化项目里为什么不一定能用?
参考答案
z是缩放级别,x是列号,y是行号;视口跨越多个瓦片格子,浏览器只拉取覆盖当前视口的那一批,所以一次加载几十张。200瓦片成功返回;304内容未变化,浏览器沿用缓存;403服务拒绝访问,通常是 key 或域名白名单问题;404该级别或该位置没有这张瓦片,可能是超过最大级别或地址写错。- 浏览器会复用本地缓存,命中后不再发请求;禁用缓存后每次拖动都能看到真实请求,便于分析 URL 组成。
- 变量值看 Scope(或 Watch),调用来源看 Call Stack。
- 前提是当前页面上下文里存在全局
map变量;普通<script>全局声明可以直接访问,模块化项目的模块变量不在全局作用域,需要先导出或在合适位置调试。
八、下一步
单文件练习能看清页面结构,但项目会越写越多:多个页面、模块化 JS、共享样式、第三方库。手写一堆 HTML 并靠复制粘贴维护,很快失控 → 第 05 节:Vite 快速上手,把单文件接进开发服务器与构建流水线。