炫技,从 12,前端黑科技实现原理揭秘

如今,webpack-spritesmith这款插件能实现我们想要的一切,先奉上配置内容:具体可参照webpack-spritesmith官方文档

执行webpack之后,就会在开发目录里生成上面两张图的结果,我们可以看看common.css里面的内容:

我们可以看到,所有我们之前放在common文件夹里的图片资源都自动地生成了相应的样式,这些都不需要我们手动处理,``webpack-spritesmith`这款插件就已经帮我们完成了!

1.3.3.使用字体图标(iconfont)

不论是压缩后的图片,还是雪碧图,终归还是图片,只要是图片,就还是会占用大量网络传输资源。但是字体图标的出现,却让前端开发者看到了另外一个神奇的世界。

我最喜欢用的是阿里矢量图标库(网址:www.iconfont.cn/),里面有大量的矢量图…

图片能做的很多事情,矢量图都能作,而且它只是往HTML里插入字符和CSS样式而已,和图片请求比起来资源占用完全不在一个数量级,如果你的项目里有小图标,就是用矢量图吧。

但如果我们做的是公司或者团队的项目,需要使用到许多自定义的字体图标,可爱的设计小姐姐们只是丢给你了几份.svg图片,你又该如何去做呢?

其实也很简单,阿里矢量图标库就提供了上传本地SVG资源的功能,这里另外推荐一个网站——icomoon。icomoon这个网站也为我们提供了将SVG图片自动转化成CSS样式的功能。(图片来自icomoon首页)

我们可以点击Import Icons按钮导入我们本地的SVG资源,然后选中他们,接下来生成CSS的事情,就交给icomoon吧,具体的操作,就和阿里矢量图标库类同了。

1.3.4.使用WebP

WebP格式,是谷歌公司开发的一种旨在加快图片加载速度的图片格式。图片压缩体积大约只有JPEG的2/3,并能节省大量的服务器带宽资源和数据空间。Facebook、Ebay等知名网站已经开始测试并使用WebP格式。

我们可以使用官网提供的Linux命令行工具对项目中的图片进行WebP编码,也可以使用我们的线上服务,这里我推荐叉拍云(网址:www.upyun.com/webp)。但是在实际…

1.4.网络传输性能检测工具——Page Speed

除了network版块,其实chrome还为我们准备好了一款监测网络传输性能的插件——Page Speed,咱们的文章封面,就是用的Page Speed的官方宣传图(因为我觉得这张图再合适不过了)。我们只需要通过下面步骤安装,就可以在chrome devtools里找到它了:chrome菜单→更多工具→拓展程序→chrome网上应用商店→搜索pagespeed后安转即可。

(PS:使用chrome应用商店需要翻墙,怎么翻墙我就不便多说了)

这就是Page Speed的功能界面:

我们只需要打开待测试的网页,然后点击Page Speed里的 Start analyzing按钮,它就会自动帮我们测试网络传输性能了,这是我的网站测试结果:

Page Speed最人性化的地方,便是它会对测试网站的性能瓶颈提出完整的建议,我们可以根据它的提示进行优化工作。这里我的网站已经优化到最好指标了(•́⌄•́๑)૭✧,Page Speed Score表示你的性能测试得分,100/100表示已经没有需要优化的地方。

优化完毕后再使用chorme devtools的network版块测量一下我们网页的白屏时间还有首屏时间,是不是得到了很大的提升?

1.5.使用CDN

Last but not least,

再好的性能优化实例,也必须在CDN的支撑下才能到达极致。

如果我们在Linux下使用命令$ traceroute targetIp 或者在Windows下使用批处理 > tracert targetIp,都可以定位用户与目标计算机之间经过的所有路由器,不言而喻,用户和服务器之间距离越远,经过的路由器越多,延迟也就越高。使用CDN的目的之一便是解决这一问题,当然不仅仅如此,CDN还可以分担IDC压力。

当然,凭着我们单个人的资金实力(除非你是王思聪)是必定搭建不起来CDN的,不过我们可以使用各大企业提供的服务,诸如腾讯云等,配置也十分简单,这里就请大家自行去推敲啦。

2.页面渲染性能优化


2.1.浏览器渲染过程(Webkit)

其实大家应该对浏览器将的HTML渲染机制比较熟悉了,基本流程同上图所述,大家在入门的时候,你的导师或者前辈可能会告诉你,在渲染方面我们要减少重排和重绘,因为他们会影响浏览器性能。不过你一定不知道其中原理是什么,对吧。今天我们就结合《Webkit技术内幕》(这本书我还是很推荐大家买来看看,好歹作为一名前端工程师,你得知道我们天天接触的浏览器内核是怎样工作的)的相关知识,给大家普及普及那些深层次的概念。

PS:这里提到了Webkit内核,我顺带提一下浏览器内部的渲染引擎、解释器等组件的关系,因为经常有师弟或者一些前端爱好者向我问这方面的知识,分不清他们的关系,我就拿一张图来说明:(如果你对着不感兴趣,可以直接跳过)

浏览器的解释器,是包括在渲染引擎内的,我们常说的Chrome(现在使用的是Blink引擎)和Safari使用的Webkit引擎,Firefox使用的Gecko引擎,指的就是渲染引擎。而在渲染引擎内,还包括着我们的HTML解释器(渲染时用于构造DOM树)、CSS解释器(渲染时用于合成CSS规则)还有我们的JS解释器。

2.2.DOM渲染层与GPU硬件加速

如果我告诉你,一个页面是有许多许多层级组成的,他们就像千层面那样,你能想象出这个页面实际的样子吗?这里为了便于大家想象,我附上一张之前Firefox的3D View插件的页面Layers层级图:

对,你没看错,页面的真实样子就是这样,是由多个DOM元素渲染层(Layers)组成的,实际上一个页面在构建完render tree之后,是经历了这样的流程才最终呈现在我们面前的:

①浏览器会先获取DOM树并依据样式将其分割成多个独立的渲染层

②CPU将每个层绘制进绘图中

③将位图作为纹理上传至GPU(显卡)绘制

④GPU将所有的渲染层缓存(如果下次上传的渲染层没有发生变化,GPU就不需要对其进行重绘)并复合多个渲染层最终形成我们的图像

从上面的步骤我们可以知道,布局是由CPU处理的,而绘制则是由GPU完成的。

其实在chrome中,也为我们提供了相关插件供我们查看页面渲染层的分布情况,以及GPU的占用率:(所以说,平时我们得多去尝试尝试chrome的那些莫名其妙的插件,真的会发现好多东西都是神器)

chrome开发者工具菜单→more tools→Layers(开启渲染层功能模块)

chrome开发者工具菜单→more tools→rendering(开启渲染性能监测工具)

执行上面的操作后,你会在浏览器里看到这样的效果:

太多东西了,分模块讲吧:

(一)最先是页面右上方的小黑窗:其实提示已经说的很清楚了,它显示的就是我们的GPU占用率,能够让我们清楚地知道页面是否发生了大量的重绘。

(二)Layers版块:这就是用于显示我们刚提到的DOM渲染层的工具了,左侧的列表里将会列出页面里存在哪些渲染层,还有这些渲染层的详细信息。

(三)Rendering版块:这个版块和我们的控制台在同一个地方,大家可别找不到它。前三个勾选项是我们最常使用的,让我来给大家解释一下他们的功能(充当一次免费翻译)

①Paint flashing:勾选之后会对页面中发生重绘的元素高亮显示

②Layer borders:和我们的Layer版块功能类似,它会用高亮边界突出我们页面中的各个渲染层

③FPS meter:就是开启我们在(一)中提到的小黑窗,用于观察我们的GPU占用率

可能大家会问我,和我提到DOM渲染层这么深的概念有什么用啊,好像跟性能优化没一点关系啊?大家应该还记得我刚说到GPU会对我们的渲染层作缓存对吧,那么大家试想一下,如果我们把那些一直发生大量重排重绘的元素提取出来,单独触发一个渲染层,那样这个元素不就不会“连累”其他元素一块重绘了对吧。

那么问题来了,什么情况下会触发渲染层呢?大家只要记住:

video元素、WebGL、Canvas、CSS3 3D、CSS滤镜、z-index大于某个相邻节点的元素都会触发新的Layer,其实我们最常用的方法,就是给某个元素加上下面的样式:

transform: translateZ(0);

backface-visibility: hidden;

这样就可以触发渲染层啦(__) 。

我们把容易触发重排重绘的元素单独触发渲染层,让它与那些“静态”元素隔离,让GPU分担更多的渲染工作,我们通常把这样的措施成为硬件加速,或者是GPU加速。大家之前肯定听过这个说法,现在完全清楚它的原理了吧。

2.3.重排与重绘

现在到我们的重头戏了,重排和重绘。先抛出概念:

①重排(reflow):渲染层内的元素布局发生修改,都会导致页面重新排列,比如窗口的尺寸发生变化、删除或添加DOM元素,修改了影响元素盒子大小的CSS属性(诸如:width、height、padding)。

②重绘(repaint):绘制,即渲染上色,所有对元素的视觉表现属性的修改,都会引发重绘。

我们习惯使用chrome devtools中的performance版块来测量页面重排重绘所占据的时间:

①蓝色部分:HTML解析和网络通信占用的时间

②黄色部分:JavaScript语句执行所占用时间

③紫色部分:重排占用时间

④绿色部分:重绘占用时间

不论是重排还是重绘,都会阻塞浏览器。要提高网页性能,就要降低重排和重绘的频率和成本,尽可能少地触发重新渲染。正如我们在2.3中提到的,重排是由CPU处理的,而重绘是由GPU处理的,CPU的处理效率远不及GPU,并且重排一定会引发重绘,而重绘不一定会引发重排。所以在性能优化工作中,我们更应当着重减少重排的发生。

这里给大家推荐一个网站,里面详细列出了哪些CSS属性在不同的渲染引擎中是否会触发重排或重绘:

csstriggers.com/   (图片来自官网)

2.4.优化策略

谈了那么多理论,最实际不过的,就是解决方案,大家一定都等着急了吧,做好准备,一大波干货来袭:

(一)CSS属性读写分离:浏览器每次对元素样式进行读操作时,都必须进行一次重新渲染(重排 + 重绘),所以我们在使用JS对元素样式进行读写操作时,最好将两者分离开,先读后写,避免出现两者交叉使用的情况。最最最客观的解决方案,就是不用JS去操作元素样式,这也是我最推荐的。

(二)通过切换class或者style.csstext属性去批量操作元素样式

(三)DOM元素离线更新:当对DOM进行相关操作时,例如innerHTML、appendChild等都可以使用Document Fragment对象进行离线操作,待元素“组装”完成后再一次插入页面,或者使用display:none 对元素隐藏,在元素“消失”后进行相关操作。

(四)将没用的元素设为不可见:visibility: hidden,这样可以减小重绘的压力,必要的时候再将元素显示。

(五)压缩DOM的深度,一个渲染层内不要有过深的子元素,少用DOM完成页面样式,多使用伪元素或者box-shadow取代。

(六)图片在渲染前指定大小:因为img元素是内联元素,所以在加载图片后会改变宽高,严重的情况会导致整个页面重排,所以最好在渲染前就指定其大小,或者让其脱离文档流。

(七)对页面中可能发生大量重排重绘的元素单独触发渲染层,使用GPU分担CPU压力。(这项策略需要慎用,得着重考量以牺牲GPU占用率能否换来可期的性能优化,毕竟页面中存在太多的渲染层对于GPU而言也是一种不必要的压力,通常情况下,我们会对动画元素采取硬件加速。)

3.JS阻塞性能


JavaScript在网站开发中几乎已经确定了垄断地位,哪怕是一个再简单不过的静态页面,你都可能看到JS的存在,可以说,没有JS,就基本没有用户交互。然而,脚本带来的问题就是他会阻塞页面的平行下载,还会提高进程的CPU占用率。更有甚者,现在node.js已经在前端开发中普及,稍有不慎,我们引发了内存泄漏,或者在代码中误写了死循环,会直接造成我们的服务器奔溃。在如今这个JS已经遍布前后端的时代,性能的瓶颈不单单只是停留在影响用户体验上,还会有更多更为严重的问题,对JS的性能优化工作不可小觑。

在编程的过程中,如果我们使用了闭包后未将相关资源加以释放,或者引用了外链后未将其置空(比如给某DOM元素绑定了事件回调,后来却remove了该元素),都会造成内存泄漏的情况发生,进而大量占用用户的CPU,造成卡顿或死机。我们可以使用chrome提供的JavaScript Profile版块,开启方式同Layers等版块,这里我就不再多说了,直接上效果图:

我们可以清除看见JS执行时各函数的执行时间以及CPU占用情况,如果我在代码里增加一行while(true){}, 那么它的占用率一定会飙升到一个异常的指标(亲测93.26%)。

其实浏览器强大的内存回收机制在大多数时候避免了这一情况的发生,即便用户发生了死机,他只要结束相关进程(或关闭浏览器)就可以解决这一问题,但我们要知道,同样的情况还会发生在我们的服务器端,也就是我们的node中,严重的情况,会直接造成我们的服务器宕机,网站奔溃。所以更多时候,我们都使用JavaScript Profile版块来进行我们的node服务的压力测试,搭配node-inspector 插件,我们能更有效地检测JS执行时各函数的CPU占用率,针对性地进行优化。

(PS:没修炼到一定水平,千万别在服务端使用闭包,一个是真没啥用,我们会有更多优良的解决办法,二是真的很容易内存泄漏,造成的后果是你无法预期的)

4.【拓展】负载均衡


之所以将负载均衡作为拓展内容,是因为如果是你自己搭建的个人网站,或者中小型网站,其实并不需要考虑多大的并发量,但是如果你搭建的是大型网站,负载均衡便是开发过程不可或缺的步骤。

4.1.Node.js处理IO密集型请求

现在的开发流程都注重前后端分离,也就是软件工程中常提到的“高内聚低耦合”的思想,你也可以用模块化的思想去理解,前后解耦就相当于把一个项目分成了前端和后端两个大模块,中间通过接口联系起来,分别进行开发。这样做有什么好处?我就举最有实际效果的一点:“异步编程”。这是我自己想的名字,因为我觉得前后解耦的形式很像我们JS中的异步队列,传统的开发模式是“同步”的,前端需要等后端封装好接口,知道了能拿什么数据,再去开发,时间短,工程大。而解耦之后,我们只需要提前约定好接口,前后两端就可以同时开发,不仅高效而且省时。

我们都知道node的核心是事件驱动,通过loop去异步处理用户请求,相比于传统的后端服务,它们都是将用户的每个请求分配到异步队列进行处理,推荐大家去看这样一篇博文:Node.js : 我只需要一个店小二。特别生动地讲解了事件驱动的运行机制,通俗易懂。事件驱动的最大优势是什么?就是在高并发IO时,不会造成堵塞,对于直播类网站,这点是至关重要的,我们有成功的先例——快手,快手强大的IO高并发究其本质一定能追溯到node。

其实现在的企业级网站,都会搭建一层node作为中间层。大概的网站框架如图所示:

4.2.pm2实现Node.js“多线程”

我们都知道node的优劣,这里分享一份链接,找了挺久写的还算详细:https://www.zhihu.com/question/19653241/answer/15993549。其实都是老套路,那些说node不行的都是指着node是单线程这一个软肋开撕,告诉你,我们有解决方案了——pm2。这是它的官网:pm2.keymetrics.io/ 。它是一款node.js进程管理器,具体的功能,就是能在你的计算机里的每一个内核都启动一个node.js服务,也就是说如果你的电脑或者服务器是多核处理器(现在也少见单核了吧),它就能启动多个node.js服务,并且它能够自动控制负载均衡,会自动将用户的请求分发至压力小的服务进程上处理。听起来这东西简直就是神器啊!而且它的功能远远不止这些,这里我就不作过多介绍了,大家知道我们在上线的时候需要用到它就行了,安装的方法也很简单,直接用npm下到全局就可以了$ npm i pm2 -g具体的使用方法还有相关特性可以参照官网。这里我在build文件夹内添加了pm2.json文件,这是pm2的启动配置文件,我们可以自行配置相关参数,具体可参考github源码,运行时我们只要在上线目录下输入命令$ pm2 start pm2.json即可。

下面是pm2启动后的效果图:

4.3.nginx搭建反向代理

在开始搭建工作之前,首先得知道什么是反向代理。可能大家对这个名词比较陌生,先上一张图:

所谓代理就是我们通常所说的中介,网站的反向代理就是指那台介于用户和我们真实服务器之间的服务器(说的我都拗口了),它的作用便是能够将用户的请求分配到压力较小的服务器上,其机制是轮询。听完这句话是不是感觉很耳熟,没错,在我介绍pm2的时候也说过同样的话,反向代理起到的作用同pm2一样也是实现负载均衡,你现在应该也明白了两者之间的差异,反向代理是对服务器实现负载均衡,而pm2是对进程实现负载均衡。大家如果想深入了解反向代理的相关知识,我推荐知乎的一个贴子:www.zhihu.com/question/24… 。但是大家会想到,配服务器是运维的事情啊,和我们前端有什么关系呢?的确,在这部分,我们的工作只有一些,只需要向运维提供一份配置文档即可。

http {

upstream video {

ip_hash;

server localhost:3000;

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
img

文末

从转行到现在,差不多两年的时间,虽不能和大佬相比,但也是学了很多东西。我个人在学习的过程中,习惯简单做做笔记,方便自己复习的时候能够快速理解,现在将自己的笔记分享出来,和大家共同学习。

个人将这段时间所学的知识,分为三个阶段:

第一阶段:HTML&CSS&JavaScript基础

第二阶段:移动端开发技术

第三阶段:前端常用框架

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

  • 推荐学习方式:针对某个知识点,可以先简单过一下我的笔记,如果理解,那是最好,可以帮助快速解决问题;

自己的笔记分享出来,和大家共同学习。

个人将这段时间所学的知识,分为三个阶段:

第一阶段:HTML&CSS&JavaScript基础

第二阶段:移动端开发技术

第三阶段:前端常用框架

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

  • 推荐学习方式:针对某个知识点,可以先简单过一下我的笔记,如果理解,那是最好,可以帮助快速解决问题;

  • 大厂的面试难在,针对一个基础知识点,比如JS的事件循环机制,不会上来就问概念,而是换个角度,从题目入手,看你是否真正掌握。所以对于概念的理解真的很重要。

  • 7
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值