技术标签: html5 react 前端面试 javascript
初始阶段 -> 加载优化
运行阶段 -> 渲染优化
#####问题分析
结论:所有加载慢的问题最终都可以归纳成两个问题 多 和 大。Tips:还有网速不好和电脑太渣
#####问题讲解
模拟面试对话
Q: 面试官爸爸 A: 你
Q:那既然你已经知道了首页加载慢的几个原因,那我先问你首页加载图片过多怎么处理?
A:减少图片不就完了吗
Q:那我们的首页就是有这么多图片怎么办?
如何分析:看看淘宝怎么解决
A: 可以通过懒加载的方式来减少首屏图片的加载量
Q: 懒加载是什么原理?
如何分析:看看懒加载的库
<img alt="A lazy image" data-src="lazy.jpg">
<------ 滚动到特定位置的时候 ------>
<img alt="A lazy image" src="lazy.jpg" data-src="lazy.jpg">
A: 懒加载原理就是监听滚动条事件,如果(滚动条距离浏览器顶部的高度 === 图片距离顶部的高度),那么就将 data-src 的值赋值到 src 上。
Q: 那假设首页的小图片就是很多,比如有很多个小 ICON 怎么办?
如何分析:还是看看淘宝怎么解决
A: 可以分别使用 iconfont 和雪碧图来处理小图标和小图片
总结:
首页加载图片过多的问题,可以通过以下几种方法解决:
- 通过懒加载的方式处理非首屏的图片
- 对于小图标可以采用 iconfont 的方式解决
- 对于小图片可以采用雪碧图的方式解决
Q: 首页的请求量过多怎么解决?
如何分析:
先通过工具来确定是哪些类型的资源请求过多
通过浏览器的 Network 可以确定首页加载的资源和请求量
requests:请求数量
resources:前端资源总大小
DOMContentLoaded: 浏览器已经完全加载了 HTML, 其他静态资源( JS, CSS, 图片等)并没有下载完毕(能看,不能用)
Load:浏览器已经加载了所有的静态资源(能用了)
通过 converge 来查看代码的使用状况
A: 可以通过减少资源的请求量
Q: 只有通过合并静态资源的方式才能减少资源请求量吗?
如何分析:
除了从资源层面来解决问题,还可以从我们自己写的代码本身来考虑。
对于引入的一些比较大型的第三方库,比如 组件库(antd,element-ui),函数库(lodash)等,务必设定按需加载。Tips: 一般都是用 Babel 插件来实现的
可以通过前端路由懒加载的方式(只限于 SPA 应用)
A: 当然不是,还可以从代码层面的优化,比如说:
1. 如果在项目中引入了比较大型的第三方库,那就可以通过特定的 Babel 插件来进行按需加载
2. 在路由层面也可以使用 React lazy 进行动态路由的加载,从而可以减少首页的 JS 和 CSS 的大小
Q:那我问你为什么 React lazy 可以进行动态路由的加载?
如何分析:先看看使用方式
// 1. 引入 react lazy, 并且使用 import 动态导入组件
import { lazy } from 'react'; // 静态导入
lazy(() => import('./Home')); // 动态导入
// 2. 引入 Suspense 组件,并使用 Suspense 将根组件包裹起来,并使用 fallback props 传入 loading 组件
import { Suspense } from 'react';
// 注意:使用 lazy 加载的组件,必须是 Suspense 子组件,或者孙组件
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
动态导入(dynamic import):当代码运行 import 的时候,再导入组件
import("./math").then(math => {
console.log(math.add(16, 26));
});
// 类似于 fetch,都是返回一个 Promise
fetch("./math").then(math => {
console.log(math.add(16, 26));
});
演示 Webpack 的代码分割
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ghvtVgx5-1622953813865)(./assets/1.png)]
结论:
import(‘xxx’) 返回的是一个 Promise
Webpack 只要遇到了 import(‘xxx’),就会把括号里引入的内容单独打一个包
A: 首先 React lazy 是使用了 dynamic import 的标准,webpack 只要遇到了 dynamic import, 就会把里面引入的内容单独打一个包。
由于 dynamic import 返回的是一个 Promise,所以可以使用 Promise 的状态来做渲染的流程控制。
如果当前 Promise 是 pending 状态,那么就渲染 Loading 组件,如果 Promise 是 resolve 状态那么就渲染动态导入的组件。
总结:
首页的请求量过多,可以通过一些手段来减少资源的请求量,比如:
- 通过 nginx 服务器来做资源文件的合并或者通过 Webpack 等打包工具进行物理打包
- 在代码层面,对于需要引入一些大型第三方库的时候,可以通过特定的 Babel 插件来进行按需加载
- 还有可以使用 React lazy 或其他动态导入方案来进行前端路由层面的动态加载,从而可以减少首页的 JS 和 CSS 的大小
Q: 首页请求的资源(CSS、JS、图片…)过大怎么解决?
A: 把资源变小不就完了吗?
Q: 怎么变小?
A:
/usr/local/etc/nginx
)#####答题思路
对于首页加载慢的问题,一般是由于首页加载资源过多,并且资源过大导致。所以应对的策略就减少资源的数量以及减小资源的大小。
- 对于图片可以懒加载,减小首屏图片加载量。以及对于小图标和小图片和分别使用 iconfont 和 雪碧图来解决,最大程度减少首屏图片数量,从而提升首页渲染性能。
- 对于其他资源可以通过打包(nginx combo 或者 Webpack 打包)来合并资源,并可以通过懒加载路由的方式来减小首页 JS 的加载量
- 减小资源的方式可以通过压缩和混淆加密来减小文件体积,图片则可以使用工具来压缩或者使用 webp 格式。
- 同时可在服务器端开始 gzip 压缩来最大化减少所有文件体积。
前端中最常见资源:HTML、CSS、JS、图片
####2. 优化图片的做法
Q: 好,那你刚刚说可以使用自动化工具对图片进行压缩,你是使用什么工具?
A: 用 熊猫站 不就完了吗?
如何分析
熊猫站:智能压缩 PNG 和 JPG 的一个网站
Q: 那你认为为什么这个工具可以同比例无损压缩?
如何分析
看看熊猫站的描述
通过相似颜色“量化”的技术来减少颜色数量,并且可以将 24 位的 PNG 文件转化成 8位的彩色图片。同时可以将不必要的元数据进行剥离。
–> 翻译成人话
通过减少颜色的数量以及不必要的数据来实现文件压缩
A:通过减少颜色的数量以及不必要的数据来实现文件压缩
Q: 非常 nice,但是这是方式不是有一个问题?难道每当我需要处理图片的时候,就要进入这个网站去上传一下吗?这样不仅仅效率低,还不安全。
A: 熊猫站很佛系的,他们把图片压缩工具 开放 出来了。可以使用 npm 安装开源包,就可以在我们本地进行图片压缩啦。
Q: 那除了这个方式还有什么其他的方式来优化图片吗?
如何分析
对图片进行转码 -> base64 格式
A: 可以使用 Webpack 的 url-loader 进行图片策略配置,将小图转换成 base64 格式,因为 base64 格式的图片的作用是减少资源的数量,但是 base64 格式的图片会增大原有图片的体积
A: 还有一种方式就是使用 webp 格式的图片
如何分析
图片格式有很多种,PNG、JPG、GIF,还有新的 WebP 格式
WebP 的优势:
根据 Google 的测试,同等条件等比例无损压缩后的 WebP 比 PNG 文件少了 26% 的体积。并且图片越多,压缩后的体积优势越明显。
压缩率比较,JPG vs WebP
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fv0IZczI-1622953813867)(./assets/2.jpg)]
加载时间比较,JPG vs WebP
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2bcji073-1622953813868)(./assets/3.jpg)]
#####答题思路
图片的优化,也是从两个方面来考虑:太多 和 太大。
可以通过懒加载减少图片的请求,或者通过雪碧图来合并图片,以及将小图转化成 base64 的格式,来解决多的问题。
图片大的问题,可以通过自动化压缩工具来压缩图片,或者使用 WebP 格式的图片。
#####问题分析
#####问题讲解
Q: 我问你,怎么使用 Webpack 进行打包优化?
A: 少 和 小
Q: 怎么样少,怎么样小
如何分析
少 -> 使用 Webpack 进行物理打包。
小 -> 使用 Webpack 进行混淆和压缩,所有与 Webpack 优化相关的配置都是在 optimization 这个配置项里管理。
从 webpack 4 开始,会根据你选择的 mode 来执行不同的优化,不过所有的优化还是可以手动配置和重写。
development:不混淆,不压缩,不优化
production:混淆 + 压缩,自动内置优化
结论:只需要将 mode 改成 production 即可
A: 使用 Webpack 对代码进行混淆和压缩,并且可以使用 React lazy 进行拆包,结合路由进行按需加载。
Q: 那这里是不是有个问题?既然你对文件进行拆包处理,那么肯定会造成文件变多,是不是有矛盾?
如何分析
其实不冲突,因为拆包后的文件,不可能同时加载的,所以就不会造成同一时间资源请求过多的请求。
但是要注意打包策略
我们通常会把包,分为两类
第三方包(node_modules 里面的)
自己实现的代码(src 目录里面的)
- 公共的
- 非公共的
所以我们可以把第三方包打一个包,公共的代码打一个包,非公共的代码打一个包。
第三方包:改动频率 – 小
公共代码包:改动频率 – 中
非公共代码包:改动频率 – 高
所以可以将 打包策略 结合 网络缓存 来做优化
对于不需要经常变动的资源(第三方包),可以使用 Cache-Control: max-age=31536000
(缓存一年) 并配合协商缓存 ETag
使用(一旦文件名变动才会下载新的文件)
对于需要频繁变动的资源(代码包),可以使用 Cache-Control: no-cache
并配合 ETag
使用,表示该资源已被缓存,但是每次都会发送请求询问资源是否更新。
A: 其实不冲突,因为拆包后的文件,不可能同时加载的,所以就不会造成同一时间资源请求过多的请求。但是可以使用 Webpack 的 optimization.splitChunks 进行打包策略的优化。将 node_modules 单独打包,以及将自己实现的代码也可以分为公共包和非公共包,并且分开打包。
最后还可以结合网络缓存来做加载性能优化。
#####答题思路
Webpack 打包优化,也是从两个方面来考虑:太多 和 太大。
- 可以通过设置 mode = production 来默认实现 Webpack 对代码的混淆和压缩,从而最大程度的减少代码体积
- 使用 Webpack + dynamic import 并结合路由的入口文件做拆包处理。
- 并且可以设定一些打包策略,并配合网络缓存做最终的加载性能优化。
####4. 实现 CDN 加速
为什么 CDN( 解决方案 -> nginx ) 可以实现加速
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2BRya1u4-1622953813869)(./assets/4.jpeg)]
游戏分区:北京一区,上海一区,广东一区…
Tips:CDN 服务器就是在你家门口放一台服务器,把所有的静态资源都同步到你家门口这台服务器上,以后只要你访问这个网站,都直接从这台服务器上下载静态资源。
Http1.1 请求:对于同一个协议、域名、端口,浏览器允许同时打开最多 6个 TCP 连接(最多同时发送 6个请求)
主站 Request URL: https://www.taobao.com/
JS&CSS Request URL: https://g.alicdn.com/??kg/home-2017/1.4.17/lib/style/lazy.css
图片 Request URL: https://img.alicdn.com/tfs/TB1_uT8a5ERMeJjSspiXXbZLFXa-143-59.png
字体 Request URL: https://at.alicdn.com/t/font_403341_n8tj33yn5peng66r.woff
扩展:Http2.0: 引入了多路复用的机制,可以最大化发送请求数量。
CDN 服务器主要是用来放静态资源的服务器,可以用来加速静态资源的下载
CDN 之所以能够加速,是因为会在很多地方都部署 CDN 服务器,如果用户需要下载静态资源,会自动选择最近的节点下载
同时由于 CDN 服务器的地址一般都跟主服务器的地址不同,所以可以破除浏览器对同一个域名发送请求的限制
####1. 渲染十万条数据如何不造成卡顿
为什么渲染很多条数据会造成浏览器卡顿
为什么渲染很多条数据会造成浏览器卡顿
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-olQwyv6s-1622953813871)(./assets/5.jpg)]
结论:
- 无论是浏览器中的 DOM 和 BOM,还是 NodeJS,它们都是基于 JavaScript 引擎之上开发出来的
- DOM 和 BOM 的处理最终都是要被转换成 JavaScript 引擎能够处理的数据
- 这个转换的过程很耗时
- 所以在浏览器中最消耗性能的就是操作 DOM
指导原则:尽可能的减少 DOM 的操作
eg:假如有一个需求,我们要在一个页面中 ul 标签里渲染 十万 个 li 标签。
// 插入十万条数据
const total = 100000;
let ul = document.querySelector('ul'); // 拿到 ul
// 懒加载的思路 -- 分段渲染
// 1. 一次渲染一屏的量
const once = 20;
// 2. 全部渲染完需要多少次,循环的时候要用
const loopCount = total / once;
// 3. 已经渲染了多少次
let countHasRender = 0;
function add() {
// 创建虚拟节点,(使用 createDocumentFragment 不会触发渲染)
const fragment = document.createDocumentFragment();
// 循环 20 次
for (let i = 0; i < once; i++) {
const li = document.createElement('li');
li.innerText = Math.floor(Math.random() * total);
fragment.appendChild(li);
}
// 最后把虚拟节点 append 到 ul 上
ul.appendChild(fragment);
// 4. 已渲染的次数 + 1
countHasRender += 1;
loop();
}
// 最重要的部分来了
function loop() {
// 5. 如果还没渲染完,那么就使用 requestAnimationFrame 来继续渲染
if (countHasRender < loopCount) {
// requestAnimationFrame 叫做逐帧渲染
// 类似于 setTimeout(add, 16);
// 帧:一秒钟播放多少张图片,一秒钟播放的图片越多,动画就约流畅
// 1000/60 = 16
window.requestAnimationFrame(add);
}
}
loop();
结论:
- 可以使用 document.createDocumentFragment 创建虚拟节点,从而避免引起没有必要的渲染
- 当所有的 li 都创建完毕后,一次性把虚拟节点里的 li 标签全部渲染出来
- 可以采取分段渲染的方式,比如一次只渲染一屏的数据
- 最后使用 window.requestAnimationFrame 来逐帧渲染
导致浏览器卡顿的原因一般都是操作 DOM 的次数太频繁。
如果想要渲染很多条数据不造成卡顿,那么就一定要尽可能的减少操作 DOM 的次数。
比方说 React 的虚拟 DOM,本质上就是用 JS 数据来模拟真实 DOM树,从而大大减少了操作真是 DOM 的次数。
还有在渲染的时候,可以使用 document.createDocumentFragment 创建虚拟节点,从而避免引起没有必要的渲染
也可以采取分段渲染的方式,最后使用 window.requestAnimationFrame 来逐帧渲染
记住:
在前端中性能优化的点主要分为两个阶段:
初始阶段,主要就是加载方面优化的问题。所有问题的指导原则就两点:
- 尽可能的减少前端资源的数量
- 尽可能的减小前端资源的大小
运行阶段,主要就是渲染方面优化的问题。只要是在浏览器中,所有的问题的指导原则就是:
- 尽可能的减少操作 DOM
文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr
文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc
文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8
文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束
文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求
文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname
文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include<stdio.h>#include<string.h>#include<stdlib.h>#include<malloc.h>#include<iostream>#include<stack>#include<queue>using namespace std;typed_二叉树的建立
文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码
文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词
文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限
文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定
文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland