
GeoLibre PWA缓存策略解析Service Worker如何管理多引擎离线化【免费下载链接】GeoLibreA lightweight, cloud-native GIS platform for visualizing, exploring, and analyzing geospatial data. It runs in the web browser, on the desktop, on mobile, and inside Jupyter notebooks.项目地址: https://gitcode.com/GitHub_Trending/ge/GeoLibreGeoLibre 是一款轻量化、云原生的 GIS 平台能在浏览器、桌面、移动端和 Jupyter 笔记本中可视化、探索与分析地理空间数据。本文深入解析它的PWA 缓存策略Service Worker 如何通过预缓存应用外壳 运行时按需缓存的双层结构把 MapLibre、Cesium、DuckDB-WASM、PGlite、Pyodide 等多个重型地图引擎变成可离线使用的能力并教你如何为离线地图区域做瓦片预热。为什么 Web GIS 的离线化很难一个典型的 Web GIS 应用启动时要加载的东西远超普通网站引擎体积加载时机MapLibre2D 地图核心约 13 MB首次渲染地图时CesiumJS3D 地球约 4.6 MB切换 3D 视图时DuckDB-WASM 空间扩展数 MB执行 SQL 分析时PGlite PostGIS 扩展约 18.8 MB选择 PostGIS 引擎时PyodidePython 运行时数 MBCDN打开 Python 面板时如果把这一切都塞进首次访问的预缓存首屏会膨胀到几十 MB完全不可用。GeoLibre 的解法在 vite.config.ts 中有非常清晰的注释说明Service Worker 预缓存应用外壳HTML 启动地图必需的 JS/CSS而重量级、按需拉取的引擎二进制定则用哈希键控的 CacheFirst 策略在运行时缓存——功能只需在线用一次之后即可离线同时不膨胀首次访问的预缓存。第一层预缓存应用外壳Precache构建时由 vite-plugin-pwaWorkbox生成sw.js预缓存规则如下缓存范围**/*.{js,css,html,woff,woff2}即外壳 字体单文件上限4 MBmaximumFileSizeToCacheInBytes自动清理cleanupOutdatedCaches在每次部署后清掉旧缓存立即接管skipWaiting clientsClaim让新 Worker 立即控制页面。关键在HEAVY_PRECACHE_IGNORESvite.config.ts#L931-L977它把重货全部排除在预缓存外被忽略的资产原因maplibre-*、duckdb-*等特性块太大改为运行时 CacheFirst*.wasm/*.data引擎二进制首次使用才拉取jupyterlite/**约 70 MB有自己作用域在/jupyterlite/的独立 Service Workerplugins/**运行时插件走 fetch → blob 导入路径i18n-locale-*.js15 个非英文语言包按需加载英文保留在预缓存中这里有个容易踩的坑CSS 也会被manualChunks规则误并入重型插件块从而把 DuckDB、Earth Engine 等拖进离线关键启动图导致冷离线重载时外壳永远挂载不了。项目在 vite.config.ts#L521-L549 中专门把样式文件与 JS 分块处理保证离线路径干净。第二层运行时 CacheFirst——三大缓存桶真正的多引擎离线化发生在运行时缓存规则里vite.config.ts#L1035-L1104共三个命名缓存1️⃣geolibre-assets同源引擎二进制匹配/assets/下的js/css/wasm/data/woff2上限 300 条、保留 30 天。因为 Vite 对产出文件做内容哈希重新部署会生成全新 URL旧条目永远不会被误当作最新版——这正是 CacheFirst 可以安全使用的原因。DuckDB-WASM 的空间扩展、MapLibre 特性插件都靠这条规则实现用一次永久离线。2️⃣geolibre-cdn-engines跨域 CDN 引擎PyodidePython、PGlite/PostGIS、CereusDBSedonaWASM 从 jsDelivr 以版本锁定 URL加载上限 400 条。URL 里嵌着精确版本号升级即新 URL同样规避陈旧缓存问题。⚠️ 注意首次使用这些引擎仍需要网络——这是文档中明确说明的边界详见 docs/architecture.md。3️⃣geolibre-basemaps底图瓦片只匹配 CORS 友好的默认底图主机OpenFreeMap / CARTO上限特意放宽到8000 条——因为下载离线区域功能会一次性预热整个区域的瓦片上限太小会把自己刚缓存的瓦片挤出去。离线区域下载让瓦片路过Service Worker普通用户最关心的功能——下载某个地图区域供离线查看——实现在 offline-tiles.ts 中它的设计非常巧妙它不直接写 Cache Storage API因为生成的 Workbox Worker 只响应自己路由写入的缓存。正确姿势是应用发起普通fetch()请求穿过 Service Worker命中geolibre-basemaps的 CacheFirst 路由后被自动存入。整个流程拆解瓦片枚举lngLatToTile 把经纬度转 XYZ 瓦片坐标tileRangeForBbox 算出每个缩放层的瓦片矩形细节处理自动拆分穿越反经线的地图太平洋视图、把请求缩放范围钳制到底图实际覆盖范围——避免请求超出底图 maxzoom 后整批 404clampZoomRange共享资产除瓦片外还预热 sprite 图标1x/2x与字体字形 PBF——不预热字形离线时地图标签根本不会显示collectStyleAssetUrls并发预热warmUrls 以默认 6 路并发拉取单请求超时计入失败而非中断全局失败瓦片可单独重试失败项支持 AbortSignal 随时取消。缓存键的一致性也有讲究字形 URL 中{fontstack}的替换刻意不做百分号编码以与 MapLibre 实际发出的请求完全一致否则 Service Worker 的缓存键就对不上预热白做。更新与失效如何不自刷新页面GeoLibre 采用autoUpdate模式但刻意把 Workbox 默认的强制刷新做成了空操作main.tsx#L208-L243新 Worker 激活后立即接管页面新预缓存服务后续所有请求页面恢复交给 stale-chunk-reload.ts只有某个已被新版删除的惰性块真正 404 时才按需重载——用户的地图状态和项目会话得以保留杜绝页面自己刷新自己的诡异现象。开发模式下 Service Worker 被整体禁用devOptions.enabled: false避免干扰 HMR离线行为只针对生产构建验证。如何用自动化测试验证离线能力e2e/pwa.spec.ts 是一份很好的参考它验证了完整的离线链路检查 manifest 可安装性192px 512px 图标、standalone显示等待 Service Worker 接管后在线刷新一次——首访时重型块是在 Worker 接管前拉取的绕过缓存轮询performance资源列表确认每个启动资产都已持久化进 Cache StorageWorker 的运行时写入是异步的画布可见≠缓存完成setOffline(true)断网冷启动验证地图画布依然渲染。小结三句话记住这套策略层次策略覆盖内容预缓存构建时生成修订号键控应用外壳HTML 启动 JS/CSS 字体运行时 CacheFirst哈希/版本锁定 URL首用即缓存DuckDB、Cesium、PGlite、Pyodide 等引擎区域预热普通 fetch 穿过 SW 写入缓存底图瓦片 图标 字形GeoLibre 的 PWA 缓存策略本质上是一套**外壳必缓存、重货按需缓存、瓦片可预热**的分级体系。多引擎不是被全部塞进缓存而是各自在首次使用时路过Service Worker 落袋为安——这正是复杂 Web GIS 应用离线化的可复用范本。更多架构细节可参考官方文档docs/architecture.md、docs/getting-started.md【免费下载链接】GeoLibreA lightweight, cloud-native GIS platform for visualizing, exploring, and analyzing geospatial data. It runs in the web browser, on the desktop, on mobile, and inside Jupyter notebooks.项目地址: https://gitcode.com/GitHub_Trending/ge/GeoLibre创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考