本文作者:勤分、流云
2023网易云音乐年度听歌报告已经上线一段时间,你它被刷屏了吗?那开发在其中起到了什么关键作用呢?接下来的文章将从性能体验、质量监控、工程效率、目标分析四个方面一一揭秘。
前言
每年的云音乐年度听歌报告,就像一个靠谱的老朋友,总会在忙碌一年的时光尽头里叩响记忆的大门。
- 如果你曾错过了彼时的年报,不妨现在就拿起手机扫描上图的二维码,与往期的精彩视听来一场不期而遇的邂逅;
- 如果你为年报中精巧而温馨的动画而深深着迷,请直接移步至本文的姊妹篇:「云音乐2023年报动效大揭秘」一探究竟;
- 如果你恰好想了解年报中前端开发承担了什么样的角色、积累了哪些最佳实践 ——那么巧了,本文将从性能体验、质量管理、工程效率和一些笔者底层思考,帮助你逐步揭开年报的神秘面纱
性能体验
首次访问年报活动为例,好的用户体验主要包括以下几个方面:
- 页面能秒级打开,页面到达率高、流失少;
- 页面间转场展示流畅,不会出现卡顿;
- 文本和图片内容在任何设备上都能完整展示,不出现缺失或者加载闪烁情况;
- 音频或视频启播速度快,播放过程中不发生错乱或者卡顿情况;
- 页面内的动效展示流畅,不会出现卡顿;
简而言之,体验优涉及以下几个方面:
1、页面导航:包括首屏秒开,页面转场等
2、资源管理:包括图片、视频、音频和字体包等
3、页面适配:包括文本适配、动效适配和机型适配等
首屏秒开
首屏秒开是指用户从点击链接开始到展示页面内容大约在1s左右完成。整个过程经历如图所示:
容器初始化 -> CDN -> TCP 建连 -> html/js/css 加载解析 -> DOM / CSSOM 解析 -> 渲染布局 -> 绘制
对于前端开发来说,优化难度是从右到左,越到左边就越需要跨团队合作来完成。可以简单的分析总结:
- 在渲染/绘制阶段,可以隔离状态变化频繁的组件,减少无效状态引起的绘制。尽量选择由 GPU 渲染的 CSS3 来实现动效。逻辑实现的动效建议使用
GSAP
。 - 在 DOM / CSSDOM 解析阶段,可以减少 DOM 的嵌套深度,减少使用 JavaScript 直接修改元素样式,减少不必要的 CSS,减少使用 CSS 选择器等。
- 在 HTML / JS / CSS 加载解析阶段,可以通过构件工具对文件进行压缩。利用离线包能力,将这些资源提前下载到本地。
- 在 CDN、TCP 建连阶段,更多依赖 App 网络库底层的优化,如使用 HTPP/2 减少 TCP 连接数。
- 在容器初始化阶段,为了达到极致的打开速度,可以将 H5 容器进行预初始化。也可以建立容器复用池,减少容器创建的耗时。
页面管理
页面路由
为了有效管控年报中多个视图的高效展示和切换,采用了 SPA 的形式对H5进行组织,同时为页面路由提供了路由表的配置。
路由表简单理解是各个子页面路由对象的集合,这个集合可以是全局数组对象,本地文件,或者服务端下发的配置。集合内的顺序决定了用户看到报告页顺序。这样也可以根据产品的述求,灵活调整集合内的顺序,这样就能动态调整页面顺序了。
各个子页面路由对象的属性具体如下。建议不用传统的 path,因为子页面数量多,且名称很难记忆,可以使用 routerIndex,这是子页面在交互稿中的位置代号,方便开发和调试。其中 ignoreSwipe 是使用在下节手势处理中「子容器接管父容器手势」的场景。
export interface PageProps {
model: unknown;
position?: number; // 页面埋点使用
}
export interface PageRouteProps {
c: ComponentType<PageProps>;
cId: string; // 当前页面唯一id
routerIndex: number | string; // 路由索引
ignoreSwipe?: boolean; // 是否忽略滑动,默认false
}
手势处理
年报项目中用户可以通过点击、左右滑动、上下滑动来切换页面。为了防止手势冲突,全局只有一个父容器,各个报告页面是子容器;一些手势频控、页面状态变化等通用逻辑统一在父容器中实现。只在父容器中使用 hammerjs
做手势监听,子容器不再负责页面切换的手势监听,关键代码如下。
hammer = new Hammer(reportRef.current);
hammer.get('swipe').set({ direction: Hammer.DIRECTION_ALL });
hammer.on('swipeleft', onNextPageWrap);
hammer.on('swiperight', onPrePageWrap);
hammer.on('swipeup', onNextPage);
hammer.on('swipedown', onPrePage);
对于子容器,可能会有以下几种特殊情况:
情况一:如果子容器需要感知用户手势事件,可以监听父容器发出的自定义事件。
// 【翻页】动效:下一页
export const ON_PAGE_NEXT = 'ON_PAGE_NEXT';
// 【翻页】动效:上一页
export const ON_PAGE_PREV = 'ON_PAGE_PREV';
情况二:如果子容器需要完全接管父容器的手势监听事件,例如年度歌手相关的所有页面。首先需要在路由表中将 ignoreSwipe=ture 设置忽略手势,然后在监听父容器发出的通知,进行自定义的事件处理。最后当子容器接管结束后,需要根据需要再次触发父容器的切换事件。关键代码如下:
const onNextPage = useCallback(
(nextAction) => {
if (currentPage >= len - 1) {
nextAction(); // 结束接管,再次触发父容器的切换事件
return;
}
setCurrentPage(currentPage + 1);
},
[currentPage, len]
);
useEffect(() => {
bus.on(ON_PAGE_NEXT, onNextPage);
return () => {
bus.off(ON_PAGE_NEXT, onNextPage);
};
}, [onNextPage, onPrePage]);
情况三:如果子容器存在特定区域需要响应特点手势,例如歌手来信页面左右切换是查看歌手来信。这时候需要子容器调用stopPropagation主动阻止手势向父容器传递。
转场实现
在路由表和手势处理准备就绪后,最后来看看页面之间转场的实现。年报页面的转场效果使用React官方实现的 react-transition-group 组件。由于篇幅限制,这里不详细介绍react-transition-group 组件的底层原理。结合路由表顺序和当前页面位置,通过 z-index 和 match 来控制子页面的层级和显示隐藏。使用 CSSTransition 实现页面间的进场和退场CSS动画。关键代码如下:
(pages || []).map((item, index) => {
// zIndex 和 match是关键代码
const zIndex = (pages.length - index) * 100;
const match = index === currentIdx;
return (
<div
key={item.cId}
style={{
zIndex,
pointerEvents: match ? 'auto' : 'none',
overflow: 'hidden',
}}>
<CSSTransition
in={match}
timeout={100}
...
appear
unmountOnExit>
<item.c
model={item.model}
position={index} />
</CSSTransition>
</div>
);
})
但是以上的页面转场存在一个问题,即页面之间只能存在一种转场方式。如何自定义页面之间的转场效果?基本思路是各自页面维护自己的转场效果;大部分页面只需将转场信息配置到路由表中;小部分页面可以通过页面上下文获得上一个或者下一个页面的信息,动态决定如何进场或者退场。基于该思路,改造路由表对象,新增一个 TransitionParams 协议,并且提供渐隐渐显的默认转场实现。关键代码如下:
export type TransitionParams = {
timeout: number | { appear?: number | undefined; enter?: number | undefined; exit?: number | undefined };
classNames: CSSTransitionClassNames;
};
export interface PageRouteProps {
c: ComponentType<PageProps>;
cId: string; // 当前页面唯一id
routerIndex: number; // 路由索引
transition: TransitionParams; //默认是渐隐渐显的转场效果
ignoreSwipe?: boolean; // 是否忽略滑动,默认false
}
CSSTransition 配合改造后的关键代码如下:
<CSSTransition
in={match}
timeout={item.transition.timeout}
// 关键代码
classNames={item.transition.classNames}
appear
unmountOnExit>
<item.c model={item.model} position={index} />
</CSSTransition>
资源管理
资源管理主要任务是将网络资源下载到本地,最终将本地资源加载到内存,以便程序可以使用这些资源。优化资源管理可以有效提高年报用户体验。通常开发者会通过压缩资源的大小,并通过内容分发网络(CDN)加快资源的下载速度。但是除了这些还有其他通用的方法呢?
在介绍具体优化手段前,先来看以下关键字,这些是性能优化的通用方法。
- 提前 preload:提前准备必要的资源,提升加载速度
- 同步 sync:串行执行当前任务,确保执行任务的优先级
- 异步 async:工作线程异步执行,处理比较耗时的操作,不阻塞主线程
- 懒加载 lazy:又称按需加载,不浪费请求
- 缓存 cache:将资源缓存到内存或者磁盘本地,减少不必要的网络请求
- 延迟 defer:不立即执行任务,延迟执行
总结如下图:
接下来,将从图片、视频、字体包等各个资源,进一步解析如何结合上述关键词进行优化。
图片
关键字:提前 preload、懒加载 lazy、缓存 cache
图片资源占整个年报项目资源中的比例是最高的,大概 70% 左右。所以图片展示速度是否足够快和内容是否完整都会直接影响用户体验。
优先将图片资源使用 tinypng 进行手动压缩,在不失真的情况下,保证图片大小足够小。其次正确选择图片格式能有效减少图片大小。其中图片格式很多,主流的有:
- SVG 是基于XML的矢量图片格式,不失真无限放大。支持动画。
- JPEG 是有损压缩,不支持透明度或者动画。
- PNG 是无损压缩,支持透明度。APNG 是 PNG 的扩展,支持动胡奥。
- WebP 是无损和有损压缩,支持动画或者透明度。
- GIF 是位图图片格式,支持动画。
不同图片格式在不同场景上使用。格式没选准确,会导致资源浪的费。如在「年度总览」一页中,海浪🌊背景是一张PNG格式,大小为 1.7MB。但是该场景不需要透明,选择JPEG后大小为 96kb。总结如下是选择图片格式的流程图。
小图标或 logo 可以使用 SVG。其它能用 WebP 尽量使用 WebP。对于 WebP 的兼容性问题,可以通过业务封装的图片组件进行处理,不能使用 WebP 则兜底变成 PNG ,因为 PNG 兼容性最好。GIF 尽量不适用。对于超过特定大小的动图,建议使用CSS动效或者视频替代。
在已经压缩图片和选择正确的图片格式的前提下,会在当前报告页面提前 preload 预加载下一页面的图片资源,并将图片缓存cache在本地。
预下载的方式有多种,可以自动全量下载,也可以手动按需下载。
自动全量下载,可以基于上文 CSSTransition 的 in 参数。不只是匹配当前页面进行渲染,也提前渲染下一页。自动下载的方案存在缺点比较明显,如:不能按需下载;页面的生命周期和用户感知不一致,导致一些逻辑提前执行如页面曝光埋点。
let matchIndex = -1;
(pages || []).map((item, index) => {
const zIndex = (pages.length - index) * 100;
const match = index === currentIdx;
if (match) {
matchIndex = index;
}
return (
<div
key={item.cId}
style={{
zIndex,
pointerEvents: match ? 'auto' : 'none',
overflow: 'hidden',
}}>
<CSSTransition
// in 这里是关键代码
in={match || (index === matchIndex + 1)}
timeout={item.transition.timeout}
classNames={item.transition.classNames}
appear
unmountOnExit>
<item.c model={item.model} position={index} />
</CSSTransition>
</div>
);
})
相较自动下载,手动按需下载更加可控。手动按需下载那些图片可以选择更接近用户体感的 LCP(Largest Contentful Paint)原则。因为在业务页面加载阶段,命中 LCP 的元素可能会发生变化,所以这里主观选择可能命中 LCP 的图片元素进行预下载。如下图,最终选择A、B、C、D这个四张图片进行预加载。
手动下载的方法有多种。可以基于三方库 pxloader
进行再一次封装。如果将 React 升级到19后,系统默认提供了 preload API,更多API详情见此链接。
import { preload } from 'react-dom'
// 下载字体包
preload('https://.../path/to/font.woff', { as: 'font' })
// 下载样式表
preload('https://.../path/to/stylesheet.css', { as: 'style' })
// 下载不知道的文件类型
prefetchDNS('https://...')
手动下载的时机可以监听页面切换,根据当前页面信息在路由表中获取到下一个需要预加载的页面信息。最终手动下载的伪代码如下:
const preload = new PreLoader();
const usePreLoader = ({ pages, currentIdx }: PreLoadSourceProps): void => {
useEffect(() => {
const preLoadIndex = currentIdx + 1; // 提前预加载
const item = pages[preLoadIndex];
if (item.cId === YearOverviewIdentifier) {
preload.add([A, B]);
preload.start();
}
...
}, [currentIdx, pages, reportInfo]);
};
视频
关键字:提前preload、同步sync
和图片同样的思路,先明确视频的尺寸,不同尺寸大小的视频资源大小也不一样。在视频尺寸正确的前提下,在做视频体验优化才能事半功倍。在项目初期准备 6 种视频,相同视频内容,网络环境下,用不同系统的机型进行压测。这 6 种视频,分别是:
- 宽1242、高2688、FPS50
- 宽1242、高2688、FPS25
- 宽1080、高2388、FPS50
- 宽1080、高2388、FPS25
- 宽720、高1625、FPS50
- 宽720、高1625、FPS25
压测得出的实验结论是:
- 安卓 10-13,分辨率高于 2400 的 6 种视频大小都能体验,但宽1242 & 高2688 尺寸的视频基本上会有卡顿;
- 安卓 10-13,分辨率低于 2400,宽1242 & 高2688 该尺寸的视频无法进行体验;
- 安卓 10 以下的,只能体验宽720 & 高1624 该尺寸下的视频。
- iOS 系统 13-16,体验都正常,iOS12 系统,宽1242 & 高2688 & FPS50 和宽1080 & 高2338 & FPS50无法进行体验。
最后根据实验结论,结合视频效果和资源大小的考虑,最终采用三种尺寸的视频,分别是:
- 宽1080、高2388、FPS50,命名为 w1080FPS50
- 宽720、高1625、FPS50,命名为 w720FPS50
- 宽720、高1625、FPS25,命名为 w720FPS25
总结如下是选择视频尺寸大小的流程图。w1080FPS50 体验最优,w720FPS25 兼容性最好。开发可以根据不同的机型、系统选择合适的视频。
为了让用户在点击封面页面的开始按钮后能流畅观看视频,选择在封面页面渲染完成后,同步 sync 添加视频页面。通过 zIndex 将其隐藏在封面页后面,利用用户游览封面页的间隙,提前 preload 创建 video 组件。同时,设置<video>
的 preload='auto',让游览器结合网络等自身条件自动决策是否预加载视频。
即使选择好合适的视频资源后,也需要兜底处理一些播放的异常情况,防止播放失败影响体验。可以监听onWaiting
回调,如果在规定时间内如果没有再次触发onPlay
回调,会直接手动执行onEnd
回调的事件。也可以在onCanPlay
回调中启动视频超时定时器,在规定范围内系统没有自动触发到onEnd回调,那也会直接手动执行onEnd回调的事件。
音频、字体包
关键字:延迟defer,懒加载lazy
音频在工程中通常有两种播放能力:WebAudio H5 原生播放能力和通过RPC方式调用客户端原生播放能力。
在站内场景中,通常推荐使用客户端 RPC 提供的播放能力,因为它可以复用端上播放的基础能力,如播放音质、启播时长等都有优化。如果站内想要绕过某些播放权限,会选择 H5 原生播放能力。而在站外,只能使用H5原生播放能力。为了简化开发接入,封装 audioManager 业务组件,提供统一的API接口,抹平站内、站外的兼容性问题。
对于字体包,通常会懒加载 lazy 选择视觉设计中使用到的字体包。针对固定文案的情况下,使用工具裁剪掉多余的字体,从而达到最小字体包。也会在 header 中延迟 defer 下载字体包的资源,以避免阻塞封面页的渲染。在封面页面不使用特殊字体包的前提下,可以在封面页面设置不可见的<p>
标签,静默下载字体包,从而让后续报告页面里的特殊字体不出现跳变。
小结
可以组合使用不同的优化手段来提高性能,但切记物极必反。例如在年报项目开发过程中,为了实现歌手子页面转场的效果,会将 6 个子页面提前加载。在开发早期,各个页面渲染复杂度低,不会出现问题。但在后续为了提高视觉效果,加入了各种噪点、混合、粒子效果后,在低端机设备上,该模块在切换时容易出现白屏现象。最后定位是子页面提前预加载过多,内存占用大,使得端上收到 OOM 警告,回收 H5 容器,从而导致了白屏。最后,采用懒加载 lazy 加载,同一时间最多显示 3 个页面,这样既保证子页面转场的流畅,也保证了功能的正常使用。
页面适配
用户手机机型千变万化,页面适配是必须要面对的问题。开发之前先明确两个关键的点:站内是否支持全屏;站外是否需要支持。明确后结合工程现状,将需要适配的重点机型进行枚举,并归纳总结,以 iPhone 机型为例如下:
如果只适配站内全屏/非全屏,建议将适配的机型宽高比控制在 2 个以内。举例年报只支持站内全屏,如下图第二列所示,可以将站内适配划分成 2 档,通过媒体查询,所以只需支持宽高比大于等于 375 / 667,适配范围支持站内宽屏或者小屏的机型。针对特殊页面,还可以配 合max-height 再做微调。
@media screen and (min-aspect-ratio: 375 / 667) {
// 大于等于 0.5622
// 适配范围:站内宽屏、特殊小屏的机型
}
@media screen and (max-height: 750px) {
}
如果需要适配站外,建议将适配的机型宽高比控制在 4 个以内。如下图第三列所示,分析历史站外流量分布,重点支持微信、微博等 App。可以将站内、外适配划分成四档。第一档需支持宽高比大于等于 400 / 815 且小于 375 / 667,适配范围支持15pro、12promax、15promax、vivo s9 等站外+大屏。第二档需支持宽高比大于等于 375 / 667 且小于 375 / 603,适配范围支持 8p、SE 等站内+宽屏、小屏。第三档需支持宽高比大于等于 375 / 603,适配范围支持8p、SE 等站外、宽屏+小屏。
@media screen and (min-aspect-ratio: 400 / 815) and (max-aspect-ratio: 374 / 667) {
// 大于等于 0.4907,小于等于 0.5607
// 适配范围:15pro、12promax、15promax、vivo s9 等 站外+大屏
}
@media screen and (min-aspect-ratio: 375 / 667) and (max-aspect-ratio: 374 / 603) {
// 大于等于 0.5622,小于0.6218
// 适配范围:8p、SE 等 站内+宽屏、小屏
}
@media screen and (min-aspect-ratio: 375 / 603) {
// 大于等于 0.6218
// 适配范围:8p、SE 等 站外、宽屏+小屏
}
质量监控
面向年报这种大型活动,针对质量问题的感知不能仅被动通过用户反馈问题,更重要的是需要一套完善的监控系统自动发现问题。通过这套系统也能够有效评估出线上运行的状态,最后用数据来验证“质量优”这个技术指标。
对于开发者而言,质量优的背后实质是高可用。需要对各种异常结果进行兜底,来保证用户完整体验完年报活动。简而言之,质量优涉及以下几个方面:
1、异常监控:包括 crash 平台、实时数据监控平台,离线日志回捞平台等
2、功能降级:包括 AB 配置中心,上线 SOP 白皮书,活动研发平台等
3、数据准确:包括异常数据兜底,敏感数据过滤,埋点数据等
异常监控
除了必备的异常 crash 监控平台,还需要根据年报活动的特性来构建一个更全面的监控体系。主要包括分享率监控、视频卡顿监控、音频启播失败监控、接口异常监控等。由于监控的多样性,需要根据不同的场景采用不同的监控策略。例如,如果想观察分享点击率,需要实时上报监控数据;如果需要排查页面白屏问题,需要收集用户本地的离线数据。由于年报日活高,样本数据量大,需要考虑是否需要采样上报。建议实时数据采用一定的采样率,而离线数据则采全量上报。
监控的思路是:现状分析,指标建设,监控埋点,指标分析,方案优化,AB 实验,验证收益。PACD 的方式持续改进,直到问题被解决。
以分享率监控为例。活动分享率要达到xx%是年报关键指标。分析工程中现状后,制定如下图的监控指标。
结合线上埋点数据,能够清晰发现图片生成耗时和图片生成成功率对图片分享成功率有正向影响。因此,后续开发的重点就是如何降低图片耗时生成和提高图片生成的成功率。
功能降级
监控的本质是及时发现问题并快速止损。在面对突发情况时,通过线上配置快速关闭某些非核心功能,以确保核心功能的正常进行。在开发中过程中,可以将降级开关集中配置在一个能进行可视化的活动研发平台内统一管理,如下图。在上线前,需要将这些开关纳入上线前的标准操作流程(SOP)中。
下图是年报的监控大盘。对可能严重影响用户体验的功能,如白屏、视频和音频进行了重点监控,同时也对关键业务模块,如报告页面和歌手来信进行了监控。这些监控在年报活动也发挥了重要的作用。例如,通过对报告页面接口的监控,发现由于 cookie 丢失导致用户进入不了年报的问题;通过对音频播放的监控,明确了站内需要支持音视频的自动播放。
数据准确
最后数据准确性也是质量优的重要组成部分。其中需要关注两个方面。首先,需要确保用户界面的数据准确无误,这包括对服务端可能出现的异常情况进行兜底处理,例如服务端下发数据失败或者下发敏感数据等情况需。其次,要确保上报后台的埋点数据不会漏报、重复报或者缺失关键信息。这些埋点数据的准确性直接影响策划和开发的实时决策。
工程效率
除了体验好、质量优,效率高也是开发一直追求的命题。
对于策划或者视觉来说,需求的频繁变更是项目最大的风险。这要求开发团队能够预见并总结可能出现变更的情况。例如,页面顺序会根据内测用户的反馈进行调整,页面数量可能会根据线上页面的流失率进行删除。在例如,视觉要求页面之间有统一的转场效果,但是针对某些特殊页面,要求工程应该能够支持自定义的转场效果。
对于 QA 或者客服来说,当用户反馈问题时,他们应能够通过快捷方式查看该用户的年报。同时,由于年报通常包含 30+ 页面,他们希望能有一种快速定位到特定页面的方法。通过这种方式,他们可以自助定位并解决部分线上客诉。在排除了用户自身、数仓或者服务端的问题后,再将问题提到前端。
对于开发者来说,期望有一套开箱即用的基础组件,如图片、视频、音频等。或者能够在项目创建初期,就能有一个包含基础交互、数据模型和常用基础组件的年报模板。更进一步是,希望在开发过程使用使用D2C的插件,通过视觉稿直接生成代码。更终极的状态是,策划和运营通过搭建平台能自助地构建出年报项目。
简而言之,效率高涉及以下几个方面:
1、页面导航:包括页面自动曝光、支持动态路由等
2、功能调试:包括年报快捷查看,页面快速定位等
3、工程基建:包括通用组件/能力,年报模板,D2C 插件,搭建平台等
为了实现各个活动之间的能力复用,可以将活动成果都会统一沉淀到活动研发平台。
这个平台覆盖了活动的完整生命周期,包括开发前期需要参考的技术方案,UI组件,通用能力,活动模板,开发中期需要的功能开关、分享内容等配置,以及开发后期需要用到保障SOP和监控告警等。
后续在年报项目的初期阶段,计划通过活动研发平台的年报模板工程,快速搭建出年报的项目。基于这个初始化工程,数据开发团队能尽早进行的自测稽查。
深度思考
最终年报项目按照预期顺利拿到业务结果。再次回顾立项初期,开发并不是简单被动接收目标,简单的将需求实现。可以从业务和技术关系分析出发,定性、定量分析项目目标是否能够达成。
关系分析
业务和技术的关系可以划分为三大类别:业务驱动技术、技术保障业务、技术引领业务。
业务驱动技术的一个典型例子是2020年报中的DIY音乐人物形象。这是开发第一次在大型项目中使用 three.js。项目的初期,需要做大量的技术调研,并需要快速解决一些从未碰过的难题。项目的过程中,由于技术局限性,策划不得不妥协,对需求进行调整。在业务驱动技术的情况下,大部分情况是未知的,这会使得开发处于高度紧张的状态,也可能导致技术动作的变型。
技术引领业务的一个典型例子是性格POP。在这个项目中,开发主导了整过程,他们基于矩形树图算法实现一个无缝挤压的动效。策划团队根据这个特定的动效,定制业务需求。在技术引领业务的情况下,由于整个过程因为都是已知的,开发都是胸有成竹的状态,这通常会使业务的收益超出预期。
大部分的需求都是属于技术保障业务的情况。这要求开发对当前的工程能力有清晰的认知,并协助策划做出最合理的决策。开发需要科学分析业务目标是否能达成,可以有效地管理策划的心理预期。
需要多积累技术知识,减少业务驱动技术的被动情况出现。同时也需要提升对业务的敏锐度,让技术引领业务的发展。最后将知识和经验沉淀,从而更好保障业务的需求。
定量分析
2023年报就是典型的技术保障业务的场景。在业务立项初期,产品目标是日活xx千万,活动分享率 xx%。
项目初期项目负责人不应埋头搬砖,需要先通过现有数据,理性分析业务目标是否能达成。
分析显示,目前 Android 和 iOS 双端的日活累计是X千万。这个数字实际设定了年报日活跃用户的上限。如果这个上限都不能满足业务目标,那开发需要寻找更多的推广渠道。除了现有的移动端设备,可以考虑其他有多终端设备,如PC、iPad和TV,还可以考虑支持例如微信等站外渠道。这样开发阶段,需要重点考虑如何适配这些不同的用户界面。
在确定投放渠道之后,可以进一步分析每个渠道内的投放位置。例如,在移动端通常会选择在首页首帧 banner、首页弹窗、以及其他高日活的页面进行投放。细化分析每个位置的用户点击率,最终能初步预估活动的日活。在投放位置有限情况,如果这个预估值无法达到业务目标,那么需要额外开发其它点击率较高的位置,如启动开屏位,供策划选择。
在不同角色中,对分享率这个指标的定义可能会有所不同。因此,在项目启动的前期,开发需要和策划达成一致,明确如何统计活动的分享率。在明确统计口径后,分析现有的分享行为,包括图片分享、链接分享、口令分享和截屏分享。需要注意,截屏分享是最容易忽略统计的一种分享行为。接下来,分析不同分享行的流程。如下图所示列出了不同分享行为所需要经过的路径。
在这些路径下进行数据埋点,以便能够观察和分析影响分享率的漏斗。通过结合对漏斗的专项治理和过往活动的数据,最终也能准确预估年报的数据。
定性分析
日活和分享率很大程度取决于年报的产品创意是否足够新颖。产品创意需要将用户的听歌数据以字体、图片、动效、音频、视频等多种方式准确地展示给用户,从而引发用户的共鸣。而作为开发者,需要以流畅、准确、且高效的方式将这些多元的媒体内容传达给到用户。
案例一:得益于今年年报对体验和质量的高要求,上线后 5 日总客诉量比往年减少了 41%,收获了大批用户好评。
案例二:首页banner投放,从用户点击到 H5 页面打开,页面达到率 Android 端只有93%左右。假设将页面到达率从 93% 优化到 97% 以上,对年报带来收益大概是是新增上百万的日活用户。
因此,好的用户体验和高的产品质量能够有效地促进年报的分享,从而进一步提升日活跃用户数量。
总结
一款深入人心的作品,不仅要有优质的产品内容支撑,有效的技术优化和保障也不可或缺,具体总结如下图:
最后本文从2023年度报告中的性能体验、质量监控和工程效率等方面出发,介绍了笔者在年报项目经历中的一些探索和经验。受限于篇幅,难免有不足之处,欢迎共同讨论~
最后
更多岗位,可进入网易招聘官网查看 https://hr.163.com/
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。