前端面试每日-31-第147天

今天的知识点 (2019.09.10) —— 第147天[html] 本地存储的生命周期是什么?[css] 请问background-attachmentn属性有什么用途?[js] 阻止事件的默认行为有哪些?说说它们之间的区别是什么?[软技能] 前端的性能统计有哪些指标?《论语》,曾子曰:“吾日三省吾身”(我每天多次反省自己)。 前端面试每日3+1题,以面试题来驱动学习,每天进步一点! 让努力成为一种习惯,让奋斗成为一种享受!相信 坚持 的力量!!!欢迎在 Issues 和朋友们一同讨论学习! 项目地址:前端面试每日3+1 【推荐】欢迎跟 jsliang 一起折腾前端,系统整理前端知识,目前正在折腾 LeetCode,打算打通算法与数据结构的任督二脉。GitHub 地址 微信公众号欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个Star, 同时欢迎微信扫码关注 前端剑解 公众号,并加入 “前端学习每日3+1” 微信群相互交流(点击公众号的菜单:进群交流)。 学习不打烊,充电加油只为遇到更好的自己,365天无节假日,每天早上5点纯手工发布面试题(死磕自己,愉悦大家)。希望大家在这浮夸的前端圈里,保持冷静,坚持每天花20分钟来学习与思考。在这千变万化,类库层出不穷的前端,建议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢迎大家到Issues交流,鼓励PR,感谢Star,大家有啥好的建议可以加我微信一起交流讨论!希望大家每日去学习与思考,这才达到来这里的目的!!!(不要为了谁而来,要为自己而来!)交流讨论欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个[Star] https://github.com/haizlin/fe...

September 10, 2019 · 1 min · jiezi

时至5G时代是否还有必要谈前端性能优化

之前,何同学的视频在网上活了一阵子。引发了我们思考:5G将会给我们带来什么。同时也回顾了4G乃至3G时代已经给我们带来了哪些新的变革。最近,一个问题总是时不时的冒出我的脑海:前端性能优化时候还有必要? 回顾前端性能优化 然后我找到了 雅虎军规 的 35 条 尽量减少 HTTP 请求个数——须权衡使用 CDN(内容分发网络)为文件头指定 Expires 或 Cache-Control ,使内容具有缓存性。避免空的 src 和 href使用 gzip 压缩内容把 CSS 放到顶部把 JS 放到底部避免使用 CSS 表达式将 CSS 和 JS 放到外部文件中减少 DNS 查找次数精简 CSS 和 JS避免跳转剔除重复的 JS 和 CSS配置 ETags使 AJAX 可缓存尽早刷新输出缓冲使用 GET 来完成 AJAX 请求延迟加载预加载减少 DOM 元素个数根据域名划分页面内容尽量减少 iframe 的个数避免 404减少 Cookie 的大小使用无 cookie 的域减少 DOM 访问开发智能事件处理程序用 link 代替 @import避免使用滤镜优化图像优化 CSS Spirite不要在 HTML 中缩放图像——须权衡favicon.ico要小而且可缓存保持单个内容小于25K打包组件成复合文本我们归档一下这里我们着重说明的网络相关的优化,而非浏览器端性能上的: 1.尽量减少 HTTP 请求个数——须权衡5.使用 gzip 压缩内容10.减少 DNS 查找次数11.精简 CSS 和 JS13.剔除重复的 JS 和 CSS15.使 AJAX 可缓存17.使用 GET 来完成 AJAX 请求29.避免使用滤镜31.优化 CSS Spirite32.不要在 HTML 中缩放图像——须权衡33.favicon.ico要小而且可缓存34.保持单个内容小于25K35.打包组件成复合文本然后就剩下这么几个了。作为现在前沿的前端技术,webpack已经帮我们做了5,11,13,33,35。而且其中的13.剔除重复的 JS 和 CSS,在框架盛行的时代,似乎我们已经选择基于框架的覆写而非直接修改框架的方式来构建我们的代码,因为维护成本。也就是说,我们在成本权衡下回做适当的放弃13.与此同时,在 resultful 盛行的今天,17. 使用 GET 来完成 AJAX 请求也不能满足需求,而被部分舍弃。然后字体图标的流行,把31. 优化 CSS Spirite的问题也变成了历史。接着我们看看还剩下些什么: ...

June 17, 2019 · 1 min · jiezi

????-记一次前端性能优化

