前端面试--性能优化

CDN优化访问速度

当你从互联网上访问一个网站时,浏览器会请求网站的各种资源,比如图片、CSS文件、JavaScript文件等。这些资源通常需要从网站的服务器上下载,但是如果网站使用了 CDN(内容分发网络),情况会有所不同。

CDN(内容分发网络)是一种分布式存储和传递内容的服务。它的工作原理类似于将网站的资源复制到多个位于世界各地的服务器上。当你访问一个使用了 CDN 的网站时,CDN 会根据你的地理位置,选择离你最近的服务器来提供网站的资源,而不是直接从网站的原始服务器上获取。这样做的好处是可以加快网站内容的加载速度,因为资源可以从距离你更近的服务器上获取,减少了网络延迟。

总结来说,CDN 的作用就是通过在全球范围内部署服务器,加速网站内容的传输,提高用户访问网站时的速度和性能。使用 CDN 可以帮助网站提供更快的加载速度、更好的用户体验,并减轻原始服务器的负载压力。

CDN的工作原理(个人简洁,比较白话)

想象一下你在家,想要吃一份外卖。如果外卖餐厅就在你家附近,你可以很快就拿到美食。但是如果外卖餐厅在城市的另一端,那送餐可能会花费更多时间。

现在,把外卖餐厅比作网站的服务器,而你自己就是网站的访问者。当你访问一个网站时,通常网站的内容(比如图片、视频、网页)都保存在服务器上。如果这些服务器离你很远,就会影响网站的加载速度,就像外卖送餐需要更长时间一样。

这时 CDN(内容分发网络)就发挥作用了。CDN 就像是在不同地方设置了很多分店的外卖连锁店。当你访问一个使用 CDN 的网站时,CDN 会把网站的内容存储在离你较近的服务器上,就像是在你家附近有一家外卖连锁店,让你更快地拿到美食一样。

因此,CDN 的工作原理就是在全球范围内设置许多服务器,将网站的内容分发到这些服务器上,让用户可以从离自己更近的服务器获取网站内容,提高网站的加载速度和性能。使用 CDN 可以让网站更快地加载,提供更好的用户体验,同时减轻原始服务器的负载压力。

总的来说,CDN 的目的就是让网站的内容能够更快地传输到用户手中,就像外卖连锁店让美食更快送到你家一样,让你更快地访问网站内容,享受更好的上网体验

4. CDN的使用场景

使用第三方的CDN服务:如果想要开源一些项目,可以使用第三方的CDN服务

使用CDN进行静态资源的缓存:将自己网站的静态资源放在CDN上,比如js、css、图片等。可以将整个项目放在CDN上,完成一键部署。

直播传送:直播本质上是使用流媒体进行传送,CDN也是支持流媒体传送的,所以直播完全可以使用CDN来提高访问速度。CDN在处理流媒体的时候与处理普通静态文件有所不同,普通文件如果在边缘节点没有找到的话,就会去上一层接着寻找,但是流媒体本身数据量就非常大,如果使用回源的方式,必然会带来性能问题,所以流媒体一般采用的都是主动推送的方式来进行。

懒加载

1. 懒加载的概念

懒加载也叫做延迟加载、按需加载,指的是在长网页中延迟加载图片数据,是一种较好的网页性能优化的方式。在比较长的网页或应用中,如果图片很多,所有的图片都被加载出来,而用户只能看到可视窗口的那一部分图片数据,这样就浪费了性能。 如果使用图片的懒加载就可以解决以上问题。在滚动屏幕之前,可视化区域之外的图片不会进行加载,在滚动屏幕时才加载。这样使得网页的加载速度更快,减少了服务器的负载。懒加载适用于图片较多,页面列表较长(长列表)的场景中。

2. 懒加载的特点

减少无用资源的加载:使用懒加载明显减少了服务器的压力和流量,同时也减小了浏览器的负担。

提升用户体验: 如果同时加载较多图片,可能需要等待的时间较长,这样影响了用户体验,而使用懒加载就能大大的提高用户体验。

