Service Worker practical specifications for the current Magic Web implementation. Covers static resource partitioning, read-only API caching, request tagging, server-side kill/off takeover for /sw.js, and emergency rollback environment variables.
61
72%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./frontend/magic-web/.agents/skills/sw-best-practices/SKILL.mdUse this specification as a priority when the Agent or developer needs to handle the following tasks:
Typical activation keywords: "modify cache rules", "add API cache", "SW troubleshooting", "PWA cache optimization", "clear SW", "MAGIC_SW_MODE", "MAGIC_SW_CLEAR_CACHES".
When handling Service Worker development for this repository, the following design philosophy and security gates must be strictly followed to prevent cache pollution and accidental interception risks:
Static resources prioritize the CacheFirst strategy. To ensure a balance between performance and stability, resources must be strictly partitioned with the following restrictions:
generateBundle, pre-cached during SW installation (install) to warm up, and written to the magic-web-app-static-assets-v1 bucket.magic-web-app-image-assets-v1 bucket.swCache=runtime via helper functions and written to the magic-web-app-marked-resource-assets-v1 bucket./sw.js, entry HTML, config.js, mockServiceWorker.js, and /sw/canvas-design-media/** must stay out of the main runtime cache buckets. Current code enforces this by route matching boundaries and, for kill/off, by server-side takeover of /sw.js.When performing CacheFirst caching and interception on cross-origin CDN resources, credentials: "omit" must be explicitly applied during SW match and fetch. This prevents user sensitive Tokens/Cookies from being sent, avoiding cross-origin privilege escalation or identity pollution.
To accelerate first-screen rendering, StaleWhileRevalidate (SWR) cache is introduced for critical read-only GET interfaces. Caching APIs with frequent write operations or high data consistency requirements is strictly prohibited.
During HttpClient calls, developers can use the swCacheOption option to determine whether to enable caching:
swCacheOption: "no-cache" (Highest Priority): Forces direct network fetch to obtain the latest data, completely bypassing the SW cache. Suitable for scenarios like pull-to-refresh and fetching configurations after successful form submission.swCacheOption: "cache" (High Priority): Ignores global switches and path whitelists, forcing the response to be stored in the SW cache. Suitable for customized cold-start acceleration on specific pages.swCacheOption: "default" or unspecified (Default): Follows "Global Switch + Path Whitelist". As long as the global environment variable MAGIC_ENABLE_API_CACHE is not "false" and the interface path hits the whitelist validation, caching is enabled.MAGIC_SW_MODE: The browser-side registration code treats on and kill as registerable modes. none, off, empty, or unknown values mean "do not register the normal app SW" and unregister existing app SW registrations on the client.MAGIC_SW_MODE=kill|off on the server: server/middleware/serviceWorkerMiddleware.js takes over /sw.js. kill returns a cleanup SW that deletes caches and unregisters itself; off returns a lightweight unregister-only SW.MAGIC_SW_CLEAR_CACHES: Only meaningful when the server is serving MAGIC_SW_MODE=kill. It accepts a comma-separated cache bucket list, or ALL (case-insensitive) to clear all CacheStorage buckets for the current origin. If omitted in kill mode, the middleware falls back to the off behavior.MAGIC_ENABLE_API_CACHE: Controls the default behavior of the request interceptor. Any value except "false" keeps whitelist-based API caching enabled by default.MAGIC_MOCK / MAGIC_FORCE_ENABLE_SW_IN_DEV: In development, the app unregisters the normal SW unless local mock mode is enabled or MAGIC_FORCE_ENABLE_SW_IN_DEV=true is set.MAGIC_CDNHOST / MAGIC_PUBLIC_CDN_URL: Used to build the Workbox runtime URL and vendor cache host allowlist during SW registration.To avoid accidental matching of unrelated interfaces that pass whitelisted APIs as query parameters (e.g., /api/v1/proxy?url=/api/v1/settings/all):
isCacheableApiRequest must first parse the request using new URL to extract a clean pathname (stripping Query and Hash) before performing the match.^ and end with $, prohibiting loose substring regex.?swCache=api-runtime, while the SW must automatically remove this query parameter before initiating the network fetch (requestWillFetch). This ensures that the actual request sent to the backend is not polluted and eliminates the impact of CORS preflight on cross-origin requests.When a business error occurs, backend interfaces might still return HTTP 200 but wrap a custom error JSON (e.g., { code: 5000, message: "Error" }).
json.code === 1000 (standard business success code) or json.code === undefined (raw configuration data like internationalization translation packages). All other responses must return null to reject caching.The Service Worker in this project adopts a clear physical structure of "single main SW entry + multiple sub-module runtime reuse + main thread interceptor tagging". Writing matching logic in multiple places on the business side is strictly prohibited.
graph TD
Client[Business/HttpClient] -->|Register common sw-cache.ts interceptor where needed| Clients[Client Instances: magicClient and other opt-in HTTP clients]
Clients -->|Append swCache=api-runtime tag when GET request hits rules| Fetch[Fetch Request]
Fetch -->|SW Activation Interception| SW[Main Entry: src/sw.ts]
SW -->|Lifecycle Distribution| Runtime[sw-runtime.ts]
SW -->|Workbox Bucket Routing & Strategy| Cache[cache-runtime.ts]
Cache -->|Compare Path Whitelist Contract| Constants[sw-constants.ts]
Server[server/middleware/serviceWorkerMiddleware.js] -->|Take over /sw.js in kill/off mode| SWCACHEABLE_API_RULES), and path extraction decision functions (isCacheableApiRequest).apiBusinessCacheablePlugin).MAGIC_SW_MODE gating, SKIP_WAITING activation, and reloading control./sw.js takeover for kill and off modes, including MAGIC_SW_CLEAR_CACHES parsing.When developing or maintaining SW in this repository, you must strictly follow the steps below.
CACHEABLE_API_RULES array. If it is a regular expression, it must start with ^ and end with $ (e.g., /^\/api\/v1\/settings\/(all|menu-modules)$/).swCacheRequestInterceptor is registered in its constructor or setupInterceptors. Do not assume that editing sw-constants.ts alone is always sufficient.1000, ensure that cacheWillUpdate on the SW side (located in cache-runtime.ts) contains the normal validation for this property to prevent caching failures due to json.code !== 1000.CACHE_NAME and matching regex in sw-constants.ts, and add the new bucket name to the MANAGED_APP_CACHE_NAMES array (to prevent accidental deletion during the activation cleanup phase).registerRoute in cache-runtime.ts, and configure the capacity and TTL limits of ExpirationPlugin.After modifying any SW-related constants, matching rules, or interceptors, the following verification must be executed before submission:
pnpm test src/workers/service-worker/__tests__/sw-constants.test.ts
pnpm test src/workers/service-worker/__tests__/register.test.ts
pnpm test plugins/__tests__/collect-precache-asset-urls.test.tspnpm buildsrc/sw.ts and generate the /sw.js artifact correctly at the project root path.If a serious online failure occurs after the Service Worker logic is deployed (such as abnormal login states, white screens, or dirty data reads caused by cache pollution):
MAGIC_SW_MODE=off/sw.js and return an unregister-only SW. The browser activates that SW and unregisters it without deleting any cache buckets.kill mode together with explicit cache targets:
MAGIC_SW_MODE=kill
MAGIC_SW_CLEAR_CACHES=magic-web-app-api-cache-v1/sw.js; when that SW activates in the browser, it deletes only the listed cache buckets and then unregisters itself. Use MAGIC_SW_CLEAR_CACHES=ALL only when a full CacheStorage reset is intentional.MAGIC_MOCK=true or MAGIC_FORCE_ENABLE_SW_IN_DEV=true. If you do enable SW locally and need to avoid stale API reads during debugging, explicitly set MAGIC_ENABLE_API_CACHE=false in the local .env, or check Disable cache in the browser developer tools' Network panel.41d7ef4
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.