工作中一直在做一款公司内部的BI工具,将数据可视化的报表赋能给业务人员,报表配置者通过简单的拖拽操作即可生成报表。随着系统不断的完善,加上运维推广,我们积累了越来越多的用户。这时候用户体验的方方面面都体现出来了。我们也停下产品的功能迭代,将整个系统进行优化,旨在提升用户体验。以下是我对前端项目的优化总结。 Webpack 打包优化项目中在使用的 Webpack 版本是3.x,本次优化的方案仍然是基于Webpack3.x版本的 Vue 脚手架进行优化。升级4.x在计划中。。。 之前也总结过一次 Webpack 2.x 在Vue2.x项目中的应用,提到过 Webpack 工程的一些优化方案,以下算是一个补充。 开启Gzip尝试了下开启gzip,直接受益还是比较大的。下面是实际项目中打包结果。 Parsed的js,1.38M Gizpped的js - 421.46K 通过数据分析,减少了70.28%的打包体积。 开启方式,在脚手架中修改配置文件:/config/index.js // 生产模式build: { productionGzip: true // 开启Gzip压缩}同时服务端 nginx 加入配置项 gzip on;gzip_min_length 1k;gzip_buffers 4 16k;gzip_comp_level 6;gzip_types application/javascript text/plain application/x-javascript text/css application/xml text/javascript application/json;gzip_vary on;重启 nginx 后刷新页面,在Chrome develop tools中 Network 查看网络链接 Request Headers 中出现 Accept-Encoding: gzip 代表客户端能够理解 gzip 压缩编码方式 Response Headers 中出现 Content-Encoding 代表服务端指明以 gzip 编码方式对数据进行压缩 ...

May 12, 2019 · 3 min · jiezi

react-hook超实用的用法和技巧分析

react hook发布也已经有几个月了,相信有部分人已经开始使用了,还有些人在犹豫要不要用,可能更多人安于现状,没有要用的打算,甚至还有很多公司的react版本是15或以下的,迫于升级的难度没有使用。以我个人的观点,要不要使用react hook呢? 建议用的的人 项目react版本已经是react16了新建的项目一直对新技术保持关注,跃跃欲试的人对函数式编程爱好的人对react的componentDidMount,componentWillReceiverProps,componentDidUpdate厌烦,甚至因为重新渲染整天在头疼的人不建议用的人 对react hook极其厌恶,对react生命周期编程是非爱好的人。只要你想,没有不建议用的人,包括第一类人。这只是我个人的建议,我现在用的周期也不长,我们的项目是react 16的,并且团队里只有我自己在写ract hook。幸好react hook和生命周期编程方式是完全兼容的。 那么其实react hook的特点和优点其实也显露出来了。 1. 没有了显性的生命周期,所有渲染后的执行方法都在useEffect里面统一管理2. 函数式编程,你不需要定义constructor,render,定义class3. 某一个组件,方法需不需要渲染,重新执行完全取决于你,而且十分方便管理4. 肯定还有我没发掘的优点针对以上的特点优点我逐一说明,对于特别基础的用法我就不大篇长论了,建议参考官网的说明文档:react官网 1. 没有了显性的生命周期,所有渲染后的执行方法都在useEffect里面统一管理上代码(伪): function getData(id) { const [data, setData] = useState({}); useEffect(() => { const data = api.getData(id); setData(data); }, [id]); return <div>{data.name}</div>}这是根据id获取数据显示name的组件。因为这个id是外部传入的,在以前你需要再didMount,willReceiverProps里面去判断是否传入的和当前的不一样,然后去获取数据,但是这里就不用了。直接集成在useEffect里面。最关键的是第二个参数[id]。这个参数的意思是id变了才进入里面的方法执行,方然第一次必执行。当然我说的不全面,大致是这个意思,还有更复杂的场景,反正这种方式类似于监听id,id变了就执行,这不就是我们的最终目的吗?react以前分那么多周期其实就是处理这一件事情 2. 函数式编程,你不需要定义constructor,render,定义class这个就不用多说了吧 function heihei() { const [count, setCount] = useState(0); return ( <div> {count} <button onClick={() => setCount(count + 1)}>增加count</button> </div> )}no生命周期,no class,一切都是函数式编程 3. 某一个组件,方法需不需要渲染,重新执行完全取决于你,而且十分方便管理这里主要讲两个方法,useMemo和useCallback先看useCallback之前如果我们在render中定义了一个方法: render() { const {data} = this.state; const filter = data.filter(e => e.id !== 5); ...}那么我们知道每次render都会执行filter这个方法,其实你是不是觉得当data没变这个方法只要执行一次就好了,看看react hook怎么做的 ...

April 30, 2019 · 1 min · jiezi

2019-前端框架对比及评测

