Lighthouse 实战 超详细解析 逐项分析优化 - zptime/blog GitHub Wiki
通过谷歌无痕浏览器内嵌的 Lighthouse 分析测试环境的 home 页
第一次内容绘制,标记绘制第一个文本或图像的时间。官网介绍
- 提高分数比较重要的一点是字体加载时间,可参考 Ensure text remains visible during webfont load
- 避免显示不可见文本:在
@font-face
样式中添加font-display: swap
,swap 告诉浏览器使用该字体的文本应立即使用系统字体显示。自定义字体准备就绪后,将替换系统字体。 - 预加载网页字体:用
<link rel="preload" as="font">
提前获取字体文件
速度指数,衡量页面加载期间内容的视觉显示速度。官网介绍
提高速度指数得分:
最大内容绘制,标记绘制最大文本或图像的渲染时间。官网介绍
交互时间,是页面完全交互所需的时间。官网介绍
总阻塞时间,FCP 和 TTI 之间总时间,当任务长度超过 50ms 时,以毫秒表示。官网介绍
累积布局偏移。官网介绍
如下建议可以帮助更快地加载页面,但它们不会直接影响性能得分
基于文本的资源应该使用压缩(gzip、deflate 或 brotli),以最小化网络总字节数(FCP,LCP)。即还有潜在的压缩空间,可以配置 gzip压缩
减少未使用的 JavaScript 并推迟加载脚本,直到需要时才加载,以减少网络活动消耗的字节数(LCP)。即删除无用的 JS,主要方法就是合理的代码分割
和按需引入
列出了阻止页面首次绘制的所有 URL(FCP,LCP)。
目标是通过内联关键资源、推迟非关键资源和删除任何未使用的内容来减少这些阻止渲染的 URL 的影响。即合理加载资源,控制加载顺序
- 如何识别关键资源:使用 Chrome DevTools 中的
Coverage
选项卡来识别非关键 CSS 和 JS。当加载或运行页面时,该选项卡可以分析使用了多少代码,以及加载了多少代码,绿色(关键),红色(非关键 ) - 如何消除渲染阻塞脚本:合理使用
async
或defer
属性标记 <script>,可查看使用 JavaScript 添加交互 - 如何消除阻塞渲染的样式表:可使用
preload
链接异步加载其余样式,可查看推迟非关键 CSS
HTTP/2 提供了许多优于 HTTP/1.1 的优点,包括二进制标头和多路复用。即现在用的是 HTTP/1.1,建议使用 HTTP/2
。这个需要服务端改,目前不支持。
避免链接关键请求,链的长度越大,下载量越大,对页面加载性能的影响就越大。下面的关键请求链向您展示了哪些资源以高优先级加载。考虑减少链的长度
,减少资源的下载大小
,或推迟不必要资源的下载
以提高页面加载。
保持较低的请求数量
和较小的传输大小
最大的内容 Paint 元素。
可按照图示进行针对性的优化:主要是人员管理的文案
避免大的布局变化。
看图解析:首页有好几个模块都是通过接口获取的数据,接口是不同步的,因此采用骨架屏形式,进行异步渲染。这几个模块是由骨架屏
替换而来的,因此会有大的布局变化,会影响性能。
避免长时间的主线程任务。由于耗时超过 50 毫秒的复杂工作,会出现占用大量 CPU 的长任务。长任务会使主线程保持忙碌,延迟用户交互。Chrome DevTools 现在可以将长任务可视化,从而更容易查看要优化的任务
- 在 Chrome DevTools 中手动查找超过 50 毫秒的“长黄色块”脚本
- DevTools 可视化了 Long Tasks。如果任务(以灰色显示)是长任务,则它们会带有红旗
看图解析:主要是 main.js
和 5.js
需要优化
避免非合成动画。官网详细说明
看图解析:主要是骨架屏的代码。首页有好几个模块都是通过接口获取的数据,接口是不同步的,因此采用骨架屏
形式,进行异步渲染
- Properly size images:适当大小的图像,避免字节浪费而减慢页面加载时间
- Defer offscreen images:屏幕外图像延迟加载
- Minify CSS:缩小 CSS 文件,减少网络负载大小
- Minify JavaScript:缩小 JS 文件,减少有效负载大小和脚本解析时间
- Reduce unused CSS:删除未使用的 CSS
- Efficiently encode images:有效地图片编码和优化
- Serve images in next-gen formats:以下一代格式提供图像
- Enable text compression:启用文本压缩
- Preconnect to required origins:预连接到所需的源
- Initial server response time was short:初始服务器响应时间很短
- Avoid multiple page redirects:避免多个页面重定向
- Preload key requests:预加载关键请求
- Use video formats for animated content:用视频替换动画 GIF
- Remove duplicate modules in JavaScript bundles:删除 JavaScript 包中的重复模块
- Avoid serving legacy JavaScript to modern browsers:避免向现代浏览器提供旧版 JavaScript
- Preload Largest Contentful Paint image:预加载最大的内容绘制
- Avoids enormous network payloads:避免巨大的网络负载
- Uses efficient cache policy on static assets:对静态资产使用高效的缓存策略
- Avoids an excessive DOM size:避免过大的 DOM 元素
- User Timing marks and measures:用户计时标记和度量
- JavaScript execution time:JavaScript 执行时间
- Minimizes main-thread work:最小化主线程工作
- All text remains visible during webfont loads:在 webfont 加载期间所有文本保持可见
- Minimize third-party usage:尽量减少第三方使用
- Lazy load third-party resources with facades:延迟加载第三方资源
- Uses passive listeners to improve scrolling performance:使用被动侦听器来提高滚动性能
- Avoids document.write():避免使用 document.write()
- Image elements have explicit width and height:图像元素应具有明确的宽度和高度
可访问性,网站的内容可用,其功能可由任何人操作
- 可感知: 用户是否能感知内容?仅凭可通过一种感官(例如视觉)感知内容并不能断定所有用户都能感知。
- 可操作: 用户是否能使用 UI 组件和在内容中导航?例如,需要悬停交互的内容无法由不能使用鼠标或触摸屏的用户操作。
- 可理解: 用户是否能理解内容?用户能否理解界面,以及其一致性是否足以避免产生混淆?
- 强健: 内容是否能被多种 User Agent(浏览器)使用? 它是否能与辅助技术协作?
增强辅助技术用户的体验,如屏幕阅读器。
问题:[aria-] attributes do not match their roles([aria-] 属性与其角色不匹配) 解决:Ant Design 日历图标属性不匹配,这个是组件库的问题,不好改
提高内容易读性
问题:Background and foreground colors do not have a sufficient contrast ratio(背景色和前景色没有足够的对比度) 解决:UI 设计的样式和颜色就是这样的,不好改
改进应用程序中的控件语义,增强辅助技术(如屏幕阅读器)用户的体验
- Image elements do not have [alt] attributes(图像元素没有 [alt] 属性)
- 解决:需要向图像添加替代文本,添加
alt
属性,用作占位符,这个容易改
- 解决:需要向图像添加替代文本,添加
- Links do not have a discernible name(链接没有可辨别的名称)
- 链接主要从其文本内容中获取其可访问的名称,内容不具备代表性时,可使用
aria-label
定义
- 链接主要从其文本内容中获取其可访问的名称,内容不具备代表性时,可使用
- [user-scalable="no"] is used in the element or the [maximum-scale] attribute is less than 5:([user-scalable="no"](禁用网页上的浏览器缩放)用于 元素或 [maximum-scale]属性小于 5)
- 分析:对于依赖浏览器缩放来查看网页内容的低视力用户来说,这两个配置都是有问题的
- 解决:但是实际情况中,缩放了页面样式会混乱,一般是不能缩放的。
- The page has a logical tab order(该页面具有逻辑 Tab 键顺序)
- 测试:可以用 tab 键盘浏览页面,元素聚焦顺序遵循 DOM 顺序
- 修复:tabindex 属性可控制
- Interactive controls are keyboard focusable(交互式控件可通过键盘聚焦)
- 测试:先通过 Tab 键浏览,再使用 TAB(或 SHIFT + TAB)到控制间来回移动,并使用箭头键 ENTER 和 SPACE 操纵它们的值
- 修复:tabindex 来提高控件的可聚焦性;可能还需要向自定义控件元素添加适当的 ARIA 角色
- Interactive elements indicate their purpose and state(交互元素表明它们的目的和状态)
- 测试:tab 键测试,:focus 可设置焦点指示器的样式
- The user's focus is directed to new content added to the page(用户的焦点被定向到添加到页面的新内容)
- User focus is not accidentally trapped in a region(用户焦点不会意外陷入某个区域)
- 测试:使用键盘在所有页面元素之间导航。用于 TAB“向前”SHIFT + TAB 导航和“向后”导航。
- 修复:提供一种键盘可访问的方法来转义模态,创建可访问 modal,模态和键盘陷阱
- Custom controls have associated labels(自定义控件具有关联的标签,是可聚焦的)
- Custom controls have ARIA roles(检查所有自定义控件是否具有 role 赋予其属性和状态的适当且任何必需的 ARIA 属性)
- Visual order on the page follows DOM order(页面上的视觉顺序遵循 DOM 顺序)
- Offscreen content is hidden from assistive technology(屏幕外内容对辅助技术隐藏)
- HTML5 landmark elements are used to improve navigation(HTML5 地标元素用于改进导航,如 main、nav、aside 等)
- [aria-hidden="true"] is not present on the document (body 上不能写 aria-hidden 属性)
- [aria-hidden="true"] elements do not contain focusable descendents([aria-hidden="true"] 元素包含可聚焦的后代)
- [aria-] attributes have valid values([aria-] 属性没有有效值)
- [aria-] attributes are valid and not misspelled([aria-] 属性无效或拼写错误)
- Buttons have an accessible name(按钮没有可访问的名称,aria-label 属性标识)
- The page contains a heading, skip link, or landmark region(页面不包含标题、跳过链接或地标区域)
- Document has a <title> element(文档有<title>元素)
- Heading elements appear in a sequentially-descending order(标题元素不是按顺序降序排列的,即结构不佳)
- element has a [lang] attribute(元素没有lang属性)
- element has a valid value for its [lang] attribute(lang属性没有有效值)
- Form elements have associated labels(表单元素没有关联的标签,使用 for 属性引用元素的 id)
- No element has a [tabindex] value greater than 0(某些元素的[tabindex]值大于 0,会被认为是反模式)
- Does not use HTTPS(没有使用 HTTPS,有 14 个不安全的请求)
- 解决:因为测试的是测试环境,没有使用 https,正式环境是 https
- Ensure CSP is effective against XSS attacks:确保 CSP 对 XSS 攻击有效
- Missing source maps for large first-party JavaScript:缺少 JavaScript 的源映射
- 解决:开发环境是有的,但是生产环境为了减少包大小,一般不会配置
- Links to cross-origin destinations are safe(指向跨源目的地的链接不安全)
- 问题:使用
target="_blank"
属性链接到另一个站点上的页面时,可能会面临性能和安全问题 - 解决:添加
rel="noopener"
或rel="noreferrer"
- 问题:使用
- Avoids requesting the geolocation permission on page load(在页面加载时请求地理定位权限)
- 问题:代码调用 geolocation.getCurrentPosition()或 geolocation.watchPosition(),并且尚未授予地理定位权限,则审核失败
- Avoids requesting the notification permission on page load(请求页面加载通知权限)
- 问题:代码调用 notification.requestPermission(),并且尚未授予通知权限,则审核失败
- Avoids front-end JavaScript libraries with known security vulnerabilities(具有已知安全漏洞的前端 JavaScript 库)
- 问题:入侵者可以通过自动网络爬虫扫描站点,查找已知的安全漏洞
- Allows users to paste into password fields(防止用户获取密码)
- Displays images with correct aspect ratio(显示纵横比不正确的图像)
- Serves images with appropriate resolution(提供响应式图像)
- Page has the HTML doctype(页面缺少 HTML 文档类型,从而触发怪异模式)
- Properly defines charset(字符集声明缺失或在 HTML 中出现得太晚)
- Avoids unload event listeners(要避免遗留的生命周期 API,事件或者监听器要注销)
- Avoids Application Cache(使用应用程序缓存)
- 使用缓存 API 而不是应用程序缓存,通过 Service Worker 使用缓存 API
- Detected JavaScript libraries(列出所有前端使用的 JavaScript 库)
- Avoids deprecated APIs(使用已弃用的 API)
- No browser errors logged to the console(没有浏览器错误被记录到控制台)
- No issues in the Issues panel in Chrome Devtools(Chrome Devtools “Issues” 面板中没有未解决的问题)
- Crawling and Indexing(爬取和索引)
- Links are not crawlable:链接不可抓取
- 具体分析:a 标签没有定义 href 属性,把跳转事件写到 click 中了,这个好改
- Links are not crawlable:链接不可抓取
- Content Best Practices(内容最佳实践)
- Image elements do not have [alt] attributes
- 具体分析:图片没写 alt 属性,这个好改,就是图片有点多
- Image elements do not have [alt] attributes
- Additional items to manually check(需要手动检查的项目)
- Structured data is valid:结构化数据有效
- Passed audits(审核通过)
- Has a tag with width or initial-scale:视窗宽度和缩放比例
- Document has a <title> element:标题
- Document has a meta description:元描述
- Page has successful HTTP status code:成功的 HTTP 状态代码
- Links have descriptive text:描述性链接文本
- Page isn’t blocked from indexing:页面没有阻止搜索引擎爬虫编制索引
- Document has a valid hreflang:有效的语言代码
- Document avoids plugins:避免插件,如 embed、object、applet
- Not applicable(不适用)
介绍文档:https://web.dev/pwa-checklist/
- Installable(安装)
- Web app manifest or service worker do not meet the installability requirements:Web 应用清单或 Service Worker 不符合可安装性要求
- PWA Optimized(PWA 优化)
- Does not register a service worker that controls page and start_url:没有注册 Service Worker
- Does not redirect HTTP traffic to HTTPS:使用 HTTPS 进行保护
- Is not configured for a custom splash screen:自定义启动画面,Failures: No manifest was fetched.
- Does not set a theme color for the address bar:为地址栏设置主题颜色
<meta name="theme-color" content="#317EFB"/>
- Does not provide a valid apple-touch-icon:添加 Apple 触摸图标
<link rel="apple-touch-icon" href="/example.png">
- Manifest doesn't have a maskable icon:没有可屏蔽图标,No manifest was fetched
因为我之前没有配置 pwa,easywebpack 有默认的配置,但是默认没开启,可以开启下
针对首页分析,进行优化点汇总:
- 字体样式控制:在
@font-face
样式中添加font-display: swap
- gzip 压缩
- 合理的
代码分割
和按需引入
- CSS(
preload
),JS(async
或defer
)加载顺序控制 - HTTP/2 替换 HTTP/1.1
- 减少请求链长度,减少资源下载大小,推迟不必要资源的下载
- 减少请求数量和传输大小
- 减少重排和重绘,避免大的布局变化
- 避免长时间主线程任务
- 避免非合成动画,骨架屏要改
- Accessibility(无障碍)要加强
- img 图片添加 alt 属性
- PWA 配置开启