| 导语 《孙子兵法·谋攻》:「知彼知己,百战不殆。」在和产品pk的时候,产品最常常的说一句话是,你看他们(竞品)都能实现,你为啥不能?你看他们(竞品)的速度怎么这么快,你看看你,为啥这么慢?javascript
《孙子兵法·谋攻》:「知彼知己,百战不殆。」在和产品pk的时候,产品最常常的说一句话是,你看他们(竞品)都能实现,你为啥不能?你看他们(竞品)的速度怎么这么快,你看看你,为啥这么慢?往往遇到这样的责难的时候,我每每都只能陷入到沉思,我只能告知产品,咱们的页面很快,真的很快,你看,个人报表。产品老是在这个时候说,不听不听,我不听。若是你不能拿出竞品的客观数据,那么,在产品看来这样的呓语只能是开发本身的寡妇心态。在每一个无人的夜晚,遇到这个问题的时候,我不得不得默默的打开了浏览器。php
因此,如何把监控作到客观,独立,第三方,就变得很重要了。html
首先,第一个来自灵魂的深思就是,如何客观的对页面体验进行评价?你说你的页面体验牛逼,你的页面体验就牛逼了么?你说竞品的页面不行,竞品的页面就真的不行么?每晚思及如此,我都默默的打开了浏览器。前端
对于页面的客观评价体系,有不少不一样的说法,基于速度,基于错误率,基于SEO…,这么多的评价标准中,要怎么样,找到最能说明用户体验的指标?或者换句话来讲,怎么样的指标是最可以表现用户真实的用户体验的?java
从直觉上来讲,一个页面的体验能够分红如下几个部分:node
这个体验最直白,用户打开页面的耗时如何,用户花了多长的时间来打开你的页面。在页面的打开过程当中,是一种什么样的体验?是白屏,是渐进加载,是菊花图,仍是骨架屏?不一样的体验体验,给用户的直觉感官是不一样的,这些感官应该怎么样来客观评价?python
页面的各类交互是否可以及时?页面上的各个交互针对不一样的人群是否兼顾?是否照顾了视觉障碍人群,是否考虑到了键盘党?各个交互是否符合浏览器预期?页面上的脚本是否使用了有危险的API?是否加载了太多的资源?git
页面是否对蜘蛛友好?页面是否对于可以被正确的收入?github
固然,上面列的比较简单,只涵盖了页面的一部分,可是,如上已经覆盖了不少咱们平时须要关注的页面信息了,那么咱们要怎么来获取和评价这些信息呢?web
最简单的方法是,咱们把浏览器的devtools打开,选中到performance tab,点击record。而后,咱们就能够看到全部咱们想要的数据了。那么问题来了,performance tab是怎么工做的呢?它是怎么拿到咱们页面的各类渲染数据的呢?
一切的一切,都要以这个协议开始:chrome devTools protocol。 chrome会经过这个协议,把内核和浏览器的一些状态暴露出来。咱们平时使用的performance tab的本质起始就是使用这个协议的一个美化了的查看器。performance里面仍是有一些内容比较没有被充分展现,若是你想了解更多,更详细的内核信息,能够进入到如下的页面查看
chrome://tracing/
复制代码
点击record,你会看到以下的选择框。
这里将会容许你,更为详细的去定义,你想要监控和了解的内核内容。
嗯,这里有一点比较好,也是比较不幸的一点,这个tracing tab将会监控当前chrome 全部tab的渲染信息。因此,使用的时候,请务必当心。还有一个须要注意的点事,这个tracing的日志量多到爆炸,尽量的选择较少的追踪项,这样,可让你保护好你的内存条。:)
若是有时间好好研究一下,这个tracing出来的内容,你会发现,浏览器的运行,好像并非你想象那样的。:)
固然了,除了使用这样的形式去使用chrome devtools protocol,咱们还可使用nodejs的来获取。毕竟,Anything that can be Written in JavaScript, will Eventually be Written in JavaScript。比较常见的nodejs的库有chrome-remote-interface(下文为了方便,简述为cri),固然,若是你说我不要,我不要js,那也不是不能够,在这里,本身选一个本身喜欢的实践吧。什么typescript,go, python,ruby都有,固然,还有,咱们你们都喜欢的php。
好了,做为一个前端工程师,咱们仍是老老实实用nodejs吧,虽然,typescript很好,可是我选择js,咱们来康康,咱们要怎么把各类各样的工具,组合起来,使之成为一个可以被工具化使用的页面监控呢?
具体的cri使用,请参考这个wiki
一切的一切,咱们要有一个开启了debugger端口的chrome。这个简单,你能够用shell脚本,本身起一个,固然,咱们还有更优雅的方式:chrome-launcher,有了它,在寂静无人的夜,你就不再用本身写shell脚原本启动chrome了:)。
经过chrome-launcher,咱们把chrome拉起来,而后获得了一个咱们须要须要调试端口,而后,咱们拿着这个端口,使用cri来获取咱们须要chrome-debugger-Protocol,拿到了具体的Protocol以后,咱们来康康,拿到的都是些啥东西:
{"pid":8784,"tid":8728,"ts":4123614461,"ph":"X","cat":"ipc,toplevel","name":"ChannelMojo::OnMessageReceived","args":{"class":50,"line":101},"dur":2,"tdur":1,"tts":22268542},
{"pid":8784,"tid":8728,"ts":4123615131,"ph":"X","cat":"toplevel","name":"MessageLoop::RunTask","args":{"src_file":"../../content/browser/renderer_host/media/media_stream_manager.cc","src_func":"SendMessageToNativeLog"},"dur":4,"tdur":4,"tts":22268810},
{"pid":8784,"tid":8728,"ts":4123615138,"ph":"X","cat":"toplevel","name":"MessageLoop::RunTask","args":{"src_file":"../../ipc/ipc_channel_proxy.cc","src_func":"Send"},"dur":8,"tdur":8,"tts":22268817},
{"pid":8784,"tid":8788,"ts":4123551336,"ph":"X","cat":"toplevel","name":"MessageLoop::RunTask","args":{"src_file":"../../base/trace_event/trace_log.cc","src_func":"SetEnabled"},"dur":130,"tdur":130,"tts":64927429},
{"pid":8784,"tid":8788,"ts":4123551358,"ph":"I","cat":"disabled-by-default-devtools.timeline","name":"TracingStartedInBrowser","args":{"data":{"frameTreeNodeId":101,"persistentIds":true,"frames":[{"frame":"7CB62147F076D4C38B128F711003B9E9","url":"https://www.huya.com/badaozongcai","name":"201905171157120c93bb02c2ca5f727133a5547b2a8d4000016f6b3731c1440","processId":5368}]}},"tts":64927451,"s":"t"},
复制代码
是否是以为似曾相识,嗯,用chrome save下来的profile.json和上面的内容的格式如出一辙。那么,这一大坨json究竟是啥意思呢?这个时候,我就要把我祖传的chrome tracing event format的文档给你掏出来了。我相信,等你看完以后,你必定会,大吼一声,卧槽,这是什么鬼!这么诘屈聱牙的文档,简直了。浏览器的底层运行原理是很是复杂的,不一样的类和组件的调用,使得追踪浏览器事件变成了一个不是这么容易的事情。固然,若是,想要图文并茂的了解浏览器的运行原理,请参考《life of a pixel》。
若是是咱们想要程序化,工具化的去监控和管理浏览器的底层渲染行为,咱们只能从上面厚厚的trace event log里,把咱们须要的内容剥离出来,进行统计分析。这时候,咱们会就想呀,有没有大神把这个事情给作了呀,咱们这种小弟,观摩学习一下就好?
答案是,固然有啦!google chrome团队,本身就开源了一个基于typescript的分析工具Lighthouse,可以帮助咱们快速的进行页面的质量分析。
lighthouse 是这么介绍本身的:
Lighthouse analyzes web apps and web pages, collecting modern performance metrics and insights on developer best practices.
在我看来,Lighthouse更像是一个google推行标准的衡量器。让广大的开发同窗知道什么是好,什么是很差,在茫茫的人海中,找到对的那我的。
与其让我重复一遍上面的内容,还不如康康Lighthouse本身是怎么说本身的工做原理的:
依照上图和前文,我相信你们已经对于Lighthouse是怎么执行的,有了很是深入的理解了,经过github上Lighthouse的readme,我相信,你们也可以很是容易的把Lighthouse跑起来了。这里就不赘述了。无非就是npm install, npx lighthouse 诸如此类。
等咱们把lighthouse跑起来以后,咱们就能够获得下面这样的一个报告:
咱们除了会使用到Lighthouse提供的这些评价标准和评价体系,更多的时候,会使用到属于咱们本身的评价标准和评价体系。这个时候问题就来了,咱们要怎么对Lighthouse进行二次开发?咱们怎么基于Lighthouse作一个属于咱们本身的标准衡量器?
在开发以前,咱们先了解基本流程,从上图,咱们能够清楚的得知Lighthouse的工做流程以下:
+--------------+ +-------------+ +------------+ +-------------------+
| | | | | | | |
| connecting +----->+ collecting +------->+ auditing +------>+ report generation |
| | | | | | | |
+--------------+ +-------------+ +------------+ +-------------------+
创建链接 收集日志 分析,审计 生成报告
复制代码
了解了流程,咱们再来了解一些基本概念,在Lighthouse里面,有以下几个特别重要的概念:
好了,知道了,以上这些内容,你就能够本身来搞一个Lighthouse了,正常来讲,一个优秀的框架设计,都是会留有插件机制的,可以让咱们很是优雅的,无侵入的把咱们的逻辑添加到框架的逻辑体系中去。Lighthouse也不例外。固然,若是你说,不要,我不要,我要硬核魔改,让它变成我本身的崽,下文也会给出一些指南。
在开发插件以前,咱们须要知道,咱们这个插件的结构是怎么样的。先俩简单的看一下:
-
|-your_audit.js
|-plugin.js
|-package.json
复制代码
只须要三个文件,就能够自行实现一个lighthouse的插件了,是否是很简单!!!
package.json是一个npm包的必备文件,咱们须要把package.json中的main指向,咱们的plugin.js。
做为一个plugin,你只是须要暴露如下一个对象便可:
//plugin.js
module.exports = {
audits: [{
path: 'path/to/your/aduit',
}],
category: {
title: 'My Plugin',
description: 'my plugin.',
auditRefs: [
{id: 'your_audit', weight: 1}, //这里须要注意,id和文件名一直
{id: 'meta-description', weight: 1}, // lighthourse的默认审计项目
],
},
};
复制代码
而后,在audit文件里,你能够本身定义你本身的审计规则,就像下面这样:
//my-audit.js
const Audit = require('lighthouse').Audit;
class myAudit extends Audit {
static get meta() {
return {
id: 'my-aduit',
title: '展现的title',
failureTitle: '未经过的时候,展现的文案',
description: '补充的一点的描述内容',
// 你所须要的收集内容
requiredArtifacts: ['LinkElements'],
};
}
static audit(artifacts) { // 上面指定的内容,将会被传递到这个函数中
// 处理你的逻辑
return {
score: 0, // 外显的分数以及决定是否算经过
displayValue: '显示的内容',
};
}
}
module.exports = myAudit;
复制代码
在执行lighthouse命令的时候,咱们须要这样来明文指示咱们要用的plugin:
npx lighthouse https://example.com --plugins=my-plugin --view
复制代码
而后,lighthouse就会去node_modules里面去寻找,你要使用到的lighthouse plugin。
lighthouse官方本身给了一个插件的demo,你们能够自行参考一下。里面还有plugin的效果图。
上面能够看到,开发一个plugin是很简单的。可是呢,咱们也很明显的发现一个问题,这个plugin的机制有点弱,好像只能就已经收集到的信息进行审计级别的重写,并不能捕获更多的数据,而后来定义本身想要的内容。
其实吧,若是,只是想本身定义一个属于本身的评价体系,作到这一步,已经够了,毕竟lighthouse的articles给的也挺多。基本上,你能想到的经常使用的内容,都有。若是想知道全部的articles都有啥,请看这里。若是你想更多的了解插件的开发内容,能够参考这里。
对于咱们这种,向来都不喜欢被约束的人而言,这么点东西,就想打发我,不行!做为一个成年人,做为一个半夜打开浏览器的男人,我都要!ok,那么咱们来看看,咱们怎么硬核的二次开发,把lighthouse变成咱们本身的崽。
Lighthouse的源码写的很规整,加上typescript的加持,很是好读,同时大量的注释,更是若有神助。
在对lighthouse进行二次开发以前,咱们须要知道lighthouse的源码结构是怎么样的。以下所示(为了避免浪费篇幅,把一些和魔改无关的逻辑去掉了):
——
├─assets
├─build
├─clients // 浏览器中的展现逻辑
│ └─extension // 扩展
├─docs // 文档
├─lighthouse-cli // 命令行工具
│ ├─commands // 命令
│ └─test
├─lighthouse-core // 核心逻辑
│ ├─audits
│ ├─computed
│ │ └─metrics
│ ├─config
│ ├─gather
│ │ ├─connections
│ │ └─gatherers
│ ├─lib // 工具库
│ ├─report // 报告生成器
│ │ └─html
│ │ └─renderer
│ └─test // 测试用例
├─lighthouse-logger // 日志收集
├─lighthouse-viewer // 报告渲染工具
└─types // 类型文件
复制代码
从上文所描述的内容中,咱们已经知道了lighthouse的一些基本的内容和结构,因此咱们能够很容易的从目录结构中,看出咱们须要修改的内容,通常是围绕在Lighthouse-core的逻辑中。总体文件看起来好像比较多,可是呢,其实核心逻辑,其实仍是比较集中。在Lighthouse-core。
总体的调用关系以下图
好像很复杂,从新整理了一下以下:
从调用链,咱们能够很清楚看到前文提到的connecting->collecting->auditing->report generation的过程,其实基本上根据函数名,你们都可以分析出函数的内容。你们按照本身的须要,切进去魔改就行了,想改啥都行。
说实话,Lighthouse的总体设计仍是很不错的,加上typescript的加持,整个代码的可读性仍是很强的。其实基于plugin的机制,基本上已经能够知足你们的各类需求了。若是真的有一天,已经到了,必需要修改源码的地步了,但愿上述内容能帮助到你们。
好了,基于上文的魔改,咱们已经获得了一个属于咱们本身的lighthouse和咱们本身的审计规则。可是,在你电脑上跑出来的数据,并不真实,并不能表明广大的人民群众。因此,咱们须要作如下的工做:
把咱们的服务部署在云端的机器,直接接受外部网络环境的洗礼。同时限制硬件素质,保持一个比较贴近现实的机器水平。
在天津,上海,广州等多个节点进行部署,看看地理位置因素,到底会给页面带来多大的影响。
一天在不一样的时间段内执行,看看不一样的时间里,随着网络流量的周期变化,你的页面在哪一个时间最糟糕?固然,这里还有一个更为重要的做用,就是,抽查页面的可访问性,页面是否是挂了?让你成为最先知道页面完整信息的人。
屡次执行取平均值咯,去除单一缓存的影响。
基于这种考虑,咱们开发了leadership,能够同时对比多份报告,云端运行。
完成了如此种种,我终于才可以在寂静无人的夜,比较客观公正的对产品说,个人页面真的比竞品的页面快!你看,这是个人报告!
关注【IVWEB社区】公众号获取每周最新文章,通往人生之巅!