Skip to content

Commit a8ce1c2

Browse files
author
Taois
committed
feat: 更新drplayer
优化部署方式,完善首页,收藏,历史
1 parent 18e091c commit a8ce1c2

20 files changed

+2534
-3580
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,4 @@ dist
128128
.yarn/build-state.yml
129129
.yarn/install-state.gz
130130
.pnp.*
131+
/dashboard/apps/drplayer/

dashboard/.env.production

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# .env.production
22
# 生产环境配置
33
# 子目录部署配置 - 例如部署到 /apps/ 目录
4-
VITE_BASE_PATH=/apps/drplayer/
4+
# VITE_BASE_PATH=/apps/drplayer/
55

66
# 如果部署到根目录,使用以下配置:
7-
# VITE_BASE_PATH=./
7+
VITE_BASE_PATH=./

dashboard/.env.production.apps

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# .env.production.apps
2+
# 子目录部署配置 - 部署到 /apps/drplayer/ 目录
3+
VITE_BASE_PATH=/apps/drplayer/

dashboard/.env.production.root

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# .env.production.root
2+
# 根目录部署配置
3+
VITE_BASE_PATH=./

dashboard/build-for-fastify.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// 为Fastify部署构建Vue应用的脚本
2+
import { execSync } from 'child_process';
3+
import path from 'path';
4+
import fs from 'fs';
5+
import { fileURLToPath } from 'url';
6+
7+
const __filename = fileURLToPath(import.meta.url);
8+
const __dirname = path.dirname(__filename);
9+
10+
async function buildForFastify() {
11+
console.log('🚀 开始为Fastify部署构建Vue应用...');
12+
13+
try {
14+
// 1. 设置环境变量
15+
process.env.NODE_ENV = 'production';
16+
process.env.VITE_BASE_PATH = '/apps/drplayer/';
17+
18+
console.log('📦 正在构建应用...');
19+
20+
// 2. 执行构建
21+
execSync('yarn build', {
22+
stdio: 'inherit',
23+
env: {
24+
...process.env,
25+
VITE_BASE_PATH: '/apps/drplayer/'
26+
}
27+
});
28+
29+
// 3. 检查构建结果
30+
const distPath = path.join(__dirname, 'dist');
31+
const indexPath = path.join(distPath, 'index.html');
32+
33+
if (fs.existsSync(indexPath)) {
34+
console.log('✅ 构建成功!');
35+
console.log(`📁 构建文件位置: ${distPath}`);
36+
console.log('');
37+
console.log('📋 部署步骤:');
38+
console.log('1. 将 dist/ 目录的内容复制到您的后端 apps/drplayer/ 目录');
39+
console.log('2. 在Fastify应用中添加SPA路由支持(参考 fastify-spa-routes.js)');
40+
console.log('3. 重启Fastify服务器');
41+
console.log('4. 访问 http://your-server/apps/drplayer/');
42+
console.log('');
43+
console.log('🔧 Fastify配置示例:');
44+
console.log('```javascript');
45+
console.log('// 添加到您的Fastify应用中');
46+
console.log('import { addSPARoutes } from "./fastify-spa-routes.js";');
47+
console.log('await fastify.register(addSPARoutes, { appsDir: options.appsDir });');
48+
console.log('```');
49+
} else {
50+
throw new Error('构建失败:未找到index.html文件');
51+
}
52+
53+
} catch (error) {
54+
console.error('❌ 构建失败:', error.message);
55+
process.exit(1);
56+
}
57+
}
58+
59+
// 如果直接运行此脚本
60+
if (import.meta.url === `file://${process.argv[1]}`) {
61+
buildForFastify();
62+
}
63+
64+
export { buildForFastify };
File renamed without changes.
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# Vue SPA + Fastify 部署指南
2+
3+
## 问题说明
4+
5+
Vue单页应用使用`createWebHistory`路由模式时,刷新页面会出现404错误。这是因为:
6+
7+
1. 用户访问 `/apps/drplayer/settings`
8+
2. 浏览器向服务器请求 `/apps/drplayer/settings` 文件
9+
3. 服务器找不到该文件,返回404
10+
4. 需要让服务器将所有SPA路由请求都返回到 `index.html`
11+
12+
## 解决方案
13+
14+
通过Fastify提供静态文件服务 + SPA路由回退机制,完全可以解决刷新404问题。
15+
16+
## 配置步骤
17+
18+
### 1. 构建Vue应用
19+
20+
```bash
21+
# 方法1:使用构建脚本(推荐)
22+
node build-for-fastify.js
23+
24+
# 方法2:手动设置环境变量
25+
set VITE_BASE_PATH=/apps/drplayer/
26+
yarn build
27+
```
28+
29+
### 2. 复制构建文件
30+
31+
`dist/` 目录的所有内容复制到您的后端 `apps/drplayer/` 目录:
32+
33+
```
34+
your-backend/
35+
├── apps/
36+
│ └── drplayer/
37+
│ ├── index.html
38+
│ ├── assets/
39+
│ │ ├── index-xxx.js
40+
│ │ └── index-xxx.css
41+
│ └── ...
42+
└── server.js
43+
```
44+
45+
### 3. 配置Fastify服务器
46+
47+
#### 方法1:使用提供的路由模块(推荐)
48+
49+
```javascript
50+
import { addSPARoutes } from './fastify-spa-routes.js';
51+
import fastifyStatic from '@fastify/static';
52+
53+
// 您现有的静态文件配置
54+
await fastify.register(fastifyStatic, {
55+
root: options.appsDir,
56+
prefix: '/apps/',
57+
decorateReply: false,
58+
});
59+
60+
// 添加SPA路由支持
61+
await fastify.register(addSPARoutes, {
62+
appsDir: options.appsDir
63+
});
64+
```
65+
66+
#### 方法2:直接在现有代码中添加
67+
68+
```javascript
69+
import path from 'path';
70+
import fs from 'fs';
71+
72+
// 在您现有的Fastify应用中添加这些路由
73+
fastify.get('/apps/drplayer/*', async (request, reply) => {
74+
const requestedPath = request.params['*'];
75+
const fullPath = path.join(options.appsDir, 'drplayer', requestedPath);
76+
77+
try {
78+
await fs.promises.access(fullPath);
79+
return reply.callNotFound(); // 让静态文件服务处理
80+
} catch (error) {
81+
// 返回index.html让Vue Router处理
82+
const indexPath = path.join(options.appsDir, 'drplayer', 'index.html');
83+
const indexContent = await fs.promises.readFile(indexPath, 'utf8');
84+
return reply
85+
.type('text/html')
86+
.header('Cache-Control', 'no-cache, no-store, must-revalidate')
87+
.send(indexContent);
88+
}
89+
});
90+
91+
// 处理根路径
92+
fastify.get('/apps/drplayer', async (request, reply) => {
93+
return reply.redirect(301, '/apps/drplayer/');
94+
});
95+
96+
fastify.get('/apps/drplayer/', async (request, reply) => {
97+
const indexPath = path.join(options.appsDir, 'drplayer', 'index.html');
98+
const indexContent = await fs.promises.readFile(indexPath, 'utf8');
99+
return reply
100+
.type('text/html')
101+
.header('Cache-Control', 'no-cache, no-store, must-revalidate')
102+
.send(indexContent);
103+
});
104+
```
105+
106+
## 工作原理
107+
108+
1. **静态文件服务**`@fastify/static` 处理所有存在的静态文件(JS、CSS、图片等)
109+
2. **路由回退**:当请求的文件不存在时,返回 `index.html`
110+
3. **Vue Router接管**`index.html` 加载后,Vue Router根据URL显示对应组件
111+
112+
## 路由优先级
113+
114+
```
115+
请求: /apps/drplayer/assets/index-xxx.js
116+
117+
静态文件存在 → 直接返回文件
118+
119+
请求: /apps/drplayer/settings
120+
121+
静态文件不存在 → 返回 index.html → Vue Router处理
122+
```
123+
124+
## 缓存策略
125+
126+
- **HTML文件**:不缓存(`no-cache`),确保路由更新
127+
- **静态资源**:长期缓存(1年),提高性能
128+
129+
## 测试验证
130+
131+
1. 启动Fastify服务器
132+
2. 访问 `http://localhost:3000/apps/drplayer/`
133+
3. 导航到不同页面(如设置页面)
134+
4. 刷新页面,确认不出现404错误
135+
5. 检查浏览器开发者工具,确认静态资源正常加载
136+
137+
## 常见问题
138+
139+
### Q: 刷新后页面空白?
140+
A: 检查 `VITE_BASE_PATH` 是否正确设置为 `/apps/drplayer/`
141+
142+
### Q: 静态资源404?
143+
A: 确认构建时的base路径与Fastify的prefix匹配
144+
145+
### Q: API请求失败?
146+
A: 确保API路由在SPA路由之前注册,避免被SPA回退拦截
147+
148+
## 性能优化
149+
150+
1. **启用Gzip压缩**
151+
```javascript
152+
import fastifyCompress from '@fastify/compress';
153+
await fastify.register(fastifyCompress);
154+
```
155+
156+
2. **设置静态资源缓存**
157+
```javascript
158+
await fastify.register(fastifyStatic, {
159+
// ... 其他配置
160+
setHeaders: (res, path) => {
161+
if (path.endsWith('.html')) {
162+
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
163+
} else if (path.match(/\.(js|css|png|jpg|jpeg|gif|ico|svg)$/)) {
164+
res.setHeader('Cache-Control', 'public, max-age=31536000');
165+
}
166+
}
167+
});
168+
```
169+
170+
## 总结
171+
172+
**可以解决404问题**:通过Fastify的路由回退机制
173+
**性能良好**:静态文件直接服务,只有路由请求才回退
174+
**配置简单**:只需添加几个路由处理器
175+
**开发友好**:支持热重载和开发服务器

0 commit comments

Comments
 (0)