技术标签: 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
文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态
文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境
文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn
文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker
文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机
文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk
文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入
文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。 Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。
文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动
文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计
文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;gt;Jni-&amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图
文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法