← Retour aux issues

Tester la mise en cache des tuiles

publié le , mis à jour
Avatar Codeberg de laemlaem

Si notre MAJ des tuiles est prévisible, alors on peut les mettre en cache agressivement !

Itération avec Mistral :

I have a web map based on maplibre. It loads tiles with Protomaps : HTTP range requests on a big planet .pmtiles file. I'd like to provide offline tiles. I known that browsers are good at caching resources. How could I defined some tiles as "to be cached" so that the web interface loads without any internet connexion after a first download of those tiles ?


To ensure that your web map can load tiles offline after the initial download, you can leverage several web technologies and strategies. Here's a step-by-step guide to achieve this:

  1. Service Workers: Service workers are scripts that your browser runs in the background, separate from a web page, opening the door to features that don't need a web page or user interaction. One of the key features of service workers is the ability to intercept and handle network requests, which can be used to cache resources.

  2. Cache API: The Cache API provides a way to store network requests and their corresponding responses. You can use this API within your service worker to cache tiles as they are fetched.

  3. Strategy for Caching Tiles:

    • Installation: When the service worker is installed, you can cache essential resources.
    • Fetch Event: Intercept fetch events to cache new tiles as they are requested and serve cached tiles when offline.

Here's a basic example of how you might implement this:

// Service Worker script (sw.js)
const CACHE_NAME = 'my-tile-cache-v1';
const urlsToCache = [
  '/', // Add other essential resources here
];

self.addEventListener('install', event => {
  // Perform install steps
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => {
        console.log('Opened cache');
        return cache.addAll(urlsToCache);
      })
  );
});

self.addEventListener('fetch', event => {
  // Check if the request is for a tile
  if (event.request.url.includes('.pmtiles')) {
    event.respondWith(
      caches.match(event.request)
        .then(response => {
          // Cache hit - return response
          if (response) {
            return response;
          }

          // Clone the request
          const fetchRequest = event.request.clone();

          return fetch(fetchRequest).then(
            response => {
              // Check if we received a valid response
              if(!response || response.status !== 200 || response.type !== 'basic') {
                return response;
              }

              // Clone the response
              const responseToCache = response.clone();

              caches.open(CACHE_NAME)
                .then(cache => {
                  cache.put(event.request, responseToCache);
                });

              return response;
            }
          );
        })
    );
  }
});

Registering the Service Worker

You need to register the service worker in your main JavaScript file:

if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('/sw.js').then(
      function(registration) {
        console.log('ServiceWorker registration successful');
      },
      function(err) {
        console.log('ServiceWorker registration failed: ', err);
      }
    );
  });
}

Additional Considerations

  • Cache Size Management: Implement logic to manage the cache size, as tiles can take up a significant amount of space. You might want to limit the number of tiles cached or implement a least-recently-used (LRU) cache policy.

  • Updates: Ensure your service worker updates correctly when you make changes to your caching strategy or resources.

  • Testing: Test your web application thoroughly in an offline environment to ensure that all necessary tiles are cached and that the application behaves as expected.

By using service workers and the Cache API, you can create a robust offline experience for your web map application.


✏️ Participer à la discussion