面试的时候常常会被问到的有关于前端性能优化这一块的问题,扯扯我的的理解html
80%的最终用户响应时间花在前端程序上,而其大部分时间则花在各类页面元素, 如图像、 样式表、 脚本和 Flash 等,的下载上。 减小页面元素将会减小 HTTP 请求 次数。这是快速显示页面的关键所在。 一种减小页面元素个数的方法是简化页面设计。 可是否存在其余方式,能作到既有丰富内容,又能得到快速响应时间呢?如下是这样一些技术: 前端
Image maps 组合多个图片到一张图片中。总文件大小变化不大,但减小了 HTTP 请求次数从而加快了页面显示速度。该方式只适合图片连续的状况;同时坐标的定义是烦人又容易出错的工做。web
CSS Sprites 是更好的方法。它能够组合页面中的图片到单个文件中,并使用 CSS 的 background-image 和 background-position 属性来实现所需的部分图片。 Inline images 使用 data: URL scheme 来在页面中内嵌图片。这将增大 HTML 文件的大小。组合 inline images 到你的(缓存)样式表是既能较少 HTTP 请求, 又能避免加大 HTML 文件大小的方法。 面试
Combined files 经过组合多个脚本文件到单一文件来减小 HTTP 请求次数。样式 表也可采用相似方法处理。 这个方法虽然简单,但没有获得大规模的使用。 10大 美国网站每页平均有 7 个脚本文件和 2 个样式表。当页面之间脚本和样式表变化 很大时,该方式将遇到很大的挑战,但若是作到的话,将能加快响应时间。 express
用户离 web server 的远近对响应时间也有很大影响。从用户角度看,把内容部 署到多个地理位置分散的服务器上将有效提升页面装载速度。 可是该从哪里开始 呢?
做为实现内容地理分布的第一步,不要试图重构 web 应用以适应分布架构。 改变 架构将致使多个周期性任务,如同步 session 状态,在多个 server 之间复制数 据库交易。 这样缩短用户与内容距离的尝试可能被应用架构改版所延迟,或阻止。 咱们还记得 80-90%的最终用户响应时间花在下载页面中的各类元素上,如图像 文件、 样式表、 脚本和 Flash 等。 与其花在重构系统这个困难的任务上,还不如先 分布静态内容。 这不只能大大减小响应时间,并且因为 CDN 的存在,分布静态内 容很是容易实现。 CDN 是地理上分布的 web server 的集合,用于更高效地发布内容。 一般基于网络 远近来选择给具体用户服务的 web server。 一些大型网站拥有本身的 CDN,可是使用如 Akamai Technologies, Mirror Image Internet, 或 Limelight Networks 等 CDN 服务提供商的服务将是划算的。 在 Yahoo!把静态内容分布到 CDN 减小了用户影响时间 20%或更多。切换到 CDN 的 代码修改工做是很容易的,但能达到提升网站的速度。 windows
DNS 用于映射主机名和 IP 地址,通常一次解析须要 20~120 毫秒。 为达到更高的 性能,DNS 解析一般被多级别地缓存,如由 ISP 或局域网维护的 caching server,本地机器操做系统的缓存(如 windows 上的 DNS Client Service), 浏览器。 的缺省 DNS 缓存时间为 30 分钟,Firefox 的缺省缓冲时间是 1 分钟。 IE 减小主机名可减小 DNS 查询的次数,但可能形成并行下载数的减小。避免 DNS 查 询可减小响应时间,而减小并行下载数可能增长响应时间。 一个可行的折中是把 内容分布到至少 2 个,最多 4 个不一样的主机名上。 浏览器
咱们发现把样式表移到 HEAD 部分能够提升界面加载速度,所以这使得页面元素 能够顺序显示。 在不少浏览器下,如 IE,把样式表放在 document 的底部的问题在于它禁止了网 页内容的顺序显示。 浏览器阻止显示以避免重画页面元素,那用户只能看到空白页 了。Firefox 不会阻止显示,但这意味着当样式表下载后,有些页面元素可能需 要重画,这致使闪烁问题。 HTML 规范明确要求样式表被定义在 HEAD 中,所以,为避免空白屏幕或闪烁问题, 最好的办法是遵循 HTML 规范,把样式表放在 HEAD 中。 缓存
与样式文件同样,咱们须要注意脚本文件的位置。 咱们需尽可能把它们放在页面的 底部,这样一方面能顺序显示,另方面可达到最大的并行下载。 浏览器会阻塞显示直到样式表下载完毕,所以咱们须要把样式表放在 HEAD 部分。 而对于脚原本说,脚本后面内容的顺序显示将被阻塞,所以把脚本尽可能放在底 部意味着更多内容能被快速显示。 脚本引发的第二个问题是它阻塞并行下载数量。HTTP/1.1 规范建议浏览器每一个 主机的并行下载数不超过 2 个。 所以若是您把图像文件分布到多台机器的话,您能够达到超过 2 个的并行下载。 可是当脚本文件下载时,浏览器不会启动其余的 并行下载,甚至其余主机的下载也不启动。 在某些状况下,不是很容易就能把脚本移到底部的。如,脚本使用 document.write 方法来插入页面内容。 同时可能还存在域的问题。 不过在不少情 况下,仍是有一些方法的。 一个备选方法是使用延迟脚本(deferred script)。DEFER 属性代表脚本未包 含 document.write,指示浏览器刻继续显示。不幸的是,Firefox 不支持 DEFER 属性。 IE 中,脚本可能被延迟执行,但不必定获得须要的长时间延迟。 在 不过从 另外角度来讲,若是脚本能被延迟执行,那它就能够被放在底部了。 安全
上述不少性能优化法则都基于外部文件进行优化。 如今,咱们必须问一个问题: JavaScript 和 CSS 应该包括在外部文件,仍是在页面文件中? 在现实世界中,使用外部文件会加快页面显示速度,由于外部文件会被浏览器 缓存。若是内置 JavaScript 和 CSS 在页面中虽然会减小 HTTP 请求次数,但增大 了页面的大小。 另一方面,使用外部文件,会被浏览器缓存,则页面大小会减 小,同时又不增长 HTTP 请求次数。 所以,通常来讲,外部文件是更可行的方式。 惟一的例外是内嵌方式对主页更有 效,如 Yahoo!和 My Yahoo!都使用内嵌方式。通常来讲,在一个 session 中,主 页访问此时较少,所以内嵌方式能够取得更快的用户响应时间。 性能优化
重定向功能是经过 301 和 302 这两个 HTTP 状态码完成的,如: HTTP/1.1 301 Moved Permanently Location: http://example.com/newuri Content-Type: text/html 浏览器自动重定向请求到 Location 指定的 URL 上,重定向的主要问题是下降了 用户体验。 一种最耗费资源、常常发生而很容易被忽视的重定向是 URL 的最后缺乏/,如访 问 http://astrology.yahoo.com/astrology 将被重定向到 http://astrology.yahoo.com/astrology/。在 Apache 下,能够经过 Alias,mod_rewrite 或 DirectorySlash 等方式来解决该问题。
一、避免 CSS 表达式
CSS 表达式是功能强大的(同时也是危险的)用于动态设置 CSS 属性的方式。IE, 从版本 5 开始支持 CSS 表达式,如 backgourd-color: expression((new Date()).getHours()%2?”#B8D4FF”:”#F08A00”),即背景色每一个小时切换一 次。 CSS 表达式的问题是其执行次数超过大部分人的指望。 不只页面显示和 resize 时 计算表达式,并且当页面滚屏,甚至当鼠标在页面上移动时都会从新计算表达 式。 一种减小 CSS 表达式执行次数的方法是一次性表达式,即当第一次执行时就以 明确的数值代替表达式。若是必须动态设置的话,可以使用事件处理函数代替。如 果您必须使用 CSS 表达式的话,请记住它们可能被执行上千次,从而影响页面 性能。
二、函数节流
函数节流就是用来节流函数从而必定程度上优化性能的。例如,DOM 操做比起非DOM 交互须要更多的内存和CPU时间。连续尝试进行过多的DOM 相关操做可能会致使浏览器挂起,有时候甚至会崩溃。尤为在IE 中使用onresize 事件处理程序的时候容易发生,当调整浏览器大小的时候,该事件会连续触发。在onresize 事件处理程序内部若是尝试进行DOM 操做,其高频率的更改可能会让浏览器崩溃。又例如,咱们常见的一个搜索的功能,咱们通常是绑定keyup事件,每按下一次键盘就搜索一次。可是咱们的目的主要是每输入一些内容搜索一次而已。为了解决这些问题,就可使用定时器对函数进行节流。
三、减小对 DOM 访问
当DOM树的结构变化时,例如节点的增减、移动等,也会触发重排。浏览器引擎布局的过程,相似于树的前序遍历,是一个从上到下从左到右的过程。 一般在这个过程当中,当前元素不会再影响其前面已经遍历过的元素。因此,若是在body最前面插入一个元素,会致使整个文档的从新渲染。既然没法避免,那就减小访问(width、offsetTop、left。。。能少就少,能够缓存起来的,就缓存)。
四、最小化代码
最小化 JavaScript、CSS、HTML 从代码中删除没必要要的字符,从而下降下载时间。 经常使用的工具备 Gulp 和 Webpack。 混淆是最小化于源码的备选方式。 象最小化同样,它经过删除注释和空格来减小 源码大小,同时它还能够对代码进行混淆处理。 做为混淆的一部分,函数名和变 量名被替换成短的字符串,这使得代码更紧凑,同时也更难读,使得难于被反 向工程。最小化是安全的、直白的过程,而混淆则更复杂,并且容易产生问题。从对大网站的调查来看,经过最小化,文件可减小 21%,而混淆则可减小 25%。 除了最小化外部脚本文件外,内嵌的脚本代码也应该被最小化。 即便脚本根据法 则 4 被压缩后传输,最小化脚本刻减小文件大小 5%或更高。
本文主要借鉴与 雅虎军规 及我的理解