Implementation:Langgenius Dify Service Worker
| Knowledge Sources | |
|---|---|
| Domains | Frontend, PWA, Caching |
| Last Updated | 2026-02-12 07:00 GMT |
Overview
PWA service worker using the Serwist library to provide precaching, runtime caching with default strategies, offline fallback for document requests, and manifest URL normalization for base path support.
Description
The web/app/sw.ts file implements the Dify application's service worker, built on the Serwist library (a modern fork of Workbox). It runs in the ServiceWorkerGlobalScope and is responsible for intercepting network requests to provide caching and offline support, making the application function as a Progressive Web App (PWA).
The service worker performs three key tasks. First, it normalizes the precache manifest URLs by stripping the /serwist/ prefix that may be present due to the build pipeline, ensuring cache keys match actual request URLs regardless of the configured base path. Second, it instantiates a Serwist instance configured with precaching entries from the build manifest, runtime caching strategies imported from @serwist/turbopack/worker, navigation preloading for faster page loads, and immediate activation via skipWaiting and clientsClaim. Third, it registers an offline fallback that serves a static _offline.html page when a document request fails and no cached response is available.
The base path is dynamically computed from the service worker's registration scope, allowing the application to be deployed under arbitrary URL prefixes without hardcoding paths.
Usage
This service worker is automatically registered by the PWAProvider component in the root layout. It does not need to be imported or invoked directly. The Serwist build integration generates the precache manifest (__SW_MANIFEST) during the Next.js build process, and the service worker is served from the application's scope path.
Code Reference
Source Location
- Repository: Langgenius_Dify
- File: web/app/sw.ts
- Lines: 1-59
Signature
declare global {
interface WorkerGlobalScope extends SerwistGlobalConfig {
__SW_MANIFEST: (PrecacheEntry | string)[] | undefined
}
}
const normalizeManifestUrl = (url: string): string => { ... }
const serwist = new Serwist({
precacheEntries: manifest,
skipWaiting: true,
disableDevLogs: true,
clientsClaim: true,
navigationPreload: true,
runtimeCaching: defaultCache,
fallbacks: {
entries: [
{
url: offlineUrl,
matcher({ request }) { return request.destination === 'document' },
},
],
},
})
serwist.addEventListeners()
Import
// This file is not imported by application code.
// It is compiled as a standalone service worker entry point.
// Internal imports:
import type { PrecacheEntry, SerwistGlobalConfig } from 'serwist'
import { defaultCache } from '@serwist/turbopack/worker'
import { Serwist } from 'serwist'
import { withLeadingSlash } from 'ufo'
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| self.__SW_MANIFEST | (PrecacheEntry | string)[] | undefined | No | Build-time generated precache manifest injected by the Serwist build plugin |
| self.registration.scope | string | Yes (implicit) | The service worker's registration scope URL, used to derive the base path |
| Network requests | FetchEvent | Yes (implicit) | All fetch events intercepted by the service worker for cache matching and fallback |
Outputs
| Name | Type | Description |
|---|---|---|
| Cached responses | Response | Precached or runtime-cached HTTP responses served from the Cache Storage API |
| Offline fallback | Response | The _offline.html page served when a document request fails and no cache hit exists
|
| Navigation preload | Response | Preloaded navigation responses for faster page transitions |
Usage Examples
Service Worker Registration (via PWAProvider)
// The PWAProvider in web/app/components/provider/serwist.tsx handles registration:
// This is done automatically when the root layout renders.
// The service worker file is built to /sw.js in the output.
//
// In development, service worker is typically disabled.
// In production, the browser registers and activates it on first visit.
How URL Normalization Works
// Given a manifest entry with URL "/serwist/apps/page.js"
// normalizeManifestUrl strips the prefix:
normalizeManifestUrl('/serwist/apps/page.js')
// Returns: '/apps/page.js'
// For entries without the prefix, a leading slash is ensured:
normalizeManifestUrl('icons/favicon.ico')
// Returns: '/icons/favicon.ico'
Offline Fallback Behavior
1. User navigates to /apps while offline
2. Service worker intercepts the fetch event
3. No cached response found, network request fails
4. Matcher checks: request.destination === 'document' -> true
5. Service worker responds with the cached _offline.html page