Progressive Web App (PWA) Installation
Relevant source files
The following files were used as context for generating this wiki page:
The Endfield-Pomodoro application is configured as a Progressive Web App (PWA), enabling an installable, app-like experience with offline capabilities. This is achieved through a Service Worker that manages asset caching and an update mechanism that ensures users have the latest version of the application. The implementation uses the vite-plugin-pwa library to automate the generation of the Service Worker and the web app manifest.
The PWA features include offline support for core application assets and a system for notifying users when a new version is available, prompting an automatic page reload to apply the update. This ensures a seamless and reliable user experience, even with intermittent network connectivity.
Sources: README.md:23-26, vite.config.ts:4, package.json:29
PWA Configuration
The core PWA logic is defined in vite.config.ts using the VitePWA plugin. This configuration dictates the web app manifest, service worker behavior, and caching strategies.
Sources: vite.config.ts:15-139
Web App Manifest
The manifest object configures the metadata for the PWA, which controls how it appears when installed on a user's device (e.g., home screen icon, app name, theme color).
Sources: vite.config.ts:18-44
| Property | Value | Description |
|---|---|---|
name | Endfield Protocol - Pomodoro Terminal | The full name of the application. |
short_name | Endfield | A shorter name for the application, used where space is limited. |
description | 融合 Cyber UI 和《终末地》风格的沉浸式番茄钟应用 | A brief description of the application's purpose. |
theme_color | #fff7d0 | The theme color for the application UI, also used in the index.html meta tag. |
background_color | #e5e5e5 | The background color of the splash screen. |
display | standalone | Configures the application to open in its own window, separate from the browser. |
start_url | / | The entry point of the application when launched from an installed icon. |
scope | / | The navigation scope of the PWA. |
icons | (Array) | An array of icon objects for different sizes and purposes (any, maskable). |
categories | ['productivity', 'utilities'] | Categories the app belongs to. |
lang | zh-CN | The primary language of the application. |
Sources: vite.config.ts:19-43, index.html:8
Service Worker (Workbox)
The service worker is configured via the workbox property, which uses Google's Workbox library to manage caching. The configuration specifies which files to pre-cache, the maximum file size for caching, and runtime caching strategies for dynamic requests.
Sources: vite.config.ts:45-138
Key Workbox Options
registerType: 'autoUpdate': This setting configures the PWA to automatically update in the background. ThePWAPrompt.tsxcomponent handles the user-facing notification and reload.cleanupOutdatedCaches: true: Ensures that old, unused caches are removed when the service worker updates.globPatterns: Defines the file patterns (js,css,html,ico,png,svg,webp,woff,woff2) to be pre-cached.maximumFileSizeToCacheInBytes: Sets a limit of 4MB for files to be included in the pre-cache.navigateFallback: 'index.html': Specifies that for any navigation request that doesn't match a cached route,index.htmlshould be served. This is essential for a Single Page Application (SPA).navigateFallbackDenylist: Prevents thenavigateFallbackfrom applying to API routes (/api/) and audio file extensions, ensuring these requests always go to the network.
Sources: vite.config.ts:16, vite.config.ts:46-55
Runtime Caching Strategies
The application employs several runtime caching strategies for different types of requests. This ensures optimal balance between performance, offline availability, and data freshness.
The following diagram illustrates the caching logic for various request types.
This table summarizes the runtime caching rules defined in vite.config.ts.
| URL Pattern | Handler | Cache Name | Description |
|---|---|---|---|
/index.html | NetworkFirst | index-html | Prioritizes fetching the latest index.html from the network. It is configured not to be cached (maxAgeSeconds: 0). |
api.injahow.cn/meting/ | NetworkOnly | - | All requests to the Meting API are network-only to get fresh music data. |
| Audio/Video destinations | NetworkOnly | - | Any request whose destination is audio or video bypasses the cache. |
| Music streaming hostnames | NetworkOnly | - | Requests to various music streaming services (NetEase, Tencent, Kugou, etc.) are always fetched from the network. |
fonts.googleapis.com | CacheFirst | google-fonts-stylesheets | Google Fonts stylesheets are served from the cache first for faster loading. |
fonts.gstatic.com | CacheFirst | google-fonts-webfonts | Webfont files from Google are served from the cache first. |
Sources: vite.config.ts:59-136
HTML Integration
The main index.html file includes several meta tags and link elements that are essential for PWA functionality, particularly for installation and appearance on mobile devices.
apple-mobile-web-app-capable: Allows the web app to run in full-screen mode on iOS.apple-mobile-web-app-status-bar-style: Sets the status bar style for the app on iOS.apple-mobile-web-app-title: Defines the app title for the home screen icon on iOS.theme-color: Specifies the UI theme color, which is used by browsers to customize the display.link rel="apple-touch-icon": Provides the icon for iOS home screens.link rel="icon": Provides the standard favicon.
Sources: index.html:8-15
Update Notification
The application provides a user-friendly update notification system managed by the PWAPrompt React component.
Sources: src/components/PWAPrompt.tsx, src/App.tsx:640
Update Detection and UI
The PWAPrompt component uses the useRegisterSW hook provided by virtual:pwa-register/react. This hook handles the service worker registration and lifecycle events.
The update process is as follows:
- Registration: On component mount,
useRegisterSWattempts to register the service worker. - Update Check:
- An initial update check is performed immediately upon successful registration (
r.update()). - A periodic check is scheduled to run every hour (
HOURLY_CHECK_INTERVAL_MS). - An additional check is triggered whenever the page becomes visible (
document.visibilityState === 'visible').
- An initial update check is performed immediately upon successful registration (
- Activation and Notification: When a new service worker has been installed and is ready to take control, the browser fires a
controllerchangeevent. - UI Prompt: The
PWAPromptcomponent listens for thiscontrollerchangeevent. When it fires, the component sets its state to show an "Updated successfully!" message. - Automatic Reload: After displaying the message for 3 seconds, the page automatically reloads (
window.location.reload()) to apply the update and ensure the user is on the latest version.
Sources: src/components/PWAPrompt.tsx:18-40, src/components/PWAPrompt.tsx:43-60
The following sequence diagram illustrates the update flow.
Integration in the Application
The PWAPrompt component is rendered at the root of the App component, ensuring it is always present to handle service worker updates. It receives the current language from the application's state to display the update message in the correct language.
// src/App.tsx
// ...
return (
<div className="...">
{/* ... other components ... */}
{/* PWA 更新提示 */}
<PWAPrompt language={settings.language} />
</div>
);
// ...
Sources: src/App.tsx:25, src/App.tsx:640, src/utils/i18n.ts:100, src/utils/i18n.ts:212
Conclusion
The PWA implementation in Endfield-Pomodoro is robust and well-configured. It leverages vite-plugin-pwa and Workbox to provide a reliable offline experience by caching essential assets while ensuring dynamic content like music streams is always fetched from the network. The automatic update mechanism, complete with a user-facing notification, guarantees that users benefit from the latest features and bug fixes with minimal disruption, enhancing the overall quality and usability of the application.