generated from Java-2025Fall/final-vibevault-template
161 lines
10 KiB
Markdown
161 lines
10 KiB
Markdown
# 前端开发反思报告
|
||
|
||
> 请参考 `FRONTEND_GUIDE.md` 了解写作要求。建议 600–1200 字。
|
||
|
||
---
|
||
|
||
## 1. 我的界面展示
|
||
|
||

|
||
这是VibeVault音乐平台首页的上半部分界面,采用现代化的卡片式布局,展示了精选推荐内容,包括"放松时刻"、"动感节拍"和"怀旧金曲"三个推荐歌单卡片。界面设计简洁明了,色彩搭配协调。
|
||
|
||

|
||
这是VibeVault音乐平台首页的下半部分界面,展示了热门歌曲列表,包含江南、小酒窝、曹操等热门歌曲,每首歌曲显示排名、名称、歌手和时长信息。用户可以直接点击歌曲进行播放。
|
||
|
||

|
||
这是歌单详情界面,展示了歌单的详细信息,包括封面图片、名称、描述和歌曲列表。用户可以在歌曲列表中选择歌曲进行播放,也可以添加新歌曲或删除现有歌曲。界面左侧为歌曲列表,右侧为当前播放歌曲的详细信息。
|
||
|
||

|
||
这是歌曲播放界面,显示了当前播放的歌曲信息,包括封面图片、标题、歌手和专辑。界面中央为播放控制区域,包含播放/暂停、上一首、下一首等控制按钮。右侧为歌词显示区域,支持歌词滚动同步显示。
|
||
|
||

|
||
这是用户登录界面,用户可以在登录界面输入用户名和密码进行登录。界面设计简洁明了,采用卡片式布局,包含用户名输入框、密码输入框和登录按钮。
|
||
|
||

|
||
这是用户登录界面的下半部分,展示了注册账号的链接。用户可以点击注册链接跳转到注册界面,完成账号的创建。
|
||
|
||
|
||
|
||
## 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,集中管理用户认证状态,通过自定义Hook(useAuth)方便组件访问和更新认证状态。同时,我使用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,提交时自动格式化,省心不少。这类工具应该项目一开始就配好,习惯养成后再改就难了。
|
||
|