diff --git a/documentation/how-to.md b/documentation/how-to.md index 2283c817c..9d6f33bbb 100644 --- a/documentation/how-to.md +++ b/documentation/how-to.md @@ -234,6 +234,46 @@ snippets (leave it empty for relative URLs that work wherever the folder is drop --- +## Hosting the dx-maps folder: caching, compression, CORS + +**Why it matters.** On a cold load a map's layers draw about 10–17 s after the page opens (measured +on the UPG-100 list page). The bundle and the map engine take under 2 s of that; the rest is basemap +tiles and data files such as the country-boundary file (1,866 KB raw, 597 KB gzipped). Compression +cuts every visit; caching means a returning reader doesn't download the same files again. + +**Every file in `dx-maps/` has a fixed name today.** Nothing is content-hashed, so a new release +overwrites files in place: bundles (`/.js`), their pages (`index.html`) and +`manifest.json` change whenever the build changes them. Images, fonts and data files change rarely, +but under the same names. + +| Files | `Cache-Control` | Why | +|---|---|---| +| everything in `dx-maps/`, as it ships today | `public, max-age=86400, stale-while-revalidate=604800`, with an `ETag` | a revisit revalidates cheaply and never re-downloads unchanged bytes, and a release shows up within a day | +| content-hashed names, if you add them (e.g. `world-adm0.3f9a1c2e.geojson`) | `public, max-age=31536000, immutable` | a changed file gets a new name, so a year-long cache is always safe | + +**Never send `immutable` for a fixed name**: an update would stay invisible for a year. + +**Compress:** serve `br` or `gzip`, and give data files a JSON content type (`application/json`, or +`application/geo+json` for `.geojson`) so CDNs compress them. Many servers send `.geojson` as +`application/octet-stream`, which CDNs don't compress. + +**CORS for script embeds:** every `embed.script` snippet loads the bundle with an `integrity` hash +and `crossorigin="anonymous"`. For that to work on another site, the host must send +`Access-Control-Allow-Origin: *`; without it the browser can't check the hash across origins and refuses +the script. iframe embeds need no CORS. + +On Cloudflare Pages or Netlify, a `_headers` file at the folder's root sets the CORS and cache headers: + +``` +/* + Access-Control-Allow-Origin: * + Cache-Control: public, max-age=86400, stale-while-revalidate=604800 +``` + +Check the content type your host gives `.geojson` files (`curl -sI `) before relying on compression. + +--- + ## Compose maps into a SPA (the app shell) Several maps + one layout = a single-page app, served from the same `public/` tree.