前言
但凡存在类似“自动搭建”的功能页、活动页、CMS页面都不可避免遇到一类问题:秒开率较之其它页面差距较大。
秒开率这个性能指标是最直观的性能观测指标之一,也是公司老板们肯定你的依据之一。现在的前端越来越卷了,你的老板可能每天都会针对某些秒开率低下的页面来质询你。
那么,页面白屏可能会带来什么?
白屏带来的不确定性
1. 请求异常
我们知道浏览器发出http请求,会包含 headers、 method、contentType
等,服务器收到请求还要有相应的response。 请问,到底是 request
出了问题,还是 response
出了问题? 下面是随便一个请求的request header,瞅瞅。
如果此时最关键且决定视图渲染的 js
脚本没正常获取到,会咋样? 很明显,这白屏不过吧?
2. 意外的异常
先说 try catch
try {
const a = 0;
a.push(1);
} catch (error) {
console.error(error);
console.log('I m comming!')
}
结果很明显
被 catch 住的异常只能说是 “正常的异常”。 能被捕捉到的异常前端自己处理就行了,根本不用BB。
so. Q1: 如果异常没被步骤到呢?
// 假如强行丢出错误呢?
throw 'a.push is not a function....'
// 假如就是没有捕捉错误呢?
const a = 0;
a.push(1);
console.log('I m comming now!')
还会像catch那样,最后会 打印出 'I m comming now!'
吗? 明显不会,因为你的js代码已经被停止向后执行了。
所以,你白屏很正常吧?
Q2: 虽然你说得都对,那你只要写代码的时候细心些不就行了吗?
答: 不好意思。虽然你说的我都懂,但就是有些页面是运营搭起来的,不是开发每次手写的。
小结一下
要知道白屏时间里到底发生了什么,得至少监控到以下几点:
- 监控
request
- 监控
response
- 监控
V8
告诉你的异常。例如js
代码执行报错Error
- 控制台
console
- 加载资源时间
puppeteer
简介不多说了,各位大佬去看官网,我就不浪费时间了。直接说,它能做到哪些事情?
1. 无头访问页面
async function main() {
// 启动chrome浏览器
const browser = await puppeteer.launch({
// 指定该浏览器的路径,我mac没有指定😂
// executablePath: chromiumPath,
// 是否为无头浏览器模式,默认为无头浏览器模式
headless: true
});
// 在一个默认的浏览器上下文中被创建一个新页面
const page1 = await browser.newPage();
const eventTypes = ['domcontentloaded', 'error', 'frameattached', 'framedetached', 'framenavigated', 'load', 'metrics', 'pageerror', 'popup', 'request', 'response', 'requestfailed', 'requestfinished', 'requestservedfromcache', 'workercreated', 'workerdestroyed']
// 空白页刚问该指定网址
await page1.goto('https://blog.csdn.net/weixin_31742871/article/details/112741137');
}
然后你会发现你没有打开浏览器,却访问到了页面。 无头浏览器由此得来。
2. 截取DOM元素的能力
async function myCheck() {
const browser = await puppeteer.launch({
headless: false
});
const page = await browser.newPage();
await page.goto('https://juejin.cn/user/2084329775958248/posts');
await page.waitForSelector('body'); // 异步等待<body />出现
// 用page自带的方法获取节点
const children = await page1.$eval('body', el => el.children);
console.log(children);// 是渣男吧 的个人主页 - 文章
}
myCheck();
如果拿到一些关键DOM,例如首屏最后一个DOM元素,是不是就可以计算时间了?
3. 监听请求/响应 & 拦截请求
async function myCheck() {
// same code ....
// 拦截请求开启
await page.setRequestInterception(true);// true开启,false关闭
page.on('request', request => {
if (request.url() === 'https://mcs.snssdk.com/v1/list') {
request.abort();
console.log('该请求被终止!!!');
}else {
console.log(request.resourceType());
console.log(request.method());
console.log(request.headers());
}
});
page.on('response', response => {
if (response.url() === 'https://mcs.snssdk.com/v1/list') {
console.log(response.status());
console.log(response.headers());
}
})
// 空白页刚问该指定网址
await page1.goto('https://www.baidu.com');
}
myCheck();
不多说,代码懂的都懂。不懂的请留言,单独解惑。
4. snapshot 截图/快照/PDF
此功能吹爆。
async function screenshot() {
await page.screenshot({
path: 'Images/screenshot.png', // 保存路径
fullPage: true // 全屏截取
});
// 截取屏幕中一个区域的内容
await page.screenshot({
path: 'Images/screenshot.jpg',
type: 'png',
quality: 80,
clip: {
x: 0,
y: 0,
width: 375, // 屏幕宽
height: 600
}
});
await page.pdf({ path: 'Pdf/errorInfo.pdf' }); // 生成PDF
browser.close();
}
screenshot();
so,当你监控到异常发生,不管三七二十一先把当前的样子截个图保存好。老板回头就把证据丢你脸上😂
最后看下有哪些可以被监听的事件
上源码:
/**
* Denotes the objects received by callback functions for page events.
*
* See {@link PageEmittedEvents} for more detail on the events and when they are
* emitted.
* @public
*/
export declare interface PageEventObject {
close: never;
console: ConsoleMessage;
dialog: Dialog;
domcontentloaded: never;
error: Error;
frameattached: Frame;
framedetached: Frame;
framenavigated: Frame;
load: never;
metrics: {
title: string;
metrics: Metrics;
};
pageerror: Error;
popup: Page;
request: HTTPRequest;
response: HTTPResponse;
requestfailed: HTTPRequest;
requestfinished: HTTPRequest;
requestservedfromcache: HTTPRequest;
workercreated: WebWorker;
workerdestroyed: WebWorker;
}
end
其实,所谓技术调研,就是你要做某样事情(可能是老板让你做)之前,你要确认一下存在可行性方案的可能。
做到这几步:
- 技术栈的稳定性、成熟性。
- 能不能做。
- 能做的话大概会遇见什么难踩的坑。
- 兼容性问题
- 人力成本如何
- 用户群
- 是否考虑并发
以上搞定了,确定了要做,那你就去和老板怼(沟通)吧。