原项目是什么
yin-yizhen/sonic-topography 是一个基于 Web Audio API 的音频可视化播放器,但它的本质是一个本地应用,而不是网站。
它的架构是这样的:
- 前端:React + Vite,
npm run dev启动开发服务器。 - 后端:通过 Vite 插件嵌入了一个 Node.js 脚本(
local-server.mjs),提供网易云音乐的搜索、歌词、播放地址接口。 - 播放列表:存储在项目根目录的
data/playlists.json文件中,本地持久化。 - 启动方式:一个命令
npm run dev即可,前后端合在一起。
关键点:它只有“本地”这一个模式。Vite 启动后,前端请求 localhost:7200(Node 服务)来获取网易云数据。没有远程代理的概念,也不支持切换到其他后端。
为什么我想改它
原项目很好用,但有几个地方让我觉得可以更灵活:
- 无法纯静态部署:如果我只有静态托管服务(比如 Vercel、Netlify),我就没法用这个应用,因为它依赖后端的 Node 服务。
- 端口写死:本地代理固定用 7200 端口,如果端口被占用或者我想换一个,就得改代码。
- 只能本地玩:我想把它部署到服务器上供朋友使用,但原项目的设计是面向单机的。
于是,我决定基于它做一个“增强版”:让这个应用既能在本地运行,也能纯静态部署(依赖远程代理),还能作为一个独立服务跑在服务器上。
我做了什么
1. 增加在线模式(远程代理)
我引入了“在线/本地”模式切换的概念:
- 本地模式:和原项目一样,请求
http://localhost:7200的 Node/Go 服务。 - 在线模式:请求一个可自定义的远程 Worker(如 Cloudflare Workers),实现纯静态部署。
这样,前端可以完全脱离本地后端运行,只要有一个远程代理地址即可。用户只需要把前端 dist/ 部署到任何静态托管服务,然后配置一个 Worker 地址,就能正常使用。
2. 自定义端口
在本地模式下,我添加了“端口”修改功能。用户可以直接在界面侧边栏点击“Port”按钮,输入新的端口号,无需修改代码或重启服务。端口号会保存在 localStorage 中,下次打开自动沿用。
3. 用 Go 重写后端(并保留 Node 作为备选)
原项目的 Node 后端和 Vite 深度绑定,无法独立运行。我新增了一个 Go 版本的后端:
- 可独立部署:编译为二进制,跑在任意服务器上。
- 可内嵌前端:通过
embed将前端dist/打包进去,实现“一个文件即完整应用”。 - 也可纯 API:只提供接口,前端单独部署。
这样,用户就有了多种选择:用原来的 Node 后端、用新的 Go 后端、或者纯前端 + 远程 Worker。
4. 播放列表从文件改为 localStorage
原项目的播放列表存在 data/playlists.json,这是本地文件,在多设备或纯静态部署场景下并不适用。我将其改为前端 localStorage 存储,这样无论部署在哪里,用户自己的浏览器数据都在。
我的设计思考
为什么要保留“本地模式”?
因为我希望开发者依然可以像原项目一样,一条命令跑起完整应用进行开发调试。本地模式提供了最快的反馈循环。
为什么还要“在线模式”?
因为我想让应用真正“可部署”。只要有一个远程代理(一个简单的 Cloudflare Worker),前端就可以被托管到任何 CDN,变成一个真正的网站应用。
为什么播放列表不用后端?
因为我希望后端尽可能“轻”和“纯”。它只做代理,不做持久化。播放列表是用户个人的数据,保存在浏览器里最自然。如果有跨设备同步的需求,那是另一个话题了。
为什么提供 Go 版本,而不只是改进 Node?
因为 Go 的部署更简单,编译后是单文件,无需安装 Node 环境。加上 embed 功能,连前端文件都能打包进去,部署流程变得极其简单。这对服务器部署场景非常友好。
最终成果
我发布了 Sonic Proxy v1.0.0,相比原项目,新增了:
- ✅ 在线/本地模式切换(支持远程 Worker)
- ✅ 本地端口自定义(界面直接修改)
- ✅ Go 版本后端(纯 API / 内嵌静态双版本)
- ✅ 播放列表迁移到 localStorage
- ✅ 完全兼容原项目的前端体验
而原项目的核心功能——音频可视化、歌词同步、频率触发、播放控制——全部保留,一丝未动。
感受
这次改造让我体会到,好代码不只在于写得好,更在于“好改”。Sonic Topography 的代码结构清晰,让我可以顺利地在它上面做扩展,而不是重写。
我也更深刻地理解了“部署”的多样性:本地应用、网站应用、自托管服务、纯静态应用…… 它们各有各的适用场景。让一个应用能适配多种场景,比只做一个单一形态的应用更有价值。
最后,这个项目也让我更熟练地掌握了 Go 的 embed、React 的优化技巧,以及如何在不破坏原有体验的前提下进行功能增强。
如果你也喜欢这个项目anagasyat/Sonic-Topography,或者有类似的需求,欢迎来我的 GitHub 看看。音乐继续,代码不止。🎵
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时
