fix: 修复对话页面白屏 — SW 注册缺失导致缓存冲突

根因: 提交 20cdcc7 删除了 main.tsx 中的 SW 注册代码,声称 App.tsx
会调用 registerServiceWorker(),但实际未调用。旧 SW (cyrene-v1) 的
cache-first 策略拦截请求返回不兼容缓存,导致 React 白屏。

修复:
- App.tsx: 在组件挂载时调用 registerServiceWorker()
- sw.js: CACHE_NAME 升级到 cyrene-v2 强制清理旧缓存,增加 SKIP_WAITING
- main.tsx: 修正注释
This commit is contained in:
2026-05-20 20:12:46 +08:00
parent 20cdcc748e
commit 4058aae1e4
3 changed files with 25 additions and 6 deletions
+16 -4
View File
@@ -1,31 +1,43 @@
const CACHE_NAME = 'cyrene-v1';
const CACHE_NAME = 'cyrene-v2';
const ASSETS_TO_CACHE = [
'/',
'/index.html',
];
// Install: 缓存核心资源
// Install: 缓存核心资源,立即激活
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll(ASSETS_TO_CACHE);
})
);
// 立即激活新 SW,不等待旧 SW 释放
self.skipWaiting();
});
// Activate: 清理旧缓存
// Activate: 清理所有旧版本缓存,立即接管所有页面
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((keys) => {
return Promise.all(
keys.filter(key => key !== CACHE_NAME).map(key => caches.delete(key))
keys.filter(key => key !== CACHE_NAME).map(key => {
console.log('[SW] 清理旧缓存:', key);
return caches.delete(key);
})
);
})
);
// 立即接管所有页面(无需刷新)
self.clients.claim();
});
// 检测新 SW 更新并通知客户端
self.addEventListener('message', (event) => {
if (event.data?.type === 'SKIP_WAITING') {
self.skipWaiting();
}
});
// Fetch: 缓存优先策略(对 API 请求使用网络优先)
self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url);
+7
View File
@@ -7,6 +7,7 @@ import { useChat } from '@/hooks/useChat';
import { useSessionStore, isAdminUser } from '@/store/sessionStore';
import { useChatStore } from '@/store/chatStore';
import { fetchMessages } from '@/api/sessions';
import { registerServiceWorker } from '@/hooks/usePWA';
/** URL Hash 工具 */
const SESSION_HASH_PREFIX = 'session=';
@@ -44,6 +45,12 @@ export default function App() {
const initializedRef = useRef(false);
// ========== PWA Service Worker ==========
// 注册 Service Worker(在 main.tsx 移除内联注册后,由 App 组件负责)
useEffect(() => {
registerServiceWorker();
}, []);
// ========== URL Hash 路由 ==========
/** 根据 hash 恢复或选择初始会话 */
+2 -2
View File
@@ -3,8 +3,8 @@ import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';
// Service Worker 注册已移至 hooks/usePWA.ts 中的 registerServiceWorker()
// 避免重复注册导致的竞态条件。App.tsx 会在初始化时调用 registerServiceWorker()。
// Service Worker 注册由 App.tsx 在初始化时调用 registerServiceWorker()(来自 hooks/usePWA.ts)。
// 避免在入口文件直接注册导致的竞态条件。
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>