网站首页 > 技术文章 正文
前端优化的步骤
首先要设定优化目标,测试当前性能,找出问题,提出解决方案。
优化的方向
一般来说,网站优化的需要考虑的方面有:
1.网络请求与下载
减少HTTP请求次数是缩短响应时间的关键
- 开启一个链接(tcp/ip的三次握手过程)-> 发送请求 -> 等待(网络延迟跟服务器的处理时间)-> 下载数据。
- 一个http请求绝大多数的时间消耗在了建立连接跟等待的时间,优化的方法是减少http请求。
减小加载文件的大小
- 页面上部分文件加载了,但在页面中却没有使用。
- 文件中含有没有使用的代码部分。
减少请求,减小文件
减少图片
- css sprites将多张图片合并成一幅单独的图片,使用css的background-position属性,将html元素的背景图片放到sprites 图片中的期望位置上。使用这项技术的附加优点是他降低了下载量,合并后的图片比分离的图片和更小,因为它降低了图片自身的开销(颜色表、格式信息等等)。实际项目中css sprites是一项体力活,因为开发过程中需要对这张大图进行维护(添加、减少图片)。
- 内联图片
- 通过使用data:URL模式可以在页面中包含图片而无需任何额外的请求。
- 对于较小的图片来说可以直接内联到web页面中,但对于大图片内联到页面里会导致页面变大,聪明的做法是使用css,将内联的图片作为背景使用,并放到外部样式表中,这意味着数据可以缓存在样式表内部。使用外部样式表虽然增加了一个http请求,但样式可以被浏览器缓存,得到额外的收获。
- IE8以下的浏览器不支持这种方式,而IE8在数据大小上有限制,只能支持23kb以内的数据。
- IconFont图标字体,这是近年来新流行的一种以字体代替图片的技术。它可以适应任何分辨率而不会出现图片模糊问题,与图片相比它具有更小的容量,更高的灵活性(像字体一样可以设置图标大小、颜色、透明度、hover状态、反转等)。IE8以上的浏览器都支持该技术。
减少脚本和样式表
- 减少脚本与样式表的请求主要原则就是合并。
- 在实际开发中我们遵循模块化的原则将代码分散到许多小文件中。但对于线上页面,将这些小文件合并到一个文件中。
减少DNS查询次数
DNS查询也消耗响应时间,如果我们的网页内容来自各个不同的domain (比如嵌入了开放广告,引用了外部图片或脚本),那么客户端首次解析这些domain也需要消耗一定的时间。DNS查询结果缓存在本地系统和浏览器中一段时间,所以DNS查询一般是对首次访问响应速度有所影响
控制Cookie大小和污染
- Cookie是本地的磁盘文件,每次浏览器都会去读取相应的Cookie,所以建议去除不必要的Coockie,使Coockie体积尽量小以减少对用户响应的影响。
- 使用Cookie跨域操作时注意在适应级别的域名上设置coockie以便使子域名不受其影响。
- Cookie是有生命周期的,所以请注意设置合理的过期时间,合理的Expire时间和不要过早去清除coockie,都会改善用户的响应时间。
避免页面跳转,重定向
将一个URL重新路由到另一个URL。重定向功能是通过301和302这两个HTTP状态码完成的,如: 浏览器自动重定向请求到Location指定的URL上,重定向的主要问题是降低了用户体验。 种最耗费资源、经常发生而很容易被忽视的重定向是URL的最后缺少/,导致自动产生结尾斜线的原因是,浏览器在进行get请求时必须指定一些路径;如果没有路径它就会简单的使用文档根。缺少结尾斜线发生重定向是很多web服务器的默认行为。需要在服务器端设置方可消除。
2.缓存
减小Cookie
Cookie被用来做认证或个性化设置,其信息被包含在http报文头中,对于cookie我们要注意以下几点,来提高请求的响应速度,
- 去除没有必要的cookie,如果网页不需要cookie就完全禁掉
- 将cookie的大小减到最小
- 注意cookie设置的domain级别,没有必要情况下不要影响到sub-domain
- 设置合适的过期时间,比较长的过期时间可以提高响应速度。
页面内容使用无cookie域名
大多数网站的静态资源都没必要cookie,我们可以采用不同的domain来单独存放这些静态文件,这样做不仅可以减少cookie大小从而提高响应速度,还有一个好处是有些proxy拒绝缓存带有cookie的内容,如果能将这些静态资源cookie去除,那就可以得到这些proxy的缓存支持。
- 常见的划分domain的方式是将静态文件放在static.example.com,动态内容放在www.example.com
- 也有一些网站需要在二级域名上应用cookie,所有的子域都会继承,这种情况下一般会再购买一个专门的域名来存放cookie-free的静态资源。
使用小且可缓存的favicon.ico
网站图标文件favicon.ico,不管你服务器有还是没有,浏览器都会去尝试请求这个图标。所以我们要确保这个图标
- 存在
- 文件尽量小,最好小于1k
- 设置一个长的过期时间
3.页面内部大小性能优化与显示
优化图像
当美工完成了网站的图片设计后,我们可以在上传图片之前对其做以下优化
- 检查GIF图片中图像颜色的数量是否和调色板规格一致。如果你发现图片中只用到了4种颜色,而在调色板的中显示的256色的颜色槽,那么这张图片就还有压缩的空间。可以使用imagemagick检查: identify -verbose image.gif
- 尝试把GIF格式转换成PNG格式,看看是否节省空间。大多数情况下是可以压缩的。下面这条简单的命令可以安全地把GIF格式转换为PNG格式: convert image.gif image.png
- 在所有的PNG图片上运行pngcrush(或者其它PNG优化工具)。例如: pngcrush image.png -rem alla -reduce -brute result.png
- 在所有的JPEG图片上运行jpegtran。这个工具可以对图片中的出现的锯齿等做无损操作,同时它还可以用于优化和清除图片中的注释以及其它无用信息 jpegtran -copy none -optimize -perfect src.jpg dest.jpg
减小脚本和样式表
- 在合并脚本和样式表时,还需要使用工具,精简:移除不必要的字符以减小文件大小缩减下载时间混淆:改写源代码,比如函数和变量名使用更短的标量名
- 对于采用AMD或CMD进行模块化开发的,在合并过程中通常会将依赖的其他模块打包到一个文件中,而模板html通常以字符串的方式内联到Javascript文件中。
- 移除重复脚本:这条说的主要是避免在页面中多次加入同一份Javascript代码,如果我们的开发中有依赖管理的方式比如AMD、CMD,基本不会出现这种情况。
- 常用构建工具:gulp,webpack,fis
样式表放顶部
- 将样式表放在底部会导致浏览器阻止内容逐步呈现。为避免当页面变化时重绘页面元素,浏览器会阻塞页面呈现,直到样式表解析完毕
- 将样式表放在顶部并不会减少资源的加载时间,它减少的是页面的呈现时间。
脚本放底部
script文件放在页面顶部会阻塞页面的逐步呈现。script元素会阻塞后续内容的解析(不论JavaScript是内嵌的还是外链的),浏览器在执行JavaScript代码时,不能同时做其它事情,即每次出现都会让页面等待脚本的解析和执行,JavaScript代码执行完成后,才继续渲染页面。这个也就是JavaScript的阻塞特性。解决的办法就是将script标签放在页面底部。这样既可以让内容逐步呈现,提高下载的并行度,有效的防止JavaScript的阻塞,又能使得页面的HTML结构能更快的释放。
避免CSS表达式
- 表达式的问题就在于它的计算频率要比我们想象的多。不仅仅是在页面显示和缩放时,就是在页面滚动、乃至移动鼠标时都会要重新计算一次。
- 使用事件句柄来代替CSS表达式是一个可行办法。
使用外部脚本和样式表
使用外部Javascript和CSS文件可以使这些文件被浏览器缓存,从而在不同的请求内容之间重用。 同时将Javascript和CSS从inline变为external也减小了网页内容的大小。
使用外部Javascript和CSS文件的决定因素在于这些外部文件的重用率,如果用户在浏览我们的页面时会访问多次相同页面或者可以重用脚本的不同页面,那么外部文件形式可以给你带来很大的好处。但对于用户通常只会访问一次的页面,例如microsoft.com首页,那inline的javascript和css相对来说可以提供更高的效率。
延迟加载
延迟加载需要我们知道我们的网页最初加载需要的最小内容集是什么。剩下的内容就可以推到延迟加载的集合中。 Javascript是典型的可以延迟加载内容。一个比较激进的做法是开发网页时先确保网页在没有Javascript的时候也可以基本工作,然后通过延迟加载脚本来完成一些高级的功能。
提前加载
与延迟加载目的相反,提前加载的是为了提前加载接下来网页中访问的资源,下面是提前加载的类型
- **无条件提前加载:**当前网页加载完成后,马上去下载一些其他的内容。例如google会在页面加载成功之后马上去下载一个所有结果中会用到的image sprite。
- **有条件加载:**根据用户的输入推断需要加载的内容
- **有预期的的加载:**这种情况一般发生在网页重新设计时,由于用户经常访问旧网页,本地对旧的网页内容缓存充分从而显得旧网页速度很快,而新的网页内容却没有缓存,设计者可以在旧网页的内容中预先加载一些新网页中可能用到的内容,这样新的网页就会生下来一些需要下载的资源。
减少Dom元素的数量
网页中元素过多对网页的加载和脚本的执行都是沉重的负担,500个元素和5000个元素在加载速度上会有很大差别。 想知道你的网页中有多少元素,通过在浏览器中的一条简单命令就可以算出document.getElementsByTagName('*').length
减少DOM访问,减少Repaint 和 Reflow
通过Javascript访问DOM元素没有我们想象中快,元素多的网页尤其慢,对于Javascript对DOM的访问我们要注意
- 缓存已经访问过的元素
- Offline更新节点然后再加回DOM Tree
- 避免通过Javascript修复layout
根据域名划分内容
- 浏览器一般对同一个域的下载连接数有所限制,按照域名划分下载内容可以浏览器增大并行下载连接,但是注意控制域名使用在2-4个之间,不然dns查询也是个问题。
- 一般网站规划会将静态资源放在类似于static.example.com,动态内容放在www.example.com上。这样做还有一个好处是可以在静态的域名上避免使用cookie。
减少iframe数量
使用iframe要注意理解iframe的优缺点
- 优点可以用来加载速度较慢的内容,例如广告。安全沙箱保护。浏览器会对iframe中的内容进行安全控制。脚本可以并行下载
- 缺点即使iframe内容为空也消耗加载时间会阻止页面加载标签没有语义
避免404
404我们都不陌生,代表服务器没有找到资源,我们要特别要注意404的情况不要在我们提供的网页资源上,客户端发送一个请求但是服务器却返回一个无用的结果,时间浪费掉了。
更糟糕的是我们网页中需要加载一个外部脚本,结果返回一个404,不仅阻塞了其他脚本下载,下载回来的内容(404)客户端还会将其当成Javascript去解析。
使用GET Ajax请求
浏览器在实现XMLHttpRequest POST的时候分成两步,先发header,然后发送数据。而GET却可以用一个TCP报文完成请求。另外GET从语义上来讲是去服务器取数据,而POST则是向服务器发送数据,所以我们使用Ajax请求数据的时候尽量通过GET来完成。
避免空的图片src
空的图片src仍然会使浏览器发送请求到服务器,这样完全是浪费时间,而且浪费服务器的资源。尤其是你的网站每天被很多人访问的时候,这种空请求造成的伤害不容忽略。
浏览器如此实现也是根据RFC 3986 - Uniform Resource Identifiers标准,空的src被定义为当前页面。
所以注意我们的网页中是否存在这样的代码
<!--straight HTML-->
<img src="">
//JavaScript
var img = new Image();
img.src = "";
不要在HTML中缩放图片
不要通过图片缩放来适应页面,如果你需要小图片,就直接使用小图片吧。
智能的事件处理
这里说智能的事件处理需要开发者对事件处理有更深入的了解,通过不同的方式尽量少去触发事件,如果必要就尽早的去处理事件。
比如一个div中10个按钮都需要事件句柄,那么我们可以将事件放在div上,在事件冒泡过程中捕获该事件然后判断事件来源。
4.网络与服务器
使用CDN加速
- 其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络,CDN系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。
- 实时性不太好是CDN的致命缺陷。随着对CDN需求的逐渐升温,这一缺陷将得到改进,使来自于远程服务器的网络内容网页与复本服务器或缓存器中的网页保持同步。解决方法是在网络内容发生变化时将新的网络内容从服务器端直接传送到缓存器,或者当对网络内容的访问增加时将数据源服务器的网络内容尽可能实时地复制到缓存服务器。
添加Expires 或Cache-Control报文头
这条规则分为两个方面,
- 对于静态内容添加Expires,将静态内容设为永不过期,或者很长时间以后。
- 对于动态内容应用合适的Cache-Control,让浏览器根据条件来发送请求。
Gzip压缩传输文件
Gzip通常可以减少70%网页内容的大小,包括脚本、样式表、图片等文件。Gzip比deflate更高效,主流服务器都有相应的压缩支持模块。
- 值得注意的是pdf文件可以从需要被压缩的类型中剔除,因为pdf文件本身已经压缩,gzip对其效果不大,而且会浪费CPU。
配置ETags
虽然标题叫配置ETags,但是这里你要根据具体情况进行一些判断。首先Etag简单来说是通过一个文件版本标识使得服务器可以轻松判断该请求的内容是否有所更新,如果没有就回复304 (not modified),从而避免下载整个文件。
- 但是Etags的版本信息即使主流服务器未能很好地支持跨服务器的判断,比如你从一个服务器集群中一台得到Etags,然后发送到了另一台那么校验很有可能会失败。
- 条件请求If-Modified-Since和If-None-Match,都是用来进行缓存再验证。ETag的问题是服务器构造ETag时,尽管两个文件完全一样,但如果处于不同的服务器的话还是会有 不同的ETag,增加了HTTP进行请求下载的次数,这对于后台是服务器集群的网站性能损伤很大。
尽早flush输出
网页后台程序中我们知道有个方法叫Response.Flush(),一般我们调用它都是在程序末尾,但注意这个方法可以被调用多次。目的是可以将现有的缓存中的回复内容先发给客户端,让客户端“有活干”。
那在什么时候调用这个方法比较好呢?一般情况下我们可以在对于需要加载比较多外部脚本或者样式表时可以提前调用一次,客户端收到了关于脚本或其他外部资源的链接可以并行的先发请求去下载,服务器接下来把后续的处理结果发给客户端。
猜你喜欢
- 2024-11-13 「直击面试」- 搞定计算机网络,这些问题还没有我答不出来的
- 2024-11-13 HTTP面试题 高校毕业生就业难 面试题
- 2024-11-13 HTTP的起源与发展 http的具体内容是什么
- 2024-11-13 Python最常见的170道面试题全解析答案(四)
- 2024-11-13 前端项目中 浏览器缓存的更新不及时问题及解决方法
- 2024-11-13 你还没弄懂浏览器的缓存机制吗? 介绍一下浏览器缓存
- 2024-11-13 如何使用缓存提高系统性能? 提高缓存速度
- 2024-11-13 网络相关面试题 网络相关面试问题
- 2024-11-13 为什么你做的H5开屏那么慢?H5首屏秒开方案探讨
- 2024-11-13 一文搞懂浏览器缓存机制 浏览器缓存概念
- 标签列表
-
- content-disposition (47)
- nth-child (56)
- math.pow (44)
- 原型和原型链 (63)
- canvas mdn (36)
- css @media (49)
- promise mdn (39)
- readasdataurl (52)
- if-modified-since (49)
- css ::after (50)
- border-image-slice (40)
- flex mdn (37)
- .join (41)
- function.apply (60)
- input type number (64)
- weakmap (62)
- js arguments (45)
- js delete方法 (61)
- blob type (44)
- math.max.apply (51)
- js (44)
- firefox 3 (47)
- cssbox-sizing (52)
- js删除 (49)
- js for continue (56)
- 最新留言
-