首页 / 实战手册 / 瓦片
瓦片返回 204 而不是 404,地图上是一片透明白块
先看结论
网络面板里全是 204,看着像「没有错误」,可地图上缺了一大片。
现象
某个自建瓦片服务在数据范围外返回 204 No Content。
地图上该区域是纯白(背景色透出),没有灰块,也没有任何报错。
tileerror 监听器一次都没触发,页面的「底图加载失败」提示不会出现。
排查时只看错误数量会误判成「一切正常」。
原因
浏览器的图片加载逻辑只区分「成功」与「失败」。
204 属于 2xx,被视为成功响应,但响应体长度为 0,
没有可解码的像素。Leaflet 为这张瓦片创建了 img,
load 事件照常触发(部分浏览器会触发 error,行为不一致),
图片本身是空白的。
| 状态码 | 图片能否解码 | Leaflet 行为 |
|---|---|---|
| 200 + image/png | 能 | 正常显示 |
| 204 | 不能 | 不报错,留白 |
| 404 | 不能 | 触发 tileerror |
| 200 + text/html | 不能 | 部分浏览器触发 error |
排查过程
- 在网络面板按状态码筛选,看是否有大量 204 或 200 但响应体为 0 字节的请求。
- 看响应头
Content-Type与Content-Length。 - 在
tileload事件里检查e.tile.naturalWidth,为 0 即空图。 - 确认瓦片服务的空值策略:是返回 204、返回透明 1×1 PNG,还是返回 404。
layer.on('tileload', e => {
if (e.tile.naturalWidth === 0) console.warn('空瓦片', e.coords, e.tile.src);
});
// 204 的瓦片会打出警告,而 tileerror 不会触发
解决方案
服务端把空瓦片的语义改成 404,前端才能感知;
或者统一返回一张透明 PNG,让视觉上保持一致。
# Nginx:空目录不再返回 204,而是 404
location /tiles/ {
try_files $uri =404;
}
# 若希望缺图时不破坏画面,返回 1×1 透明 PNG
location /tiles/ {
try_files $uri /blank.png;
add_header Cache-Control "public, max-age=86400";
}
前端也要能识别空图,不能只依赖 tileerror。
let blanks = 0;
layer.on('tileload', e => {
if (e.tile.naturalWidth > 0) return;
if (++blanks === 5) showTip('当前范围暂无底图数据');
});
验证
改完后空瓦片请求返回 404,tileerror 正常触发;
或返回透明 PNG,naturalWidth 为 256,画面无白块。
console.assert(e.tile.naturalWidth === 256 || errors > 0, '空瓦片仍未被识别');
适用版本
| 组件 | 版本 | 说明 |
|---|---|---|
| Leaflet | 1.9.x | 仅 4xx/5xx 与解码失败触发 tileerror |
| OpenLayers | 9.x | tileloaderror 同样不覆盖 204 |
| Nginx | 1.20 及以上 | try_files ... =404 可改变默认状态码 |
经纬志(2026)。《瓦片返回 204 而不是 404,地图上是一片透明白块》。https://www.jingweizhi.com/cookbook/tile-204-blank.html(访问日期 2026-11-03)。