Senka Viewer
Senka Viewer是一个展示从网页游戏《艦これ》获取到游戏的战果数据(得分排名),经过数据处理、结果预测,并经由前端展示的网站。
这个项目前前后后做了差不多一年了(18 年 01 月份开始做的),由简单到复杂,从前到后都做了相当多的工作。现在我想写这篇文章,做一个简单的分享。
初衷
游戏内查看战果数据其实是有限制的,只能看到某个玩家在某个时间点上的数据,而且游戏数据每天更新两次,分别是日本时间的 3:00 和 15:00;无法得知过去玩家的战果值,无法表现玩家的战果值的数据的变化趋势。
一旦知道了玩家数据的变化趋势,就可以对玩家的行为做一定的预测分析,甚至能预测月底的情况(游戏中有些特定的点能获取大量战果,而且以月为周期刷新,经常有玩家利用这个进行瞬间反超的操作,被称为“战果炮”)。
其实之前也有人做过类似的网站,不过搞这个仿佛是知道了某些人的“秘密”似的,有人对网站充满敌意,不断地用 DOS 去攻击网站,造成网站瘫痪,最后负责维护的人不得已放弃网站。
最初我们做的目的是继承之前人的工作,把数据准确、及时的展示给需要的人,再有就是要扛住这些“恶人”的攻击。
开始
18 年一月份第一次找到我,大致是想让我做一个展示上传到服务器上数据的网站,当时我正在期末考试之前复习考试,突然让我来写前端,其实一开始我是不想弄的,但可能是因为不停地复习,我自己也有些许的厌倦了,便接受了下来。
后端返回几个 json 接口,我想这就是典型的前后分离的模式,于是直接照着我之前项目的方式,用 react
+ react-router
写了个简单的单页应用。
做好了之后,大家发现效果还不错,觉得或许可以加上图表展示。我又用 echarts
在原来的基础上加上了几张图表。
慢慢地,项目的问题出现了:单页应用导致前端构建出来的文件非常的大。接着我准备去优化这个项目。
新的工具
就在差不多的时间点上,webpack 出到了 4.0,我想要借用 webpack 4 的“力量“去优化项目。
当时的 webpack 处于一个东西刚出,但没有其他项目跟进的状态,很多老的插件都没开始兼容新的 webpack。在折腾了好久总算能跑通后,发现优化的效果微乎其微。
还尝试了新的 api splitChunks
,依旧没有太大的变化。
服务端渲染
从 1 月到 3 月整个网站都处于无人问津的状态,虽然有通过微博宣传过,但实际使用的用户实在是少的可怜。4 月份的时候,我们想要对网站进行整体的优化,其中优化的重点就在于 SEO 上。
首先我就想到用 react 服务器渲染,因为能同时够解决下面两个问题:
- 首屏优化
- SEO
使用 Next.js 很快就把原来的单页应用给迁移成了一个服务端渲染项目,首屏加载时间过长的问题和 SEO 的问题一下子就解决了。使用服务器渲染后,我们的网站很快就被 google 收录了。
i18n 化
网站 SSR 化之后,突然有一天我们发现 google analytic 上当日访问量骤增,惊奇地发现绝大多数的访问来源是来自推特的。在推特上搜索了下“Senka Viewer”,发现是有一个日本的玩家无意间看到了我们的网站,发了条推并附上我链接,接下来这个链接就一下子在推特上火了起来。
这次的事件让我们意识到了其他语言玩家的重要性,毕竟玩家群体里不止只有懂得汉语的人,为了使华语圈、日语圈和英语圈的玩家都能看得懂我们的网站,我决定对网站进行 i18n 化,支持中文、日语和英语。i18n 的效果也十分的好,网站的传播速度越来越快了,传播带来的价值也得到了提升。
还是不够
通过几个月的观察,我们发现网站的流量总是集中在月底(月底会根据玩家的战果发放奖励)。为了防止 DOS 的攻击,网站后端计算后的数据都是直接存在内存里的,到了月底这些数据大概能占到 3GB 的内存,加上如此大的访问流量,月底的时候服务器经常会撑不住。而且这么大的数据量对于前端的性能也有很大的影响。所以,之前做的那些工作还远远不够,如何去解决现在眼下的问题就是我之后做的这些工作。
缓存
7 月之后我来到某互联网公司实习,刚到不久便听了一场隔壁数据组的分享:
他们组有一个数据看版,上面的数据需要经过一个耗时非常非常长的计算,而且数据并不要求实时性。所以他们在前端和后端的中间做了一层缓存;同时前端用了 service worker 做了一层请求代理。
当时直接就联想到了 Senka Viewr 这个项目,于是我决定从这两方面着手去优化。
后端
后端的主要是利用 node 中台服务端渲染的页面和接口数据进行缓存。这里利用了时间差,和同事的分享采用了相同的方式。
- 没有缓存渲染页面,并放入缓存中
- 存在缓存则直接调取之前的缓存,同时异步渲染页面更新缓存
这样使得存在缓存的时候,用户总是能直接从缓存中获取页面,减少了处理和渲染的时间。同时异步更新页面缓存,使页面不至于总是不刷新。虽然存在明明后台数据已经更新了,但是用户得到的页面依旧是老的情况,不过用户再等待刷新就能拿到新的,所以并没有太大的问题。
前端
虽然使用了服务端渲染,但是页面需要加载的静态资源文件还是没有减小,这些文件的变化只随着发版变化。所以我想到用原本用来做离线应用的 server worker 做文件缓存。先预缓存一些已知的静态文件,再拦截页面请求,匹配 .js
和 .css
结尾的静态文件。
新的尝试
经过两波大的优化,页面的访问体验大幅的提升。随着不断地传播扩散,我们的用户也越来越多了。7 月 31 日甚至达到了 6k+的访问人数,页面 pv 达到了 1w+。现在 11 月,在平静之后日访问人数基本稳定在 1k~3k 了。

远远还没结束,我还想在这个项目上尝试更多新的东西。例如,后端对 json 格式的数据进行了缓存,但是到了月底,json 的大小会变的十分的大,传输起来还是比较耗时的。我又想到吧 json 格式的数据用 protobuf 转换成二进制格式的数据,再 push 到前端,这样处理的数据大小大概为原来的 25%,效果十分的明显。再有就是兼容性,测试发现 IE10 也是能够正常访问的。
接下来
在我眼中,这个项目始终没有完善,其实还有很多可以去探索的点。
一个是我想做动态展示每一个时间点用户排名变化的过程,更类似比赛比分变化的那种,更具有观赏性。(2018-12-19 完成)
另一个是想更完整的去了解一个同构应用的体系结构,去尝试弄一个更符合自己风格的同构应用模式。