Jacek Schae 原作,授权 LeanCloud 翻译。 我们将基于 RealWorld 示例应用对比前端框架。RealWorld 示例应用的特点: RealWorld 应用比待办事项类应用更复杂。通常待办事项类应用不足以传达足够多的知识见解构建实际应用。 标准化项目遵循特定规则。提供后端 API、静态标记语言、风格、API 规范。 专业人士编写、审阅理想情况下,会是高一致性、高真实度的项目,由使用该技术的专业人士编写或审阅。 比较的库和框架撰写本文时,RealWorld 示例应用仓库共包括 18 个 Conduit (Medium.com 克隆应用)实现。 本文不考虑框架的流行程度,RealWorld 仓库中列出的前端框架皆纳入对比范围。 测度性能应用显示内容、可以使用需要花多久? 尺寸应用有多大?我们只比较编译后的 JavaScript 文件大小。所有应用使用同样的 CSS 样式文件,CSS 文件加载自 CDN。所有应用使用的 HTML 也是一样的。这些框架都支持编译或转换为 JavaScript,所以我们仅仅测量 JavaScript 文件大小。 代码行数根据规范创建 RealWorld 应用需要多少行代码?公平地说,某些实现的功能要略微多一点,但这应该没有什么显著的影响。我们仅仅测量每个应用的 src/ 目录。 性能我们将使用 Chrome 的 [Lighthouse Audit] 测试性能。Lighthouse 返回 0 至 100 间的评分。0 为最低分。 配置所有测试均使用如下配置: 性能评分基于以下测度得出: First Contentful Paint (页面中内容元素首次渲染时间)First Meaningful Paint (页面中有意义的内容元素首次渲染时间)Speed Index (页面加载过程视觉上的变化速度)First CPU Idle (到 CPU 首次空闲的时间)Time to Interactive (到页面可交互的时间)Estimated Input Latency (预计输入延迟)详见 Lighthouse 评分指南。 ...

April 24, 2019 · 1 min · jiezi

Web渲染那些事儿