防止加载过多图片而影响其他资源文件的加载 :会影响网站应用的正常使用。
 

3. 懒加载的实现原理

图片的加载是由src引起的,当对src赋值时,浏览器就会请求图片资源。根据这个原理,我们使用HTML5 的data-xxx属性来储存图片的路径,在需要加载图片的时候,将data-xxx中图片的路径赋值给src,这样就实现了图片的按需加载,即懒加载。

知识点:

(1)window.innerHeight 是浏览器可视区的高度

(2)document.body.scrollTop || document.documentElement.scrollTop 是浏览器滚动的过的距离

(3)imgs.offsetTop 是元素顶部距离文档顶部的高度(包括滚动条的距离)

(4)图片加载条件:img.offsetTop < window.innerHeight + document.body.scrollTop;

<body>
<div id="app">
  <img class="lazy" data-src="image.jpg" alt="Lazy Loaded Image">
</div>
<script>
  document.addEventListener('DOMContentLoaded', function() {
    let lazyImages = document.querySelectorAll('.lazy');

    function lazyLoad() {
      lazyImages.forEach(function(image) {
        if (image.getBoundingClientRect().top < window.innerHeight) {
          image.src = image.getAttribute('data-src');
          image.classList.remove('lazy');
        }
      });
    }

    lazyLoad();

    document.addEventListener('scroll', lazyLoad);
    window.addEventListener('resize', lazyLoad);
  });
</script>
4. 懒加载与预加载的区别

懒加载和预加载是类似相反的存在,懒加载是延迟加载或者不加载,目的是减轻前端服务的压力,而预加载是提前加载,目的是为了提高用户体验。

回流与重绘

回流

回流(reflow)是浏览器重新计算和重新绘制网页布局的过程。当网页中的元素发生变化(比如大小、内容、位置等),浏览器就需要重新计算元素的位置和大小,然后重新绘制整个页面,以确保页面显示正确。

想象一下你在画一幅画,如果你需要移动一幅已经画好的部分,那么你可能需要重新调整其他部分的位置,然后重新绘制整幅画。类似地,在网页中,如果一个元素的大小或位置发生变化,那么浏览器就需要重新计算其他元素的位置,然后重新绘制整个页面,以适应新的变化。

回流是一种消耗性能的操作,因为它涉及到重新计算和重新绘制页面的多个部分。因此,为了提高页面的性能,我们应该尽量减少回流的次数。一些触发回流的操作包括改变元素的大小、位置、内容,以及调整窗口大小等。优化网页布局和避免频繁的回流能够提升页面的性能和用户体验。

希望这个简单的解释能帮助您理解回流这个概念。如果您有任何其他问题或需要进一步解释,请随时告诉我。

重绘

重绘(repaint)是指浏览器在不改变页面布局的情况下,重新绘制页面元素的过程。当页面的样式发生变化(比如颜色、字体、背景等),但不影响元素在文档流中的位置时,浏览器会进行重绘操作,更新元素的外观,而不会改变它们的位置。

想象一下你在房间里重新粉刷墙壁:如果你只是改变了墙壁的颜色,而没有移动任何家具,房间的布局仍然是一样的。类似地,在网页中,如果你只是改变了元素的颜色或字体样式,但没有改变它们的位置,浏览器就会进行重绘,更新元素的外观,而不需要重新计算它们的位置。

重绘的操作相对于回流来说更轻量级,因为它只涉及更新元素的外观,而不需要重新计算整个页面布局。尽管重绘消耗的资源相对较少,但过多的重绘操作仍然会影响页面的性能。因此,在编写网页样式时,我们应该尽量减少不必要的重绘,以提高页面的性能和用户体验。

如何避免回流与重绘 

减少回流与重绘的措施: 操作DOM时,尽量在低层级的DOM节点进行操作 不要使用table布局, 一个小的改动可能会使整个table进行重新布局 使用CSS的表达式 不要频繁操作元素的样式,对于静态页面,可以修改类名,而不是样式。

