Skip to content

Commit 9a44911

Browse files
authored
Merge pull request #1 from weizwz/dev
Dev
2 parents 6d12b36 + f4d9ff3 commit 9a44911

File tree

10 files changed

+381
-48
lines changed

10 files changed

+381
-48
lines changed

.env.example

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# 网站 URL(用于生成 Open Graph 和 Twitter 卡片)
2+
# 开发环境
3+
# NEXT_PUBLIC_SITE_URL=http://localhost:3000
4+
5+
# 生产环境
6+
NEXT_PUBLIC_SITE_URL=https://nav.weizwz.com
Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
# 缓存清除指南
2+
3+
## 问题现象
4+
5+
更新网站后,可能出现以下问题:
6+
- ❌ CSP 错误:`connect-src 'self'` 阻止请求
7+
- ❌ 图标加载失败
8+
- ❌ 功能异常
9+
- ❌ 样式不更新
10+
11+
## 原因分析
12+
13+
浏览器缓存了旧版本的文件:
14+
1. **Service Worker 缓存**:缓存了旧的 `_headers` 文件
15+
2. **浏览器缓存**:缓存了旧的静态资源
16+
3. **HTTP 缓存**:CDN 或浏览器的 HTTP 缓存
17+
18+
## 解决方案
19+
20+
### 方法 1:使用清除缓存工具(推荐)
21+
22+
访问:`https://nav.weizwz.com/clear-cache.html`
23+
24+
点击"全部清除并刷新"按钮,自动完成所有清理工作。
25+
26+
### 方法 2:手动清除(开发者)
27+
28+
**Chrome/Edge**
29+
```
30+
1. F12 打开开发者工具
31+
2. Application → Storage → Clear site data
32+
3. 勾选所有选项
33+
4. 点击 "Clear site data"
34+
5. 刷新页面(Ctrl+Shift+R)
35+
```
36+
37+
**Firefox**
38+
```
39+
1. F12 打开开发者工具
40+
2. Storage → 右键 → Delete All
41+
3. 刷新页面(Ctrl+Shift+R)
42+
```
43+
44+
### 方法 3:浏览器设置清除
45+
46+
**所有浏览器**
47+
```
48+
1. Ctrl+Shift+Delete(Mac: Cmd+Shift+Delete)
49+
2. 选择"缓存的图片和文件"
50+
3. 时间范围选择"全部"
51+
4. 点击"清除数据"
52+
5. 刷新页面
53+
```
54+
55+
### 方法 4:隐身模式测试
56+
57+
```
58+
1. Ctrl+Shift+N(Chrome)或 Ctrl+Shift+P(Firefox)
59+
2. 访问网站
60+
3. 验证问题是否解决
61+
```
62+
63+
## 开发者:强制更新
64+
65+
### 1. 更新 Service Worker 版本
66+
67+
```javascript
68+
// public/sw.js
69+
const CACHE_NAME = 'weiz-nav-v5'; // v4 → v5
70+
const RUNTIME_CACHE = 'weiz-nav-runtime-v5';
71+
const IMAGE_CACHE = 'weiz-nav-images-v5';
72+
```
73+
74+
### 2. 更新 version.json
75+
76+
```json
77+
{
78+
"version": "1.0.5",
79+
"cacheVersion": "v5"
80+
}
81+
```
82+
83+
### 3. 部署
84+
85+
```bash
86+
git add public/sw.js public/version.json
87+
git commit -m "chore: 强制清除缓存 v5"
88+
git push
89+
```
90+
91+
### 4. 用户端自动更新
92+
93+
用户访问网站时:
94+
1. 检测到新版本 Service Worker
95+
2. 自动下载并安装
96+
3. 删除旧缓存(v1, v2, v3, v4)
97+
4. 激活新版本(v5)
98+
5. 自动刷新页面
99+
100+
## 验证缓存已清除
101+
102+
### 浏览器控制台
103+
104+
```javascript
105+
// 查看 Service Worker 版本
106+
navigator.serviceWorker.getRegistration().then(reg => {
107+
console.log('SW:', reg?.active?.scriptURL);
108+
});
109+
110+
// 查看缓存列表
111+
caches.keys().then(keys => {
112+
console.log('Caches:', keys);
113+
// 应该只看到 v4 的缓存
114+
});
115+
116+
// 查看 CSP 策略
117+
fetch('/').then(r => {
118+
console.log('CSP:', r.headers.get('content-security-policy'));
119+
});
120+
```
121+
122+
### DevTools 检查
123+
124+
```
125+
F12 → Application → Service Workers
126+
- 状态应该是 "activated and is running"
127+
- 版本应该是最新的
128+
129+
F12 → Application → Cache Storage
130+
- 应该只有 v4 的缓存
131+
- 旧版本(v1, v2, v3)应该被删除
132+
```
133+
134+
## 常见问题
135+
136+
### Q: 为什么清除后还是有问题?
137+
138+
**A**: 可能的原因:
139+
1. **CDN 缓存**:Cloudflare 边缘节点缓存了旧文件
140+
- 解决:在 Cloudflare 控制台清除缓存
141+
142+
2. **浏览器扩展**:某些扩展会缓存资源
143+
- 解决:禁用扩展或使用隐身模式
144+
145+
3. **DNS 缓存**:DNS 解析到旧的 IP
146+
- 解决:`ipconfig /flushdns`(Windows)或 `sudo dscacheutil -flushcache`(Mac)
147+
148+
### Q: 如何防止缓存问题?
149+
150+
**A**: 最佳实践:
151+
1. **版本化资源**:使用哈希文件名
152+
2. **合理的缓存策略**:
153+
- HTML: `max-age=0`
154+
- JS/CSS: `max-age=31536000` + 哈希
155+
- 图片: `max-age=2592000`
156+
3. **Service Worker 版本管理**:每次更新递增版本号
157+
158+
### Q: 用户需要手动清除吗?
159+
160+
**A**: 不需要!
161+
- Service Worker 会自动更新
162+
- 旧缓存会自动清除
163+
- 用户只需刷新页面
164+
165+
但如果遇到问题,可以:
166+
1. 访问 `/clear-cache.html`
167+
2. 点击"全部清除并刷新"
168+
169+
### Q: 清除缓存会丢失数据吗?
170+
171+
**A**: 不会!
172+
- ✅ LocalStorage 数据保留(用户的导航链接)
173+
- ✅ 用户设置保留
174+
- ❌ 只清除缓存的静态资源
175+
176+
## 预防措施
177+
178+
### 1. 开发时禁用缓存
179+
180+
```
181+
DevTools → Network → Disable cache(勾选)
182+
```
183+
184+
### 2. 使用版本号
185+
186+
```javascript
187+
// 在 URL 中添加版本号
188+
<script src="/app.js?v=1.0.4"></script>
189+
```
190+
191+
### 3. 设置正确的缓存头
192+
193+
```
194+
# public/_headers
195+
/*.html
196+
Cache-Control: public, max-age=0, must-revalidate
197+
198+
/*.js
199+
Cache-Control: public, max-age=31536000, immutable
200+
```
201+
202+
### 4. 监控缓存状态
203+
204+
```javascript
205+
// 定期检查缓存大小
206+
navigator.storage.estimate().then(estimate => {
207+
const used = (estimate.usage / 1024 / 1024).toFixed(2);
208+
const quota = (estimate.quota / 1024 / 1024).toFixed(2);
209+
console.log(`缓存: ${used}MB / ${quota}MB`);
210+
});
211+
```
212+
213+
## 清除缓存检查清单
214+
215+
部署新版本后:
216+
217+
- [ ] 更新 Service Worker 版本号
218+
- [ ] 更新 version.json
219+
- [ ] 提交并部署
220+
- [ ] 清除 Cloudflare 缓存(如果使用)
221+
- [ ] 测试环境验证
222+
- [ ] 生产环境验证
223+
- [ ] 监控用户反馈
224+
225+
## 紧急清除脚本
226+
227+
如果需要强制所有用户清除缓存:
228+
229+
```javascript
230+
// 在 Service Worker 中添加
231+
self.addEventListener('activate', (event) => {
232+
event.waitUntil(
233+
// 删除所有缓存
234+
caches.keys().then((cacheNames) => {
235+
return Promise.all(
236+
cacheNames.map((cacheName) => {
237+
return caches.delete(cacheName);
238+
})
239+
);
240+
})
241+
);
242+
});
243+
```
244+
245+
## 总结
246+
247+
**用户端**:
248+
- 访问 `/clear-cache.html` 清除缓存
249+
- 或等待 Service Worker 自动更新
250+
251+
**开发者端**:
252+
- 每次更新递增 Service Worker 版本
253+
- 设置合理的缓存策略
254+
- 监控缓存状态
255+
256+
**预防**:
257+
- 使用版本化资源
258+
- 正确的 HTTP 缓存头
259+
- Service Worker 自动更新机制
260+
261+
---
262+
263+
**记住**:缓存是为了性能,但也要确保用户能及时获取更新!

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,17 @@ Next.js 15 · TypeScript 5 · Tailwind CSS 4 · Ant Design 5 · Redux Toolkit ·
4242
## 🚀 快速开始
4343