作为开发者,经常需要面对影响整个应用架构的决策。而Web开发者的核心决策之一,就是应用逻辑与渲染工作的实现,应处于架构中的什么位置(译注:客户端 or 服务器?)。现在有很多不同构建网站的方法,因此这些决策变得愈加困难。我们对这一领域的理解,来自于我们过去几年在 Chrome 工作中,与大型网站的交流。从广义上讲,我们鼓励开发人员考虑通过一种称为 rehydration 的方式,进行服务器渲染或静态渲染。为了更好地理解在做出决定时所选择的架构,我们需要对每种方法有充分的理解,并且在谈到它们时使用一致的术语。术语渲染SSR:服务器渲染(Server-Side Rendering)——在服务器上将客户端或通用(universal)应用程序渲染成HTML。CSR:客户端渲染(Client-Side Rendering)——在浏览器中渲染App,通常使用DOM。Rehydration:在客户端上“启动” JavaScript 视图,复用服务器渲染的HTML DOM树和数据。(译注:利用服务器返回HTML中的JS数据,重新渲染页面的技术,详见知乎讨论,其中《三体》的部分很形象~)预渲染(Prerendering):在构建时运行客户端应用程序,以将其初始状态捕获为静态HTML。性能TTFB:首字节时间(Time to First Byte)——从点击链接 到 接收第一个字节内容 之间的时间。FP:首次绘制(First Pain)——第一次有像素对用户可见的时间。FCP:首次内容绘制(First Contentful Paint)——请求内容(文章正文等)变得可见的时间。TTI:可交互时间(Time To Interactive)——页面变为可交互的时间(事件绑定等)。服务器渲染(Server Rendering)服务器渲染,指在服务器中生成整个页面的HTML,以此响应请求的技术。这样做避免了在客户端上进行数据获取的额外往返(round-trips)和模板处理,因为这些工作在浏览器获得响应之前,已由服务器处理了。服务器渲染通常会得到快速的首次绘制(FP)和首次内容绘制(FCP)。在服务器上运行页面逻辑和渲染,可以避免向客户端发送大量 JavaScript,有助于实现快速的可交互时间(TTI)。这之所以行得通,因为服务器渲染的本质,只是向用户浏览器发送文本和链接。这种方法适用于广泛的设备和网络,并能触发一些有趣的浏览器优化,比如流文档解析。使用服务器渲染,用户不再需要在客户端上等待 CPU 相关的 JavaScript 处理后,然后才能访问站点。即使第三方JS无法避免,使用服务器渲染来减少自己的JS成本,也能提供更多的性能“预算”。但是,这种方法有一个主要缺点:在服务器上生成页面有一定耗时,可能会导致较慢的首字节时间(TTFB)。服务器渲染是否满足应用程序,很大程度上取决于构建目标的体验类型。关于服务器渲染与客户端渲染的正确应用存在长期争论,但重要的是我们可以选择对某些页面使用服务器渲染,而对其余页面不使用。一些网站已成功采用混合渲染技术:Netflix 服务器渲染其相对静态的落地页面,同时为交互繁重的页面预拉取JS,为这些重客户端页面提供更快的加载能力。许多现代框架、库和架构,使得在客户端和服务器上渲染相同的应用程序成为可能。这些技术可用于服务器渲染,但是要注意,在服务器和客户端上进行渲染的架构,都是各框架自家的解决方案,具有不同的性能特点和权衡。React 用户可以使用 renderToString() 或在其上构建的解决方案如 Next.js,用于服务器渲染;Vue 用户可以查看 Vue 的服务器渲染指南或 Nuxt;Angular 有 Universal。大部分流行的解决方案采用某种 hydration 的形态,因此在选择工具之前要注意使用的方法。静态渲染(Static Rendering)静态渲染在构建时进行,并提供快速的 FP、FCP 和 TTI——假设客户端JS的体积得当。与服务器渲染不同,它还致力于实现始终如一的快速首字节时间(TTFB),因为页面的 HTML 不必动态生成。通常,静态渲染意味着提前为每个 URL 生成单独的 HTML 文件。通过预先生成 HTML 响应,可以将静态渲染部署到多个 CDN 以利用边缘缓存。(译注:也就是“页面静态化”)静态渲染的解决方案选择很多,像 Gatsby 这样的工具旨在让开发人员感觉他们的应用程序是动态渲染的,而不是构建过程生成的。Jekyl 和 Metalsmith 提供更多模板驱动的方法,更加符合它们的静态特质。静态渲染的一个缺点是必须为每个可能的 URL 生成单独的 HTML 文件。 如果无法提前预测这些 URL 的内容,或者对于具有大量不同页面的网站,这可能具有挑战性甚至是不可行的。React 用户可能熟悉 Gatsby、Next.js 静态导出或 Navi ——它们都可以方便使用组件。但是,了解静态渲染和预渲染之间的区别非常重要:静态渲染页面是无需执行太多客户端 JS 就可交互的,预渲染则改进了单页面应用的 FP 或 FCP,由于是单页面应用,所以必须等待客户端启动过程,以使页面真正具有交互性。(译注:简单的说静态渲染不依赖客户端JS,适用于静态页面,而预渲染则依赖JS,更多是为了富应用的初始界面加速)如果不确定选择静态渲染还是预渲染方案,请尝试此测试:禁用JavaScript并加载创建的网页。对于静态渲染的页面,大多数功能在未启用JavaScript下仍然正常运作。而对于预渲染页面,一些基本功能(如链接)能正常展现,但页面其余部分无法正常展现。另一个有效的测试是使用 Chrome DevTools 减慢网络速度,并观察在页面变为可交互之前已下载了多少 JavaScript。预渲染通常需要更多的 JavaScript 来实现交互,并且这些 JS 往往比静态渲染使用的渐进增强方法更复杂。服务器渲染 vs 静态渲染服务器渲染并不是银弹——它的动态特性带来显著的计算成本。许多服务器渲染解决方案会有耗时,导致延迟的 TTFB 或成倍的数据传输(例如,客户端 JS 所需的内联状态)。在 React 中,renderToString() 可能很慢,因为它是同步和单线程的。服务器渲染“正确”的姿势,可能涉及查找或构建组件缓存方案、内存消耗管理、应用记忆化技术以及许多其他方面。同一个应用程序通常需要多次处理/重建——一次在客户端中,一次在服务器中。因此服务器渲染可以使某些东西更快地显示出来,但并不意味着可以减少工作量。服务器渲染为每个 URL 按需生成 HTML,但速度可能比仅提供静态渲染内容要慢。如果加以进行额外的工作,服务器渲染 + HTML缓存,可以大大减少服务器渲染时间。服务器渲染的优势在于,能够提取更多“实时”数据,并响应比静态渲染更完整的请求集。个性化页面就是一个不适用于静态渲染的页面类型代表。在构建 PWA 时,服务器渲染也抛出一个有趣的问题。 整个页面使用 Service Worker 缓存,与服务器渲染部分内容片段,哪个方案更好?客户端渲染(Client-Side Rendering,CSR)客户端渲染(CSR)意味着使用 JavaScript 直接在浏览器中渲染页面。 所有逻辑、数据获取、模板和路由都在客户端处理,而不是服务器上。客户端渲染很难在移动端做到很快。如果做好压缩工作,严格控制 JavaScript 预算,并在尽可能少的 RTT 中提供内容,它可以接近纯服务器渲染的性能。使用 HTTP/2 Server Push 或 <link rel = preload> 可以更快地提供关键脚本和数据,这将使解析器更快地完成工作。像 PRPL 这样的模式值得评估,以确保初始和后续导航的即时感。客户端渲染的主要缺点是,随着应用程序的发展,所需的 JavaScript 数量会增加。随着添加新的 JavaScript 库、polyfill 和第三方代码,更是一发不可收拾。这些代码会竞争处理能力,并且通常必须在渲染页面内容之前完成处理。构建依赖大型 JavaScript 的 CSR 应用时,应该考虑积极的代码分割,并确保延迟加载 JavaScript——“只在需要时提供所需内容”。对于很少或没有交互性的页面,服务器渲染可以作为更具扩展性的解决方案。对于构建单页应用程序的人来说,识别大多数页面共享的UI核心部分,意味着可以应用 Application Shell 缓存技术。与 Service Worker 相结合,可以显著提高重复访问的感知性能。通过 Rehydration 将服务器渲染和 CSR 相结合这种方法通常被称为通用渲染或简称为“SSR”,它试图通过两者兼顾来平滑客户端渲染和服务器渲染之间的权衡。页面请求交由服务器处理,将应用程序渲染为 HTML,然后把用于渲染的 JavaScript 和数据,嵌入到生成的文档中。只要处理得当,这就像服务器渲染一样实现了快速的 FCP,然后通过称为 (re)hydration 的技术,在客户端上再次“拾取”来渲染。这是一种新颖的解决方案,但也具有一些明显性能缺陷。译注:如果这里不好理解,请先理解上面术语部分中 Rehydration 的知乎链接内容。rehydration 后的 SSR 主要缺点,是它会对可交互时间(TTI)产生显著的负面影响,即使它改善了首次绘制(FP)。SSR 页面通常看起来具有欺骗性的加载完成和可交互性,但在执行客户端JS并绑定事件处理之前,页面实际上无法响应输入。这在移动设备上可能持续几秒甚至几分钟。也许你自己也经历过这种情况——在页面看起来已经加载后的一段时间内,点击或触摸什么都没反应。这很快变得令人沮丧……“为什么没有反应? 为什么我不能滚动?“一个 Rehydration 问题:应用的双重成本由于JS特性,Rehydration 问题往往比延迟交互更糟糕。为了使客户端 JavaScript 能够不用重新请求服务器,就能准确地获取服务器返回的用于呈现其 HTML 的所有数据,当前的 SSR 解决方案通常将UI的数据响应序列化, 以 Script 标签形式存放在 HTML 中。结果是生成的 HTML 文档包含大量重复片段:正如你所看到的,服务器除了返回应用程序 UI 以响应页面请求,还返回了用于组成该 UI 的源数据,以及生成相同 UI 的实现代码,即刻在客户端上运行。只有在 bundle.js 完成加载和执行后,页面才会变为可交互。从使用 Rehydration SSR 站点收集的性能数据显示,这种用法应极力避免。归根结底,原因归结为用户体验:很容易让用户处于“不明所以”的状态。Rehydration SSR 也不是没有希望。在短期内,仅将 SSR 用于高度可缓存的内容,可以减少 TTFB 延迟,从而达到与预渲染类似的结果。流式服务器渲染和渐进式 Rehydration服务器渲染在过去几年中发展迅猛。流式服务器渲染能以 chunk 形式发送 HTML,浏览器可以在接收时逐块渲染。这促成了快速的 First Paint 和 First Contentful Paint,因为 HTML 标签更快地到达用户侧。在 React 中,流在 renderToNodeStream() 中异步处理,相比于同步的 renderToString,服务器的压力也会更小。渐进式 Rehydration 也值得关注,React 一直在探索。使用这种方法,服务器渲染后的页面各部分,随着时间推移被“启动”,而不是通常一次初始化整个应用程序的做法。这可以减少页面可交互所需的 JavaScript 量,因为可以延迟页面低优先级部分,以防止阻塞主线程。它还可以帮助避免最常见的 SSR Rehydration 陷阱:服务器渲染的DOM树被破坏后立即重建——通常是因为客户端初始同步渲染所需的数据还没准备好,比如还在等待 Promise 的解析。部分 Rehydration部分 Rehydration 已被证明难以实现。该方法是渐进式 Rehydration 概念的扩展,通过分析渐进式 Rehydration 的各个部分(组件/视图/树),识别出那些不具交互性的部分。对于每个基本静态的部分,相应的 JavaScript 代码会被转换为惰性引用和装饰功能,将其客户端占用空间减少到接近于零。部分 Rehydration 方案伴随着自身的问题和妥协。它为缓存带来了一些有趣的挑战,我们无法假设服务器渲染的惰性部分 HTML,在页面完整加载前是可用的。三方同构渲染(Trisomorphic Rendering)如果可以使用 service worker,“trisomorphic”渲染也很有意思。该技术是指,利用流式服务器渲染初始页面,等 Service Worker 加载后,接管 HTML 的渲染工作。这可以使缓存的组件和模板保持最新,并启用 SPA 式的导航以在同一会话中渲染新视图。当可以在服务器、客户端页面和 Service Worker 之间共享相同模板和路由代码时,此方法最有效。SEO 考虑在选择渲染策略时,团队通常会考虑 SEO 的影响。为了让爬虫能够轻松获得“完整页面”,服务器渲染是不二的选择。虽然爬虫可能会理解 JavaScript,但是在渲染方式上的局限性需要注意。如果你的应用非常重 JavaScript,最近的动态渲染方案也是个值得考虑的选择。如果有疑问,Mobile-Friendly Test 工具对于测试你选择的方法是否符合预期,非常有用。它展示了 Google 爬虫渲染页面的预览、序列化的 HTML 内容(执行 JavaScript 后),以及渲染过程中发生的错误。总结在决定渲染方式时,需要测量和理解真正的瓶颈在哪里。静态渲染或服务器渲染在多数情况都比较适用,尤其是可交互性对JS依赖较低的场景。下面是一张便捷的信息图,显示了服务器到客户端的技术频谱: ...