使用absolute或者fixed,使元素脱离文档流,这样他们发生变化就不会影响其他元素 避免频繁操作DOM,可以创建一个文档片段documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中 将元素先设置display: none,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。

将DOM的多个读操作(或者写操作)放在一起,而不是读写操作穿插着写。这得益于浏览器的渲染队列机制。 浏览器针对页面的回流与重绘,进行了自身的优化——渲染队列 浏览器会将所有的回流、重绘的操作放在一个队列中,当队列中的操作到了一定的数量或者到了一定的时间间隔,浏览器就会对队列进行批处理。这样就会让多次的回流、重绘变成一次回流重绘。 上面,将多个读操作(或者写操作)放在一起,就会等所有的读操作进入队列之后执行,这样,原本应该是触发多次回流,变成了只触发一次回流。

 如何优化动画

对于如何优化动画,我们知道,一般情况下,动画需要频繁的操作DOM,就就会导致页面的性能问题,我们可以将动画的position属性设置为absolute或者fixed,将动画脱离文档流,这样他的回流就不会影响到页面了。

DocumentFragment

DocumentFragment 是一个轻量级的 DOM 节点对象,可以用来包含和操作多个 DOM 元素,而不会直接影响文档的结构。它可以帮助提高性能,因为将多个元素添加到 DocumentFragment 中再统一插入到文档中,比直接一个个操作 DOM 元素更高效。

下面是一个简单的示例,展示如何使用 DocumentFragment 创建一组列表项并一次性插入到文档中:

<body>
<div id="app"></div>
<script>
  // 创建一个 DocumentFragment
  const fragment = document.createDocumentFragment();

  // 创建一个包含多个列表项的数组
  const items = ['Item 1', 'Item 2', 'Item 3', 'Item 4'];

  // 在 DocumentFragment 中添加列表项
  items.forEach(itemText => {
    const li = document.createElement('li');
    li.textContent = itemText;
    fragment.appendChild(li);
  });

  // 将 DocumentFragment 中的内容一次性插入到文档中
  const list = document.createElement('ul');
  list.appendChild(fragment);

  // 将列表添加到文档中的 app 元素中
  document.getElementById('app').appendChild(list);
</script>

节流和防抖

1. 对节流与防抖的理解
  • 函数防抖是指在事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。这可以使用在一些点击请求的事件上,避免因为用户的多次点击向后端发送多次请求。
  • 函数节流是指规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。节流可以使用在 scroll 函数的事件监听上,通过事件节流来降低事件调用的频率。

防抖函数的应用场景:
  • 按钮提交场景:防⽌多次提交按钮,只执⾏最后提交的⼀次
  • 服务端验证场景:表单验证需要服务端配合,只执⾏⼀段连续的输⼊事件的最后⼀次,还有搜索联想词功能类似⽣存环境请⽤lodash.debounce

节流函数的适⽤场景:
  • 拖拽场景:固定时间内只执⾏⼀次,防⽌超⾼频次触发位置变动
  • 缩放场景:监控浏览器resize
  • 动画场景:避免短时间内多次触发动画引起性能问题

防抖和节流的实现可以看我其他帖子,上面有防抖节流的详细说明

图片优化

1. 如何对项目中的图片进行优化?
  1. 不用图片。很多时候会使用到很多修饰类图片,其实这类修饰图片完全可以用 CSS 去代替。
  2. 对于移动端来说,屏幕宽度就那么点,完全没有必要去加载原图浪费带宽。一般图片都用 CDN 加载,可以计算出适配屏幕的宽度,然后去请求相应裁剪好的图片。
  3. 小图使用 base64 格式
  4. 将多个图标文件整合到一张图片中(雪碧图)
  5. 选择正确的图片格式:
    • 对于能够显示 WebP 格式的浏览器尽量使用 WebP 格式。因为 WebP 格式具有更好的图像数据压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量,缺点就是兼容性并不好
    • 小图使用 PNG,其实对于大部分图标这类图片,完全可以使用 SVG 代替
    • 照片使用 JPEG

  • 25
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值