用免费地图给卡帕多奇亚民宿做预订页,被瓦片加载拖垮了

卡帕多奇亚的民宿老板想要个预订页,能拖动地图看位置,这个需求很合理。我接了这个外包单,用 Leaflet + OpenStreetMap 瓦片,本地开发时地图加载很快,拖动也流畅。但部署到线上后,用手机 4G 打开,瓦片加载慢得像挤牙膏,整张地图空白了三四秒,用户早滑走了。

我的做法是用 Leaflet 的 tileLayer 加缓存和预加载。先设置 updateWhenIdle: true,让拖动时不在每一帧都请求瓦片,减少请求数量。然后加 keepBuffer: 4,预加载可视区域外 4 个瓦片,这样拖动时不会出现大片空白。关键代码片段:

const map = L.map('map', {
  center: [38.6431, 34.8289],
  zoom: 13,
  updateWhenIdle: true,
  keepBuffer: 4
});

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  maxZoom: 19,
  attribution: '© OpenStreetMap'
}).addTo(map);

另外,我用了 L.tileLayer 的 crossOrigin: true 配合 Service Worker 缓存瓦片,但 Service Worker 的缓存策略要谨慎,不然瓦片更新不了。最后我选择用 Workbox 的 StaleWhileRevalidate,先返回缓存,后台更新。这样二次访问时,瓦片基本秒开。

为什么这样做?updateWhenIdle 让 Leaflet 等到拖动结束再加载瓦片,牺牲了一点实时性,但大幅减少请求数;keepBuffer 用内存换流畅度,代价是初次加载多请求一些瓦片,但用户拖动时不会看到空白。Service Worker 缓存是双刃剑,如果瓦片更新频繁,用户可能看到旧地图,但对民宿位置展示来说,地图变化不大,可以接受。

哪里会失效?如果用户在弱网环境下首次访问,Service Worker 还没缓存,瓦片依然会慢,这时需要加个 loading 骨架屏,别让用户盯着空白。还有,OpenStreetMap 的瓦片服务器有使用政策,大量请求可能被限流,尤其是做商业项目时,最好换成 Mapbox 或自建瓦片。我踩过的坑是:一开始没设 maxZoom,用户放大到 20 级,瓦片 404,地图一片灰,被老板吐槽“你们这地图怎么是破的”。

结尾问一句:你们在做地图类页面时,是怎么平衡首次加载速度和拖动流畅度的?有没有更轻量的方案?

0
赞同度 100% · 0 条评论 · 7 阅读

0 条评论

支持 Markdown · 回复会实时推送给对方

还没有评论,写下第一条。