性能优化-进阶知识

2020/11/7 性能优化
// iconfont
1. 相对于图片减少了请求数量和体积
2. 矢量图形,可伸缩
3. iconfont 可以直接通过 css 修改样式 // 颜色为单色
----------------------------------------------------------------------------------------------
// svg
1. 保持了图片能力,支持多色彩
2. 矢量图形
3. xml 语法,搜索引擎 seo 和无障碍读屏软件读取
----------------------------------------------------------------------------------------------
// flexbox
1. flexbox 布局比 float 布局消耗时间短
2. flexbox 结合媒体查询可以实现响应式 // 子元素 flex 属性
----------------------------------------------------------------------------------------------
// 优化资源加载的顺序
1. 可以在 network 的 priority 查看资源加载的优先级
2. 浏览器有默认的加载优先级:html ——> head 中的 js 和 css ——> dom 中的图片和字体
3. preload // 提前加载,较晚出现,对当前页面非常重要的资源,只管加载不管解析,所以必须要声明解析
    <link ref="preload" href="img/dog.svg" as="image" />
    <link ref="preload" href="font.woff2" as="font" crossorigin="anonymous" /> // 字体必须加 crossorigin 属性跨域
    webpack 中的 'import' 函数中的魔法注释原理就是这个
      import(/* webpackPreload: true */ url)
4. prefetch // 提前加载后继路由需要的资源,优先级低,会在页面加载完其他东西后进行加载,只管加载不管解析,所以必须要声明解析
    webpack 中的 'import' 函数中的魔法注释原理就是这个
    <link ref="prefetch" href="img/dog.svg" as="image" />
    import(/* webpackPreload: true */ url)
5. preload 和 prefetch 的区别
  1. preload:资源在当前页面使用,会优先加载
  2. prefetch:资源在未来页面使用,空闲时加载
  3. 示例
    <head>
      <link rel="preload" href="style.css" as="style" />
      <link rel="preload" href="main.js" as="script" />
      <link rel="prefetch" href="other.js" as="script" />
      <link rel="stylesheet" href="style.css" />
      <script src="main.js" defer></script>
    </head>
6. dns-prefetch 和 preconnect 的区别
  1. dns-prefetch:DNS 预查询
  2. preconnect:DNS 预连接
  3. 示例
    <head>
      <link rel="dns-prefetch" href="https://fonts.gstatic.com" />
      <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    </head>
----------------------------------------------------------------------------------------------
// 预渲染
1. 大型单页应用的性能瓶颈:js 下载 + 解析 + 执行
2. ssr 的主要问题:牺牲 TTFB 来补救 First Paint 且实现复杂
3. 可以通过 Pre-rendering 在打包时提前渲染页面,且不用服务端参与
    React-Snap 是用来做 Pre-rendering 即预渲染的库 // npm install React-Snap -D
    原理是在 build 后会自动执行 postbuild,在后台打开类似 chrome 的浏览器去爬取页面
      在 package.json 中的 script 中配置 "postbuild": "react-snap"
      使用 ReactDOM.hydrate()
      内联样式,避免明显的 FOUC 即样式闪动
----------------------------------------------------------------------------------------------
// Windowing 窗口化提高列表性能
1. 加载大列表、大表单的每一行严重影响性能
2. Lazy loading 仍然会让 DOM 变得过大
3. windowing 只渲染可见的行,渲染和滚动的性能都会提升
4. npm install react-window -D
----------------------------------------------------------------------------------------------
// 使用骨架组件减少布局移动
1. npm intsall react-placeholder -D
----------------------------------------------------------------------------------------------
// 从输入 url 到页面加载显示完成都发生了什么?
1. 简述
  1. 网络请求
    1. DNS 解析
    2. TCP 连接
    3. 发送 HTTP 请求
  2. 解析:字符串 ===> 结构化数据
    1. DOM2. CSSOM3. Render tree
  3. 渲染
    1. 计算
    2. 绘制
    3. 同时执行 js
2. 深入
  1. 包括 Browser Process 和 Renderer Process // 浏览器进程和渲染进程
  2. Browser Process 包括 UI thread 和 Network thread // Ui 线程和 网络线程
  3. Renderer Process 包括 Main thread 和 Raster thread 和 Compositor thread // 主线程和绘制线程和复合线程
  4. UI thread:搜索关键词或 url 请求站点 // ui 线程做的工作
  5. Network thread:DNS 查找 IP (如果是 https 会建立 TLS 连接) ——> 设置 UA 等信息发送请求 ——> web server 响应 ——> 读取 response 分析数据类型
  6. Browser Process 把分析完的数据传递给 Renderer Process
  7. Main thread:解析文本构建 DOM ——> 边解析 DOM 边加载子资源 ——> JS 阻塞解析 ——> 解析 css 计算 computed styles 即每个元素的 style ——> 构造布局树即位置大小
  8. Raster thread + Compositor thread:创建绘制记录确定绘制的顺序 ——> 将页面拆分图层构建图层树 ——> 复合线程像素化图层创建一个复合帧
----------------------------------------------------------------------------------------------
// 什么是首屏加载?怎么优化?
1. 首屏即用户初次印象,第一见到的页面
2. 首屏加载用户体验的 3 个关键时刻:
    什么时候有内容出现 // 白屏
    什么时候出现有意思的内容,是否用户想要的
    什么时候可以进行交互
3. 什么时候有内容出现的优化标准? // First Contentful Paint (FCP)
    0s —— 2s // 优
    2s —— 4s // 中
    > 4s // 差
4. 什么时候出现有意思的内容,是否用户想要的优化标准? // Largest Contentful Paint (LCP)
    0s —— 2.5s // 优
    2.5s —— 4s // 中
    > 4s // 差
5. 什么时候可以进行交互的优化标准? // Time to Interactive (TTI)
    0s —— 3.8s // 优
    3.8s —— 7.3s // 中
    > 7.3s // 差
6. 优化策略:
    资源体积太大?
      资源压缩、传输压缩、代码拆分、Tree shaking、HTTP/2、缓存
    首页内容太多?
      路由/组件/内容 lazy-loading、预渲染/ssr、Inline Css
    加载顺序不合适?
      prefetch、preload
7. 首屏优化
  1. 路由懒加载
    1. 适用于 SPA,不适用 MPA
    2. 路由拆分,优先保证首页加载
  2. 服务端渲染 SSR
    1. 传统的前后端分离 SPA 渲染页面的过程复杂
    2. SSR 渲染页面过程简单,所有性能好
    3. 如果是纯 H5 页面,SSR 是性能优化的终极方案
    4. PHPASPJSP 就是 SSR,Nuxt.js(Vue)、Next.js(React)
  3. App 预取
    1. 如果 H5 在 App WebView 中展示,可使用 App 预取
    2. 用户访问列表页时,App 预加载文章首屏内容(一般是文本)
    3. 用户进入 H5 页,直接从 App 中获取内容,瞬间展示首屏
  4. 分页
    1. 针对列表页
    2. 默认只展示第一页内容
    3. 上划加载更多
  5. 图片懒加载
    1. 针对详情页
    2. 默认只展示文本内容,然后触发图片懒加载
    3. 注意:提前设置图片尺寸,尽量只重绘不重排
  6. Hybrid
    1. 提前将 HTMLJSCSS 下载到 App 内部
    2. 在 App WebView 中使用 'file://' 协议加载页面文件
    3. 再用 Ajax 获取内容并展示(也结合 App 预取)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
Last Updated: 2024/7/31 12:57:25
    飘向北方
    那吾克热-NW,尤长靖