March 4, 2019 · 2 min · jiezi

阿里云ARMS重磅推出小程序监控,助力小程序稳定运行

2018年是小程序蓬勃发展的一年,各大公司如腾讯、阿里、百度、头条等都陆续推出了自己的小程序,小程序已成为一个未来必然的趋势、移动互联网的新风口。据数据统计,目前已上线的微信小程序已超过100万,支付宝小程序、钉钉E应用、百度智能小程序、头条小程序等也在不断发力。由于小程序具有:无需下载、触手可及、用完即走、无需卸载的特性,所以用户体验对于小程序来说非常重要,一旦出现小程序卡顿,缓慢和错误,需要及时发现并修复,否则用户流失的概率会非常大。小程序与H5的不同小程序和H5都属于移动端场景下的技术选择方案,那么这里介绍一下小程序与H5的不同。运行环境的不同传统的H5的运行环境是浏览器,包括webview,其中浏览器提供window、document等BOM对象小程序的逻辑层和渲染层是分开的,逻辑层运行在JSCore中,并没有一个完整的浏览器对象,所以缺少相关的DOM API和BOM API开发成本的不同H5的开发,涉及到开发工具、前端框架、模块管理工具、任务管理工具、UI库的选择、接口调用工具及浏览器兼容性等小程序的开发,指定环境的小程序会提供开发者工具、API及规范的开发标准。由于小程序是跑在指定的环境下的,同时API是指定环境下提供的,所以不用考虑浏览器的兼容性。在H5开发中,前端常用的HTML/CSS在不同的小程序中都有指定的文件标准。例如:在微信小程序中使用WXML/WXSS在支付宝小程序、钉钉E应用中使用AXML/ACSS在百度智能小程序中使用SWAN/CSS…开发规范在指定的官方文档中都会有明确的使用介绍,使用方法与原来H5的开发大同小异,所以上手开发相对容易。使用体验的不同H5页面需要在浏览器中渲染,在复杂的业务逻辑或者丰富的页面交互时会有卡顿情况小程序除首次使用略慢,页面切换及跳转等非常顺滑,接近Native通过以上几点小程序和H5的不同的介绍,我们可以发现原来针对H5页面的监控无法直接监控小程序;同时由于小程序封闭性较强,不同的小程序在标准上也略有不同,如微信小程序、支付宝小程序及钉钉E应用等等小程序在使用标准及开放的API方面也会有一些差异,所以针对小程序的监控与针对Web应用的监控会有所不同。小程序监控的现状现在针对小程序监控的大概分为以下几类:小程序的数据统计分析,助力小程序运营相关产品: 微信小程序助手、阿拉丁小程序统计平台等特点:大部分是针对微信小程序提供相应的数据统计分析能力,从多维度分析小程序相关用户数据,适用于小程序运营,但缺乏对于用户体验,小程序性能的监控小程序错误监控相关产品: FunDebug等特点:监控小程序使用户出现的错误,帮助开发者发现并解决小程序错误,但缺乏对于小程序全局性能的监控,对于缓慢请求,缓慢页面没法监测小程序性能监控相关产品: FrontJS、听云小程序监控等特点:主要提供性能相关数据,包括JS错误、网络请求响应情况等。但是只支持微信小程序,而且没有办法把小程序的性能与后台应用的性能关联起来,没法形成端到端的监控通过上面对现有的小程序监控产品分析,存在以下问题:无法支持所有的小程序监控,主要支持微信小程序支持多类小程序监控的产品,提供的小程序相关数据较少,主要集中在错误监控没有后台应用服务的性能监控,无法从小程序上的性能问题追溯到后台应用代码和数据库,无法形成端到端的监控基于以上情况,阿里云ARMS前端监控重磅推出小程序监控,旨在帮助端到端的快速定位小程序问题,提升小程序的用户体验。提供的能力阿里云ARMS前端监控此次重点推出的小程序监控有以下特点:1. 覆盖各类符合标准规范的小程序首先解释一下这里所说的"标准规范的小程序",即包含App和Page两层:App用来描述整体程序,包含: onError事件Page用来描述各个页面,包含: onShow、onHide、onUnload事件小程序的运行环境依赖于对应的客户端,各类小程序的DSL设计看起来很像,但细节上的差别还是比较多,并且已有了分化的趋势。在这种情况下,阿里云ARMS前端监控为了更好的支持小程序的监控诉求,提供以下小程序监控的场景:微信小程序支付宝小程序钉钉E应用其他类别小程序由于小程序发展迅速,现在无法针对各类小程序都提供对应的监控SDK,所以不属于微信小程序、支付宝小程序和钉钉E应用的小程序可选择其他类别小程序的场景接入进行监控,但要满足上面说的"标准规范的小程序"前提,同时支持npm包。2. 完善的性能监控指标基础业务指标,帮助了解小程序应用的使用情况应用总PV/UV页面维度的PV/UV小程序各维度指标手机型号操作系统版本微信/支付宝等相应的APP版本网络等JS错误分析JS错误率、错误聚类、JS错误堆栈及错误定位等API请求追踪API请求成功率、API请求耗时及API请求的链路追踪自定义事件统计支持业务上自定义事件sum/avg统计3. 可通过配置选择上报方式由于业务方使用监控的诉求不同,我们不仅支持优雅的静默数据上报,也支持使用开放的统计能力进行自定义上报。具体可查看官网的前端监控接入概述中的小程序场景相关文档。总结小程序作为各大互联网公司重磅加持的方向,未来小程序的应用数量会越来越多,那么对于用户体验方面的关注与提升诉求也会不断增加,阿里云ARMS前端监控提供的小程序监控可帮助客户实时监控发现质量问题,为企业的小程序的稳定运行提供坚实的保障。附录:业务实时监控服务ARMS业务实时监控服务ARMS前端监控小程序监控接入文档