4444
```bash
45+
# 克隆项目
46+
git clone <repository-url>
47+
cd frontend-navigation-site
48+
4549
# 安装依赖
4650
pnpm install
4751

52+
# 配置环境变量(可选)
53+
cp .env.example .env.local
54+
# 编辑 .env.local 设置你的网站 URL
55+
4856
# 启动开发服务器
4957
pnpm dev
5058

@@ -80,6 +88,7 @@ pnpm deploy
8088
- [快速开始](./.kiro/specs/frontend-navigation-site/QUICKSTART.md) - 5 分钟快速部署
8189
- [部署指南](./.kiro/specs/frontend-navigation-site/DEPLOYMENT.md) - 详细部署说明
8290
- [PWA 使用指南](./.kiro/specs/frontend-navigation-site/PWA_GUIDE.md) - PWA 安装和使用
91+
- [缓存清除指南](./.kiro/specs/frontend-navigation-site/CACHE_CLEAR_GUIDE.md) - 解决缓存问题
8392

8493
**开发文档**
8594
- [需求文档](./.kiro/specs/frontend-navigation-site/requirements.md) - 功能需求

app/globals.css

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,3 +397,40 @@ select:focus-visible {
397397
.install-success {
398398
animation: success-bounce 0.5s ease-in-out;
399399
}
400+
401+
/* 固定布局样式 */
402+
.h-screen {
403+
height: 100vh;
404+
height: 100dvh; /* 动态视口高度,移动端更准确 */
405+
}
406+
407+
/* 确保 body 和 html 不会滚动 */
408+
html, body {
409+
overflow: hidden;
410+
height: 100%;
411+
}
412+
413+
/* 只允许内容区域滚动 */
414+
#main-content {
415+
scroll-behavior: smooth;
416+
}
417+
418+
/* 优化滚动性能 */
419+
#main-content {
420+
-webkit-overflow-scrolling: touch; /* iOS 平滑滚动 */
421+
overscroll-behavior: contain; /* 防止滚动链 */
422+
}
423+
424+
/* 侧边栏滚动优化 */
425+
aside {
426+
-webkit-overflow-scrolling: touch;
427+
overscroll-behavior: contain;
428+
}
429+
430+
/* 移动端优化 */
431+
@media (max-width: 1023px) {
432+
/* 移动端允许整体滚动 */
433+
html, body {
434+
overflow: auto;
435+
}
436+
}

app/layout.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import RegisterServiceWorker from './register-sw';
55
import '@ant-design/v5-patch-for-react-19';
66

77
export const metadata: Metadata = {
8+
metadataBase: new URL(process.env.NEXT_PUBLIC_SITE_URL || 'https://nav.weizwz.com'),
89
title: {
910
default: '唯知导航',
1011
template: '%s | 唯知导航',

app/page.tsx

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -146,19 +146,21 @@ export default function Home() {
146146
);
147147

148148
return (
149-
<div className="min-h-screen flex flex-col bg-gray-50 dark:bg-(--background) transition-theme">
150-
{/* 页头组件 */}
151-
<Header onMenuClick={() => setDrawerOpen(true)} />
149+
<div className="h-screen flex flex-col bg-gray-50 dark:bg-(--background) transition-theme overflow-hidden">
150+
{/* 固定顶部 Header */}
151+
<div className="flex-none">
152+
<Header onMenuClick={() => setDrawerOpen(true)} />
153+
</div>
152154

153-
{/* 主内容区域 */}
154-
<div className="flex-1 flex overflow-hidden relative">
155+
{/* 主内容区域 - 固定高度,内部滚动 */}
156+
<div className="flex-1 flex overflow-hidden">
155157

156-
{/* 左侧分类导航 - Desktop */}
158+
{/* 左侧分类导航 - Desktop - 固定,内部滚动 */}
157159
<aside
158-
className="hidden lg:block w-48 bg-white dark:bg-antd-dark border-r border-gray-200 dark:border-neutral-700 overflow-y-auto transition-theme"
160+
className="hidden lg:flex flex-col w-48 bg-white dark:bg-antd-dark border-r border-gray-200 dark:border-neutral-700 transition-theme overflow-hidden"
159161
aria-label="分类导航侧边栏"
160162
>
161-
<CategorySidebar style={{height: '100%'}} />
163+
<CategorySidebar className="h-full" />
162164
</aside>
163165

164166
{/* 移动端抽屉 - 分类导航 */}
@@ -169,11 +171,14 @@ export default function Home() {
169171
open={drawerOpen}
170172
className="lg:hidden"
171173
width={280}
174+
styles={{
175+
body: { padding: 0, height: '100%' }
176+
}}
172177
>
173-
<CategorySidebar />
178+
<CategorySidebar className="h-full" />
174179
</Drawer>
175180

176-
{/* 右侧内容区域 */}
181+
{/* 右侧内容区域 - 只有这里滚动 */}
177182
<main
178183
id="main-content"
179184
className="flex-1 overflow-y-auto overflow-x-hidden"

0 commit comments

Comments
 (0)