经纬志
首页 / 实战手册 / 瓦片

瓦片返回 204 而不是 404,地图上是一片透明白块

先看结论

网络面板里全是 204,看着像「没有错误」,可地图上缺了一大片。

最后验证 2026-11-03 · 多技术栈 · 更新 2026-10-29 · 引用本文

现象

某个自建瓦片服务在数据范围外返回 204 No Content。 地图上该区域是纯白(背景色透出),没有灰块,也没有任何报错。

tileerror 监听器一次都没触发,页面的「底图加载失败」提示不会出现。 排查时只看错误数量会误判成「一切正常」。

原因

浏览器的图片加载逻辑只区分「成功」与「失败」。 204 属于 2xx,被视为成功响应,但响应体长度为 0, 没有可解码的像素。Leaflet 为这张瓦片创建了 img, load 事件照常触发(部分浏览器会触发 error,行为不一致), 图片本身是空白的。

状态码图片能否解码Leaflet 行为
200 + image/png能正常显示
204不能不报错,留白
404不能触发 tileerror
200 + text/html不能部分浏览器触发 error

排查过程

  1. 在网络面板按状态码筛选,看是否有大量 204 或 200 但响应体为 0 字节的请求。
  2. 看响应头 Content-Type 与 Content-Length。
  3. 在 tileload 事件里检查 e.tile.naturalWidth,为 0 即空图。
  4. 确认瓦片服务的空值策略:是返回 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, '空瓦片仍未被识别');

适用版本

组件版本说明
Leaflet1.9.x仅 4xx/5xx 与解码失败触发 tileerror
OpenLayers9.xtileloaderror 同样不覆盖 204
Nginx1.20 及以上try_files ... =404 可改变默认状态码
引用本文

经纬志(2026)。《瓦片返回 204 而不是 404,地图上是一片透明白块》。https://www.jingweizhi.com/cookbook/tile-204-blank.html(访问日期 2026-11-03)。