February 20, 2019 · 1 min · jiezi

前端监控实践——FMP的智能获取算法

今天来给大家介绍下前端监控中一个特定指标的获取算法,有人会问,为啥就单单讲一个指标?这是因为,目前大部分的指标,比如白屏时间,dom加载时间等等,都能通过现代浏览器提供的各种api去进行较为精确的获取,而今天讲的这个指标,以往获取他的方式只能是通过逻辑埋点去获取它的值,因此在做一些前端监控时,需要根据业务需要去改变页面对这个值的埋点方式,会比较繁琐,恰巧最近刚刚好在做一些前端监控相关的项目,遇到这个问题时就在想,能不能通过一种无须埋点的方式,将这个值给获取到?倒腾了一段时间,终于把算法弄出来了,今天就来给大家介绍下————FMP(first meaning paint) 指标的智能获取算法什么是FMP解答这个问题之前,我们先来了解下现代前端监控性能的主要指标统计方法,在2013年之后,标准组织推出了 performance timing api ,如下图这个api统计了浏览器从网址开始导航到 window.onload事件触发的时间点,比如请求开始的时间点——requestStart,响应结束的时间点——responseEnd,通过这些时间点我们可以计算出一些对页面加载质量有指导意见的时长,比如以下几个:TTFB : ResponseStart - RequestStart (首包时间,关注网络链路耗时)FPT : ResponseEnd - FetchStart (首次渲染时间 / 白屏时间)TTI : DomInteractive - FetchStart (首次可交付时间)Ready : DomContentLoadEventEnd - FetchStart (加载完成时间)Load : LoadEventStart - FetchStart (页面完全加载时间)通过这些指标我们可以得到很多有用的web端网页加载信息,建立对网页性能概况以上的指标可以对网页进行数值化的衡量,但是其实这种衡量只能体现一个视角的性能观点,比如TTFB很快,就能代表用户能够很快的看到页面的内容嘛?这个不一定是成立的,因此人们有开始从用户的视角去分析网页加载的性能情况,将用户看待加载过程,分成了以下几个阶段:页面是否正在正常加载 (happening)页面加载的内容是否已经足够(useful)页面是否已经可以操作了 (usable)页面是否可以交互,动画是否顺畅(delightful)而我们今天讨论的FMP(first meaningful paint),其实就是回答 is it useful,加载的内容是否已经足够,其实这是一个很难被定义的概念。每个网页都有自己的特点,只有开发者和产品能够比较确定哪个元素加载的时间点属于FMP,今天我们就来讨论一下,如何比较智能的去找出页面那个主要的元素,确定页面的FMP成为FMP元素的条件首先我们可以看看下面的图:我们可以发现在页面中比较useful的内容,都是含有信息量比较丰富的,比如图片,视频,动画,另外就是占可视面积较大的,页面中还存在两种形态的内容可以被视为是useful的,一种是单一的块状元素,另外一种是由多个元素组合而成的大元素,比如视频元素,banner图,这种属于单一的块状元素,而像图片列表,多图像的组合,这种属于元素组合总结一下成为FMP元素的条件:体积占比比较大屏幕内可见占比大资源加载元素占比更高(img, svg , video , object , embed, canvas)主要元素可能是多个组成的算法如何设计前面介绍了FMP的概念还有成为FMP的条件,接下来我们来看看如何设计FMP获取的算法,按照上面的介绍,我们知道算法分为以下两个部分:获取FMP元素计算FMP元素的加载时间如果有了解过浏览器加载原理的同学都知道,浏览器在在获取到html页面之后会逐步的对html文档进行解析,遇到javascript会停止html文档的解析工作,执行javascript,执行完继续解析html,直到整个页面解析完成为止。页面除了html文档中的元素加载,可能在执行javascript的时候,会产生动态的元素片段加载,一般来说,首屏元素会在这期间加载。因此我们只需要监控元素的加载和加载的时间点,然后再进行计算。具体的算法流程如下图相关的代码链接我已经放在最后面了,下面我会逐步的讲解整个算法流程我把整个流程分为两个下面两个部分:监听元素加载,主要是为了确定普通元素加载的时间点确定FMP元素,计算出最终的FMP值下面我们按照步骤来分析初始化监听可以看到首先我们先执行了firstSnapshot方法,用于记录在代码执行之前加载的元素的时间点接下来初始化MutationObserver,开始监听document的加载情况,在发生回调的时候,记录下当前到performance.timing.fetchStart的时间间隔,然后对body的元素进行深度遍历,进行打点,记录是在哪一次回调的时候记录的,如下图监听的最后我们会将在window.onload的时候去触发检查是否停止监听的条件,如下图如果监听的时间超过LIMIT,或者发生回调的时间间隔已经超过1s中,我们认为页面已经稳定,停止dom元素加载的监听,开始进入计算过程完成监听,进行元素得分计算首先前面我们说了,我们的元素对于页面的贡献是不同的,资源加载的元素会对用户视觉感官的影响比较大,比如图片,带背景的元素,视频等等,因此我设计了一套权重系统,如下:可以看到svg,img的权重为2,canvas,object,embed,video的权重为4,其他的元素为1,也就是说,如果一个图片面积为1/2首屏面积,其实他的影响力会和普通元素占满首屏的影响力一样接着我们回到代码,我们首先会对整个页面进行深度优先遍历搜索,然后对每一个元素进行进行分数计算,如下图可以看到我们通过element.getBoundingClientRect获取了元素的位置和大小,然后通过计算"width * height * weight * 元素在viewport的面积占比"的乘积,确定元素的最终得分,然后将改元素的子元素得分之和与其得分进行比较,去较大值,记录得分元素集通过计算确定FMP元素,计算最终FMP时间通过上面的步骤我们获取到了一个集合,这个集合是"可视区域内得分最高的元素的集合",我们会对这个集合的得分取均值,然后过滤出在平均分之上的元素集合,然后进行时间计算可以看到分为两种情况去处理:weight为1的普通元素,那么我们会通过元素上面的标记,去查询之前保存的时间集合,得到这个元素的加载时间点weight不为1的元素,那么其实就存在资源加载情况,元素的加载时间其实是资源加载的时间,我们通过performance.getEntries去获取对应资源的加载时间,获取元素的加载速度最后去所有元素最大的加载时间值,作为页面加载的FMP时间最后以上就是整个算法的比较具体的流程,可能有人会说,这个东西算出来的就是准确的么?这个算法其实是按照特征分析,特定的规则总结出来的算法, 总体来说还是会比较准确,当然web页面的布局如果比较奇特,可能是会存在一些偏差的情况。也希望大家能够一起来丰富这个东西,为FMP这个计算方法提出自己的建议附上代码 链接

November 22, 2018 · 1 min · jiezi