sw.js fixed
This commit is contained in:
146
.fixoffline
Normal file
146
.fixoffline
Normal file
@@ -0,0 +1,146 @@
|
||||
Hier ist die instruktive Anleitung für deine IDE (Cursor, Antigravity, etc.). Du kannst diesen Text direkt als Prompt oder Kontext-Datei (`OFFLINE_STRATEGY.md`) in deine IDE kopieren.
|
||||
|
||||
Es enthält die **Pre-Caching Strategie** (für den Start im Keller) und den **Navigation Fallback** (gegen den White Screen).
|
||||
|
||||
---
|
||||
|
||||
# 🛡️ PWA "Ironclad" Offline Strategy Implementation
|
||||
|
||||
**Context:** The application fails to load when started completely offline ("Keller-Szenario") or crashes during navigation when the network is flaky.
|
||||
**Goal:** Implement aggressive Pre-Caching for core routes and a robust Navigation Fallback in `public/sw.js`.
|
||||
**Framework:** Next.js (App Router) + Workbox.
|
||||
|
||||
## 🚨 Critical Requirements
|
||||
|
||||
1. **Preserve Existing Logic:** Do not remove the `skipWaiting()` or `clients.claim()` logic if already present.
|
||||
2. **App Router Compatibility:** Ensure `_next/data` requests do not cause crashes.
|
||||
3. **Dexie Integration:** Rely on the existing `useLiveQuery` hooks for data. The Service Worker only needs to deliver the **App Shell**.
|
||||
|
||||
---
|
||||
|
||||
## 📝 Implementation Instructions for `public/sw.js`
|
||||
|
||||
Please refactor or append the Service Worker logic to include the following **three mechanics**:
|
||||
|
||||
### 1. Define Core Pages (The "Keller" List)
|
||||
|
||||
Define a list of static routes that *must* work immediately upon installation, even without a network connection.
|
||||
|
||||
```javascript
|
||||
// CONFIG: Core pages to pre-cache immediately on install
|
||||
const CORE_PAGES = [
|
||||
'/', // Dashboard / Home
|
||||
'/tasting/new', // Critical: Add Tasting Screen
|
||||
'/scan', // Critical: Scan Screen
|
||||
'/offline' // Optional: Dedicated offline fallback
|
||||
];
|
||||
|
||||
```
|
||||
|
||||
### 2. The "Warm Cache" Install Event
|
||||
|
||||
Add an `install` event listener that aggressively fetches these pages into the cache *before* the user needs them.
|
||||
|
||||
```javascript
|
||||
self.addEventListener('install', (event) => {
|
||||
event.waitUntil(
|
||||
caches.open('pages').then((cache) => {
|
||||
console.log('⚡ PWA: Pre-caching core pages for offline usage...');
|
||||
// { cache: 'reload' } forces a network fetch, ignoring browser http cache
|
||||
return cache.addAll(CORE_PAGES);
|
||||
})
|
||||
);
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
### 3. The Navigation Safety Net (The "Anti-Crash" Logic)
|
||||
|
||||
Implement a `NavigationRoute` that attempts the network first (with a short timeout), falls back to the cache, and—**critically**—falls back to the Root (`/`) if the specific deep-link is missing from the cache.
|
||||
|
||||
*Rationale:* In Next.js (SPA), loading `/` from cache is sufficient to bootstrap the React app. The client-side router will then handle the URL, and Dexie will provide the data.
|
||||
|
||||
```javascript
|
||||
import { registerRoute, NavigationRoute } from 'workbox-routing';
|
||||
import { NetworkFirst } from 'workbox-strategies';
|
||||
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
|
||||
|
||||
// Strategy: Network (3s timeout) -> Cache -> Fallback to Root
|
||||
const navigationHandler = async (params) => {
|
||||
try {
|
||||
// 1. Try Network First (Fail fast if poor connection)
|
||||
const strategy = new NetworkFirst({
|
||||
cacheName: 'pages',
|
||||
networkTimeoutSeconds: 3,
|
||||
plugins: [
|
||||
new CacheableResponsePlugin({ statuses: [0, 200] }),
|
||||
],
|
||||
});
|
||||
return await strategy.handle(params);
|
||||
|
||||
} catch (error) {
|
||||
// 2. Network failed. Try getting the specific page from cache.
|
||||
const cache = await caches.open('pages');
|
||||
// params.request.url contains the full URL user is trying to reach
|
||||
let response = await cache.match(params.request);
|
||||
|
||||
if (response) return response;
|
||||
|
||||
// 3. CRITICAL FALLBACK: Load the App Shell (Root)
|
||||
// Even if the user requested /tasting/new, serving / allows Next.js to start.
|
||||
// Once React hydrates, it sees the URL is /tasting/new and renders the correct page
|
||||
// using data from Dexie.
|
||||
const fallbackResponse = await cache.match('/');
|
||||
if (fallbackResponse) {
|
||||
console.log('⚠️ PWA: Serving Root App Shell for offline navigation.');
|
||||
return fallbackResponse;
|
||||
}
|
||||
|
||||
// 4. Absolute last resort
|
||||
return new Response('Offline mode unavailable', { status: 504 });
|
||||
}
|
||||
};
|
||||
|
||||
// Apply this handler to all Navigation requests
|
||||
registerRoute(new NavigationRoute(navigationHandler));
|
||||
|
||||
```
|
||||
|
||||
### 4. Handling Next.js Data (RSC)
|
||||
|
||||
Prevent crashes when `_next/data/...` fetches fail.
|
||||
|
||||
```javascript
|
||||
// Swallow errors for RSC data to prevent "Application Error" screens
|
||||
registerRoute(
|
||||
({ url }) => url.pathname.startsWith('/_next/data/'),
|
||||
new NetworkFirst({
|
||||
cacheName: 'next-data',
|
||||
networkTimeoutSeconds: 2,
|
||||
plugins: [
|
||||
{
|
||||
// If offline and not in cache, return empty JSON to keep React alive
|
||||
handlerDidError: async () => new Response(JSON.stringify({}), {
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
})
|
||||
}
|
||||
]
|
||||
})
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Verification Checklist
|
||||
|
||||
After applying these changes:
|
||||
|
||||
1. **Clear Storage:** Unregister old Service Workers and clear Storage in DevTools.
|
||||
2. **Install:** Load the app once online. Verify `pages` cache contains `/tasting/new`.
|
||||
3. **Test:**
|
||||
* Go Offline (Airplane Mode).
|
||||
* Reload the page.
|
||||
* Navigate to `/tasting/new`.
|
||||
* **Expectation:** App loads, UI renders, data comes from Dexie. No "No Internet" dino.
|
||||
Reference in New Issue
Block a user