2311061106/FRONTEND.md
23175 b8b09fd9d4
Some checks failed
autograde-final-vibevault / check-trigger (push) Successful in 13s
autograde-final-vibevault / grade (push) Failing after 55s
完成作业
2025-12-14 16:02:40 +08:00

161 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 前端开发反思报告
> 请参考 `FRONTEND_GUIDE.md` 了解写作要求。建议 6001200 字。
---
## 1. 我的界面展示
![首页界面(上半部分)](images/images/homepage1.png)
这是VibeVault音乐平台首页的上半部分界面采用现代化的卡片式布局展示了精选推荐内容包括"放松时刻"、"动感节拍"和"怀旧金曲"三个推荐歌单卡片。界面设计简洁明了,色彩搭配协调。
![首页界面(下半部分)](images/images/homepage2.png)
这是VibeVault音乐平台首页的下半部分界面展示了热门歌曲列表包含江南、小酒窝、曹操等热门歌曲每首歌曲显示排名、名称、歌手和时长信息。用户可以直接点击歌曲进行播放。
![歌单详情界面](images/images/playlist-detail.png)
这是歌单详情界面,展示了歌单的详细信息,包括封面图片、名称、描述和歌曲列表。用户可以在歌曲列表中选择歌曲进行播放,也可以添加新歌曲或删除现有歌曲。界面左侧为歌曲列表,右侧为当前播放歌曲的详细信息。
![歌曲播放界面](images/images/song-playing.png)
这是歌曲播放界面,显示了当前播放的歌曲信息,包括封面图片、标题、歌手和专辑。界面中央为播放控制区域,包含播放/暂停、上一首、下一首等控制按钮。右侧为歌词显示区域,支持歌词滚动同步显示。
![登录界面](images/images/user-center1.png)
这是用户登录界面,用户可以在登录界面输入用户名和密码进行登录。界面设计简洁明了,采用卡片式布局,包含用户名输入框、密码输入框和登录按钮。
![注册界面](images/images/user-center2.png)
这是用户登录界面的下半部分,展示了注册账号的链接。用户可以点击注册链接跳转到注册界面,完成账号的创建。
## 2. 音频播放功能实现
音频播放是音乐平台的核心功能,我最初把所有播放逻辑都堆在一个大组件里,结果代码混乱不堪,调试时经常找不到问题所在。后来我重构了播放器,采用了更模块化的设计,才真正体会到了组件化开发的优势。
### 2.1 歌曲播放问题:从混乱到有序
开发初期我直接让AI在App.jsx里写了300多行播放逻辑包括音频元素创建、事件监听、状态管理等。当用户报告部分歌曲无法播放时我花了整整一天才定位到问题——原来有些音频URL返回403错误但我的错误处理代码被淹没在庞大的组件中根本没起作用。
我意识到必须重构:
- 把播放逻辑抽出来创建了独立的AudioPlayer组件
- 编写了`test-audio-urls.js`脚本批量验证所有音频URL的有效性
- 添加了清晰的错误提示,当播放失败时显示"该歌曲暂时无法播放",而不是让播放器沉默崩溃
- 考虑到版权问题,实现了通过服务器代理播放的机制,确保只播放授权内容
重构后播放器代码减少到100多行维护起来轻松多了后来修复自动播放问题时也很快找到了相关代码。
### 2.2 自动播放问题
浏览器出于用户体验和流量节省的考虑对自动播放做了限制。初期我的实现比较简单粗暴页面一加载就直接调用play()方法,结果发现很多用户根本听不到声音,尤其是第一次访问的用户。
后来查资料才知道,现代浏览器要求至少有一次用户交互(比如点击)后,音频才能自动播放。我当时的做法是:
1. 在useEffect里先尝试播放如果失败就记录下“用户想播但被拦了”这个状态
2. 在页面上加了个几乎透明的覆盖层,监听各种交互事件(点击、触摸、按键)
3. 只要用户碰了一下页面,就立刻再试一次播放
4. 播放成功后,把这个覆盖层隐藏掉
虽然有点取巧,但至少能让用户在第一次交互后听到音乐,而不是完全无声。
### 2.3 歌曲切换问题
用户从一首歌的详情页点进另一首歌的详情页时,按理应该自动播放新歌,但实际却没反应。我调试后发现:
· 组件虽然重新渲染了,但音频对象还是旧的
· 路由参数变了,但播放逻辑没跟上
· 有些情况播放器会报错,然后整个功能就卡住了
我花了不少时间才理顺这个流程:
1. 监听路由参数变化
2. 参数一变就清理旧的音频对象
3. 重新加载新歌的数据和音频文件
4. 根据之前的播放状态决定是否自动播放(比如用户之前如果是暂停状态,切歌后就不自动播)
## 3. 我遇到的最大挑战
除了音频播放功能实现中的挑战外,我在开发过程中还遇到了几个重大挑战:
### 3.1 状态管理和路由实现
由于项目采用了React Context API进行状态管理在处理全局状态如用户认证状态需要确保状态的一致性和实时更新特别是在组件间共享状态时容易出现状态不同步的问题。同时由于没有使用专业的路由库在处理复杂路由场景时遇到了一定的困难特别是在解析动态路由参数如歌单ID时需要额外的处理逻辑。
为了解决这些问题我首先对状态管理进行了优化。我使用React Context API创建了AuthContext集中管理用户认证状态通过自定义HookuseAuth方便组件访问和更新认证状态。同时我使用localStorage持久化存储认证信息确保页面刷新后状态不会丢失。
对于路由实现我实现了基于URL路径的简单路由逻辑通过监听popstate事件和手动修改history实现页面导航。在解析动态路由参数时我使用正则表达式匹配URL路径提取所需参数。虽然这种实现方式不如专业路由库完善但在当前项目规模下能够满足需求。
### 3.2 组件间通信
在开发复杂组件时,组件间的通信也是一个挑战。特别是当多个组件需要共享和更新同一个状态时,如何确保状态的一致性和实时更新是一个关键问题。
为了解决这个问题我使用了React的Context API和props传递相结合的方式。对于全局状态如用户认证状态我使用Context API进行管理对于局部状态如组件内部的表单状态我使用组件内部的state进行管理。同时我实现了一些自定义Hook用于封装常用的状态管理逻辑提高代码的复用性和可维护性。
### 3.3 性能优化
项目上线后,有用户反馈页面加载很慢,特别是在网络不好的时候。我自己测试了一下,确实首页要等五六秒才能完全显示,图片也是一张张慢慢“刷”出来的。
我先是打开 Chrome DevTools 的性能面板和网络面板看了一圈,发现几个明显的问题:
1. 打包文件太大:主 JS 文件有 2MB+,用户第一次访问下载时间太长
2. 图片没处理UI 同学给的图都是高清大图,一个 banner 图就 3MB
3. 重复请求多:用户切页面时,同样的接口反复调用
针对这些问题,我做了以下优化:
1. 代码拆分和懒加载
原来所有页面都打包在一个文件里。我用 Webpack 的 dynamic import 把路由按页面拆分,比如用户访问“我的音乐”页,才加载对应的代码。这样首页加载的文件小了快一半。
2. 图片处理
· 让 UI 重新导出适合网页的尺寸(原来 4000px 宽的图真没必要)
· 用 tinypng 压缩了一遍图片
· 对于展示型图片,转成 WebP 格式,体积又小了一半
· 重要的首屏图片加了预加载
3. 缓存和 CDN
· 给静态资源加了合适的 Cache-Control 头
· 把图片、字体这些静态资源放到 CDN 上,用阿里云的 OSS+CDN
· 接口响应里加了 ETag减少重复传输
改完之后,首页加载时间从 5s+ 降到了 2s 以内,效果还是挺明显的。
## 4. 如果重新做一遍
如果重新做一遍这个项目,我会在以下几个方面进行改进:
### 4.1 技术选型
1. 路由管理
一开始觉得项目不大自己用useState和条件渲染简单搞了个路由。结果后来加了页面权限、路由动画、嵌套路由代码就越写越乱。如果重来一开始就会用React Router它的useNavigate、路由守卫这些功能现成的能省很多自己造轮子的工夫。
2. 状态管理
前期为了快全用useState和Context。等到播放器状态、用户登录态、主题设置这些全局状态混在一起时组件间传参就像传纸条一样绕来绕去。后来局部补了点Zustand但要是早点用上状态管理库数据流会清晰很多。
3. 组件库
自己写了按钮、弹窗、输入框但样式不统一改起来也麻烦。看到同事用Ant Design封装好的组件直接用样式还好看。下次项目如果UI要求高会考虑直接用成熟组件库把时间花在业务逻辑上。
### 4.2 架构设计
1. 组件拆分
有些组件写得太“胖”了比如播放器组件既管UI又管逻辑一改就牵一发动全身。后来拆成PlayerUI、PlayerControls、PlayerLogic几个小组件好维护多了。如果一开始就注意职责分离后期重构能少掉不少头发。
2. 响应式适配
虽然做了移动端适配但有些地方只是简单缩放小屏幕上体验不好。比如歌单卡片在手机上堆得太挤按钮点起来费劲。下次应该从设计阶段就考虑多端适配用好CSS Grid和Flex布局而不是靠媒体查询硬调。
3. TypeScript
用JavaScript开发时好几次因为参数传错类型导致页面崩溃都是运行时才报错。后来看到TypeScript能在写代码时就提示类型问题确实能避免不少低级错误。如果项目规模大或团队协作上TS肯定更稳。
### 4.3 质量保障
1. 测试
这次项目几乎没写测试全靠手动点点点。有次改了一个工具函数结果播放器整个不工作了排查半天才发现是函数返回值变了。下次至少该给核心工具函数和组件写点单元测试用Jest简单测一下心里踏实。
2. 性能监控
优化完性能就以为没问题了,但实际用户在不同网络、设备上的表现不清楚。后来接了点前端监控,才发现有些用户加载时间还是很长。如果早点加上性能数据收集,优化会更有针对性。
3. 代码规范
前期大家各写各的缩进、命名都不统一Review代码时看得眼疼。后来上了ESLint和Prettier提交时自动格式化省心不少。这类工具应该项目一开始就配好习惯养成后再改就难了。