v6.7.3: faster loading, and pages search engines can read
The bundles carried all thirteen translations at once and a page fetched them a third time as raw source; each page now loads only its own language. Alongside that: JavaScript is minified, the eight stylesheets are served as one file, the QR scanner is fetched after the app is up instead of on every visit, Inter ships once rather than five copies of the same file, and Font Awesome is subset to the 82 icons this app draws instead of all 2468. 1.85 MB across 43 requests becomes under 700 KB across 33. On mobile the page starts drawing in 1.6 s instead of 6.3 s and is usable in 4.5 s instead of 11 s. Pages also carry their text in the HTML now. Everything was drawn by JavaScript into an empty div, so crawlers saw correct metadata around nothing, and twelve of the thirteen language pages had never been shown to anyone. The documentation is published under /docs/ with a new FAQ, and unknown addresses return a real 404. Separately: the localized shells were served with the year-long immutable cache header meant for static assets, which pinned anyone who opened /de/ or /ru/ to that build. The header is fixed and the service worker refreshes what it cached. Claude-Session: https://claude.ai/code/session_014KjzTXxrhzYoDDWChYQ4u2
This commit is contained in:
@@ -11,7 +11,7 @@ let DYNAMIC_CACHE = 'securebit-pwa-dynamic-v4.7.56';
|
||||
// Build stamp — rewritten by scripts/post-build.js on every release so this file's
|
||||
// bytes change each deploy. That is what makes the browser detect a new Service Worker,
|
||||
// reinstall it, drop stale caches and (via controllerchange) prompt the page to update.
|
||||
const SW_BUILD_VERSION = '1788390440675';
|
||||
const SW_BUILD_VERSION = '1788496655816';
|
||||
|
||||
// Locale subdirectories, rewritten by scripts/build-i18n.js. Each localized page is a
|
||||
// separate document at its own URL, so the shell has to be cached and served per
|
||||
@@ -19,6 +19,20 @@ const SW_BUILD_VERSION = '1788390440675';
|
||||
const SW_LOCALES = ['de', 'fr', 'es', 'uk', 'ru', 'zh', 'ko', 'hi', 'ar', 'he', 'fa', 'ur'];
|
||||
const LOCALE_SHELLS = SW_LOCALES.flatMap((code) => [`/${code}/`, `/${code}/index.html`, `/${code}/manifest.json`]);
|
||||
|
||||
// Dictionary modules, rewritten by scripts/build-i18n.js alongside SW_LOCALES. Each
|
||||
// locale now ships its own strings rather than all thirteen riding inside the bundles,
|
||||
// so a shell cached for offline use is only half a page without the matching dictionary
|
||||
// — the visitor would get their own language's layout wrapped around English text.
|
||||
//
|
||||
// Only two of these are precached: the default locale's, which every page needs because
|
||||
// t() falls back to it, and the alias index.js imports. Downloading the other twelve up
|
||||
// front would put back most of the weight this split was for. They are allowlisted for
|
||||
// caching instead, so the one a visitor actually loads is stored on the way past.
|
||||
// BEGIN generated locale dictionaries
|
||||
const SW_DICTS = ['/src/i18n/dict/default.js', '/src/i18n/dict/en.js', '/src/i18n/dict/de.js', '/src/i18n/dict/fr.js', '/src/i18n/dict/es.js', '/src/i18n/dict/uk.js', '/src/i18n/dict/ru.js', '/src/i18n/dict/zh.js', '/src/i18n/dict/ko.js', '/src/i18n/dict/hi.js', '/src/i18n/dict/ar.js', '/src/i18n/dict/he.js', '/src/i18n/dict/fa.js', '/src/i18n/dict/ur.js'];
|
||||
const SW_PRECACHE_DICTS = ['/src/i18n/dict/default.js', '/src/i18n/dict/en.js'];
|
||||
// END generated locale dictionaries
|
||||
|
||||
// The locale a request belongs to, as a shell path. Falls back to the root shell.
|
||||
function shellFor(pathname) {
|
||||
const code = SW_LOCALES.find((c) => pathname === `/${c}` || pathname.startsWith(`/${c}/`));
|
||||
@@ -77,6 +91,7 @@ const STATIC_ASSETS = [
|
||||
// would fail to load offline, which is exactly when it is most likely to be shown.
|
||||
'/src/i18n/index.js',
|
||||
'/src/i18n/generated.js',
|
||||
...SW_PRECACHE_DICTS,
|
||||
|
||||
// Localized app shells (empty when the site is single-locale).
|
||||
...LOCALE_SHELLS
|
||||
@@ -128,6 +143,7 @@ const CACHEABLE_PATHS = new Set([
|
||||
'/src/scripts/pwa-offline-test.js',
|
||||
'/src/i18n/index.js',
|
||||
'/src/i18n/generated.js',
|
||||
...SW_DICTS,
|
||||
...LOCALE_SHELLS
|
||||
]);
|
||||
|
||||
@@ -171,7 +187,13 @@ self.addEventListener('install', (event) => {
|
||||
url = url + '?t=' + Date.now();
|
||||
}
|
||||
|
||||
await cache.add(url);
|
||||
// cache: 'reload' bypasses the browser's own HTTP cache
|
||||
// for this fetch and replaces what is in it. Without it a
|
||||
// client that once received a shell under the year-long
|
||||
// immutable header (see deploy/nginx.conf) would keep
|
||||
// re-caching that same stale copy on every install, and
|
||||
// never see a release again.
|
||||
await cache.add(new Request(url, { cache: 'reload' }));
|
||||
} catch (error) {
|
||||
console.warn(`⚠️ Failed to cache ${url}:`, error.message);
|
||||
// Continue with other assets even if one fails
|
||||
|
||||
Reference in New Issue
Block a user