李季骏 小红书 社区前端工程师

前端狗

2019/07/09 发布于 编程 分类

GMTC2019 

文字内容
1. 从重新认识前端渲染开始,⼩小红书的前 端性能监控及优化实践 李李季骏 ⼩小红书社区前端⼯工程师
2. 在此键入姓名 在此键入tittle
3. 在此键入姓名 在此键入tittle
4. ⾃自我介绍 2016 年年底加⼊入⼩小红书⾄至今,⽬目前任职于社区前端组,负责了了包括⼩小红书前端⼯工程化、服务端同构、混合 开发容器器层建设(WebView、React Native)等⽅方向。 对于跨平台混合开发场景有丰富的实践,并在效率、性能等⽅方向累积了了⼀一定的⼯工程化解决⽅方案经验。
5. ⽬目录 • App WebView 开发模式给前端开发者提出的挑战,传统的(已有 的) Web 渲染性能衡量方式的不切实用 • 核心性能体验指标的梳理和工程化的采集/监控方案 • 基于关键渲染帧的过程拆解,和多个场景下的实践 • 借助 App Webview 的容器能力下的探索 • 一点工程化的思考
6. 衡量量 Web 渲染性能前,⼏几个需要被解答的问题 • 提炼影响用户决策的感官指标 • • 跨实现的统一衡量手段 • • client-side-render 与 server-side-render 的横向⽐比较 End-to-End 的采集方式 • • 渐进式的渲染过程(⻣骨架屏、⾸首屏) 采集来⾃自于⽤用户的真实体验 拆解影响感官指标的过程因素,尝试归因并优化 • • 找寻关键过程的关键影响因⼦子(⽹网络、机型) 单节点的优化和验证能⼒力力
7. 提炼影响⽤用户决策的感官指标 The Metric The Experience First Paint (FP) / First Contentful Paint (FCP) First Meaningful Paint (FMP) Is it happening? Did the navigation start successfully? Has the server responded? Is it useful? Has enough content rendered that users can engage with it? Time to Interactive (TTI) Is it usable? Can users interact with the page, or is it still busy loading? Long Tasks (technically the absence of long Is it delightful? tasks) Are the interactions smooth and natural, free of lag and jank? https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#_1
8. 传统的(已有的) Web 渲染性能衡量量⽅方式的不不切实⽤用 “ 它们能帮你分析你的⽹网⻚页可能存在的症结; 它们不不太了了解你的⽹网⻚页在不不同设备的运⾏行行情况; 甚⾄至不不能告诉你你在完成⼀一项优化⼯工作后给⽤用户带来了了多少价值; 它们不不应该成为你开展优化⼯工作的起点或终点; ” —— lighthouse, Web Page Test
9. 在真实⽤用户的设备上衡量量这些指标 • 基于 JS 的统计实现原理 基于 Mutation 观察每⼀一次渲染帧,并根据适⽤用的算法计算 // Paint-timing collector observer = new MutationObserver(records => { records.forEach(record => { 出 FCP, FMP 等关键渲染帧 timing if (record.type === 'childList') { recordNodes(record.addedNodes) } }) pushObservedPoints() }) observer.observe(document) 事实上,这段 code 还能另你重新认识和理理解你的应⽤用是如 何被渲染的,尤其是当 MVVM 的 Web 编程思想⼤大⾏行行其道
10. ⼯工程化的采集/监控⽅方案 采集 处理理 消费 JS SDK —— Collector Emitter Translator —— Visualization —— Frontend Engineering, then we have data
11. 透过数据被量量化放⼤大的问题 client-side-render 和 server-side-render 的 tradeoff 2500ms / 1750ms client-side-render server-side-render PWA、可以充分调动本地缓存的能⼒力力 ⾸首屏更更快 渐进式的⾸首屏体验 HTML ⽆无法缓存 ⾸首屏渲染依赖 JS 执⾏行行完成 渲染时序处理理不不当⻚页⾯面可能出现多次跳闪 ⽹网络故障时,⽤用户可能⾯面对⻓长时间的⽩白屏
12. 巨⼤大的 JavaScript 启动开销 ⽐比起服务端渲染/客户端渲染,可以将启动成本是均摊到整个⽣生命周期,是前端渲染与之⽐比较下难以逾越 的鸿沟的本质 // Example Component create() { http.get(’foo’).then(res => { this.foo = res.foo }) }
13. 巨⼤大的 JavaScript 启动开销 • dynamic import // code-splitting import(‘foo’).then(foo => { // do something }) // dynamic import const importFoo = () => ( Promise.resolve(require(‘foo’).default) ) importFoo().then(foo => { // do something }) • redundant packages
14. 透过数据被量量化放⼤大的问题 600ms PWA 就可以实现解决“秒开零白屏”的效果么,哪些因素干扰了骨架图的出现? • • 理理解关键渲染路路径 理理解浏览器器绘制
15. 调整脚本加载策略略 “defer 的脚本被完全缓存时,并没有遵守规范等待解析结束,反⽽而阻塞 了了解析与渲染。”
16. 透过数据被量量化放⼤大的问题 渲染时序的混乱,渲染不稳定 1350ms ~ 3150ms
17. 理理解 Vue 的渲染触发机制 Register dom-update task which batcher (watcher) cost large calculation on dom diff by a microtask. One event loop update dom
18. 渲染时序完全由⽹网络决定 // Main component // Main component mounted() { // Main component this.fetchNotes().then(notes => { mounted() { Promise.all([ this.notes = notes this.fetchNotes(), }) this.fetchTags(), this.fetchTags().then(tags => { this.fetchGallery(), this.tags = tags ]).then([notes, tags, gallery] => { }) this.notes = notes this.fetchGallery().then(gallery => { this.tags = tags this.gallery = gallery this.gallery = gallery }) } }) }
19. 通过 Vuex 控制数据流,从⽽而控制渲染时序 // Vuex Getters function notes(state) { return state.Note.notes } function tags(state) { return state.Note.ready ? state.Tag.tags : [] } function gallery(state) { return state.Note.ready && state.Tag.ready ? state.gallery.pics : [] }
20. ⼩小红书借助 App Webview 的容器器能⼒力力下的探索 Create Webview Instance 资源内置 Load HTML 数据预传、数据预取 Load CSSs Load Scripts Parse HTML Calculate Stylesheets ⽩白屏 • 并行关键渲染路径上的部分过程 • 空间换时间 Load APIs Evaluate Scripts Evaluate Scripts ⻣骨架 Parse HTML Evaluate Scripts ⾸首屏 TTI
21. 资源内置 如何拦截?如何存储?如何更新(下发)? 如何拦截 如何存储 如何更更新(下发) PWA service worker:基于浏览器器能 Browser Storage ⼒力力的⽹网络层拦截 基于 service worker 的策略略配 置(前端可控) Bowl 改变资源的引⽤用⽅方法,基于 JS Browser Storage library 能⼒力力 基于业务实现的策略略配置(前 端可控) ⼩小程序 基于 Native 能⼒力力 完全由平台策略略决定 Native App Storage Target:⾼高定制化,低侵⼊入的资源内置设施;简单⾼高效的资源更更新(下发)策略略
22. 拦截和存储 Customized Storage Interceptor Memory cache Match Rules Disk storage Webview Distribution Service resources: request:'>request: s.xhs.com/**/main.175cae.js cache_key:'>key: s.xhs.com/**/main.175cae.js CDN HTML: request:'>request: www.xhs.com/item/1000123 cache_key:'>key: s.xhs.com/**/index.6045eb9.html
23. 资源更更新(下发) Application Image Container Mobile CD CI Static Resources CDN Distribution Service
24. 数据预传、数据预取 一些在 Native 开发生态下成熟的解决方案在混合开发场景下的应用 • 数据预传(强依赖⼊入⼝口⻚页) • • • • 数据携带的协议 数据使⽤用的 API 底层 Cache 的打通(图⽚片) 数据预取(⽬目标⻚页⾃自治) • • 数据使⽤用的 API 预取规则的下发
25. 充分借助客户端能⼒力力,前后端混合渲染⽅方案 Create Webview Instance Load HTML fragments and APIs Load HTML from disk Load resources from disk Parse HTML ⽩白屏 Calculate Stylesheets ⻣骨架 Parse HTML Evaluate Scripts ⾸首屏 TTI
26. ⼀一点⼯工程化的思考 • 数据能力 • • 采集 -> 处理理 -> 可视化(监控/实验) 优化解决方案 • • 持续集成/交付 对传统 web 应⽤用分发形式的打破(分发、容灾)
27. 在此键入姓名 在此键入tittle
28. 在此键入姓名 在此键入tittle
29. THANKS THANKS! THANKS!