🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 1. 性能比你想象的重要 ```JS 随着前端功能越来越复杂,我们所依赖的资源和库越来越多,页面在浏览器中的加载越来越慢,性能问题随之而来, 性能衡量的指标? 有什么办法是优化性能? 怎么样对性能监控? ``` ## 2. 为什么要关注性能? ```JS 性能 ==》 影响用户体验 ==》 影响网站收益 指标:搜索量、收入、流量、下载量 性能 收益 Google延迟400ms 搜索量下降0.59% Bing延迟2s 收入下降4.3%. Yahoo延迟400ms 流量下降5-9% Mozilla页面打开减少2.2s 下载量提升15.4% ``` ## 3. window.performance window.performance高精度测量网站性能; 可获取网络连接、dus、加载等性能数据. ## 4. [资料] performance 详解 ### performance 详解 ```JS 为了更加精确地测量和提高网页和Web应用程序的性能,W3C 和各浏览器厂商共同制定了 Web Performance API。 我们可以通过该接口查看用户访问网站各项性能数据,如连接建立时间、dns时间等信息,为更好地增强网页性能提供了前所未有的支持。 ``` ### 浏览器内存相关 performance.memory ```JS performance.memory 可获取浏览器的内存情况,这个属性并不是标准的performance 属性,只在 chrome浏览器中。具体有以下值: usedJSHeapSize 表示所有被使用的 js 堆栈内存 totalJSHeapSize 表示当前 js 堆栈内存总大小 jsHeapSizeLimit 表示内存大小限制 其中 usedJSHeapSize 不能大于 totalJSHeapSize,如果大于则可能出现了内存泄漏的情况。 ``` ### 网页导航相关 performance.navigation ```JS performance.navigation 对象存储了两个属性,它们表示触发页面加载的原因。 这些原因可能是页面重定向、前进后退按钮或者普通的 URL 加载。两个属性如下: performance.navigation.type 该属性的值为一个整数值,表示网页的加载来源,共以下4种情况。 ``` 数值 | 含义 | 相应的常量 ---- | ---- | ---- 0 | 通过点击链接、地址栏输入、表单提交、脚本操作等方式加载。 | TYPE_NAVIGATENEXT 1 | 通过刷新操作或者 location.reload() 方法 | TYPE_RELOAD 2 |通过历史遍历操作加载 | TYPE_BACK_FORWARD 255 | 其他来源的加载 | TYPE_UNDEFINED ```JS performance.navigation.redirectCount 该属性表示到达当前页面,经过重定向的次数。 ``` ### 时间相关 performance.timing performance.timing 对象包含了各种浏览器性能相关的信息如网站建立连接、DNS查询、DOM 解析等各项数据, 使我们能够更为全面精确地了解网页性能的详细情况。 ![](https://raw.githubusercontent.com/lz109896/Web-datum/26225a54652ca39c2ad27c426ebae233fba8c7d6/performance%20%E8%AF%A6%E8%A7%A3%201.png) 以下是相关的属性: * navigationStart:当前浏览器窗口的前一个网页关闭,发生unload事件时的时间。如果没有上一个页面, 这个值会和 fetchStart 相同。通常我们也理解为准备加载新页面的起始时间。 * redirectStart:到当前页面的重定向开始的时间。当重定向的页面来自同一个域时这个属性才会有值,否则值为0。 * redirectEnd:到当前页面的重定向结束的时间。当重定向的页面来自同一个域时这个属性才会有值,否则值为0。 * fetchStart:准备使用HTTP请求(fetch)页面的时间。 * domainLookupStart:域名查询开始的时间。 * domainLookupEnd:域名查询结束的时间。 * connectStart:返回HTTP请求开始向服务器发送的时间,如果使用持久连接(persistent connection), 则返回值等同于 fetchStart 的值。 * (secureConnectionStart):可选特性。如果页面是HTTPS协议,则返回开始SSL握手的那个时间。 如果当前网页不要求安全连接,则返回0。 * connectEnd:返回浏览器与服务器之间的连接建立的时间。如果建立的是持久连接,则返回值等同于 fetchStart 属性的值。 连接建立指的是所有握手和认证过程全部结束。 * requestStart:返回浏览器向服务器发出HTTP请求时(或开始读取本地缓存时)的时间。 * responseStart:返回浏览器从服务器收到(或从本地缓存读取)第一个字节时的时间。 * responseEnd:返回浏览器从服务器收到(或从本地缓存读取)最后一个字节时的时间。 * unloadEventStart:返回同一个域名前一个网页的 unload 事件触发时的时间。否则返回值为0。 * unloadEventEnd:返回同一个域名前一个网页的 unload 事件触发时的时间。否则返回值为0。 * domLoading:返回当前网页 DOM 结构开始解析时(即Document.readyState属性变为 loading、 相应的readystatechange事件触发时)的时间 * domInteractive:返回当前网页DOM结构结束解析、开始加载内嵌资源时(即Document.readyState属性变为 interactive 、 相应的readystatechange事件触发时)的时间。 * domContentLoadedEventStart:返回当解析器发送 DOMContentLoaded 事件的开始时间 * domContentLoadedEventEnd:返回当文档的 DOMContentLoaded 事件的结束时间。 * domComplete:返回当前文档解析完成,即Document.readyState 变为 complete 且相对应的readystatechange 被触发时的时间。 * loadEventStart:返回该文档下,load 事件被发送时的时间。如果这个事件还未被发送,它的值将会是0。 * loadEventEnd:返回当 load 事件结束,即加载事件完成时的时间。如果这个事件还未被发送,或者尚未完成,它的值将会是0。 ### 计算相关节点 我们可以通过上面的属性计算出许多网页的信息。 ### 页面经历了多长时间 ```JS 如下面代码表示距离浏览器开始加载网页到现在的时间间隔。 var timing = performance.timing; var duration = Date.now() - timing.navigationStart; ``` ### 网页加载整个过程的(onload)耗时 ```JS 如下面代码表示网页加载整个过程的耗时。 var timing = performance.timing; var pageLoadTime = timing.loadEventEnd - timing.navigationStart; ``` ### DNS 域名解析的耗时 ```JS 如下面代码表示 DNS 域名解析的耗时。 var timing = performance.timing; var dns = timing.domainLookupEnd - timing.domainLookupStart; ``` ### tcp 连接的耗时 ```JS 如下面代码表示 DNS 域名解析的耗时。 var timing = performance.timing; var tcp = timing.connectEnd - timing.connectStart; ``` ### TTFB 获取首字节的耗时 ```JS 如下面代码表示 TTFB(time to frist byte ) 获取首字节的耗时。 var timing = performance.timing; var ttfb = timing.responseStart - timing.navigationStart; ``` ### 返回时间 performance.now() ```JS performance.now 方法将会返回当前网页自从performance.timing.navigationStart 到当前时间之间的微秒数(毫秒的千分之一)。 performance.now() 返回的时间近似于 Date.now()。但前者的时间精度是后者的 1000 倍。 ``` ### 资源加载相关 performance.getEntries() ```JS 浏览器获取网页时,会对网页中每一个资源文件(js、css、图片等)发出一个HTTP请求。performance.getEntries会统计这些 请求并且返回相应的时间信息。 如下所说,返回的是第二个HTTP请求的加载情况: ``` ![](https://raw.githubusercontent.com/lz109896/Web-datum/26225a54652ca39c2ad27c426ebae233fba8c7d6/performance%20%E8%AF%A6%E8%A7%A3%202.png) 更多阅读 Window.performance - MDN :https://developer.mozilla.org/zh-CN/docs/Web/API/Window/performance Performance APIß :http://javascript.ruanyifeng.com/bom/performance.html#toc4 ## 5. 性能衡量指标 ```JS 如果你无法对一件事进行衡量,那么就无法改善它 打开一个页面的时候==》 开始请求:加载页面的起始时间点,performance.timing.navigationStart 获取首字节:接收到第一个字节数据的时刻,performance.timing.responseStart 页面开始展示:用户屏幕刚开始显示内容的时刻,也称为:白屏时间 首屏内容加载完成:比如一个移动端的页面内,不滚动屏幕,能看到的内容加载完成的时间点,也叫作:首屏时间 最后到达加载完成 主要的性能衡量指标:获取首字节、页面开始展示、首屏内容加载完成 ``` ## 6. [资料] Date 类型,你得知道这些 ### Date 类型 ```JS 在实际应用中,我们常常需要用到日期或者时间等,而在 JS 中,我们通常使用 Date 类型来表示日期。 由于 JS 中的 Date 类型是在早期 Java 中的 java.util.Date 类基础上构建的,所以 JS 的 Date 类型使用的是 自 UTC 1970年1月1日0时0分0秒(世界标准时间)起的毫秒数。比如2017年8月7号16时37分26秒, 用毫秒数表示就是 1502095046000。当然,我们实际使用中不需要手动去计算这些毫秒数,但是要理解这个数字的含义。 ``` ### 日期对象 ```JS 通常我们调用 new Date() 获取当前时间,函数返回的是日期对象,这个对象有很多方法可以获取日期的信息。 // 当前时间 var now = new Date(); // Tue Aug 08 2017 15:41:26 GMT+0800 (CST) 除此之外,我们还可以传入参数使用,如: var today = new Date(1453094034000); // by timestamp(accurate to the millimeter) var birthday = new Date('December 17, 1995 03:24:00'); var birthday = new Date('1995-12-17T03:24:00'); var birthday = new Date(1995, 11, 17); var birthday = new Date(1995, 11, 17, 3, 24, 0); 其参数规则如下: // value 代表自1970年1月1日00:00:00 (世界标准时间) 起经过的毫秒数 new Date(value); // 表示日期的字符串值 new Date(dateString); // year 代表年份的整数值,为了避免2000年问题最好指定4位数的年份; 如使用 1998, 而不要用 98 // month 代表月份的整数值从0(1月)到11(12月) // day 代表一个月中的第几天的整数值,从1开始 // hour 代表一天中的小时数的整数值 (24小时制),minute 分钟数,second 秒数,millisecond 毫秒数 new Date(year, month[, day[, hour[, minutes[, seconds[, milliseconds]]]]]); 注:由于日期对象的方法实在有点多,这里就抽取几个常用的说明下,其余的可参考我们下面的参考资料文章。 ``` ### 静态方法 ### now 方法 ```JS es5 中添加了 Date.now() 方法,返回表示调用这个方法时的日期和时间的毫秒数。我们经常用此方法来测试代码的运行时间, 这样就可以根据运行时间判断其性能了,如: // 记录开始时间 var start = Date.now(); // 这里运行一段代码 doSomething(); // 记录结束时间 var stop = Date.now(); // 得到代码运行时间 var timeUse = start - stop; 但是对于不支持 Date.now() 方法的浏览器(如 IE8-),我们还可以使用+操作符把 Date 对象转换成字符串, 也可以达到同样的目的,如下: // 记录开始时间 var start = +new Date(); // 这里运行一段代码 doSomething(); // 记录结束时间 var stop = +new Date(); // 得到代码运行时间 var timeUse = start - stop; ``` ### 实例方法 #### Getter ```JS getFullYear():根据本地时间返回指定日期对象的年份(四位数年份时返回四位数字) getMonth():根据本地时间返回指定日期对象的月份(0-11) getDate():根据本地时间返回指定日期对象的月份中的第几天(1-31) getDay():根据本地时间返回指定日期对象的星期中的第几天(0-6) getHours():根据本地时间返回指定日期对象的小时(0-23) getMinutes():根据本地时间返回指定日期对象的分钟(0-59) getSeconds():根据本地时间返回指定日期对象的秒数(0-59) getMilliseconds():根据本地时间返回指定日期对象的微秒(0-999) getTime():返回从1970-1-1 00:00:00 UTC(协调世界时)到该日期经过的毫秒数, 对于1970-1-1 00:00:00 UTC之前的时间返回负值。 下面我们以一个简单的格式化时间来说明下上面方法的一些使用: // 将时间格式化为:YYYY-MM-DD HH:mm:ss // 小于或等于9的数字前面添加0 function addZero(num) { return num > 9 ? num : '0' + num; } // 格式化时间,可传入一个时间或使用当前时间 function dateFormat(date) { var date = date ? new Date(date) : new Date(); var str = date.getFullYear() + '-' + addZero(date.getMonth() + 1) + '-' + addZero(date.getDate()) + ' ' + addZero(date.getHours()) + ':' + addZero(date.getMinutes()) + ':' + addZero(date.getSeconds()); return str; } dateFormat(); // 2017-08-07 17:44:51 dateFormat(1502095046000); // 2017-08-07 16:37:26 dateFormat('December 3, 1995 03:19:05'); // 1995-12-03 03:19:05 当然对于格式化时间这么常用的功能,已经有Moment.js库来帮我们处理了。 Setter setFullYear():根据本地时间为指定日期对象设置完整年份(四位数年份是四个数字) setMonth():根据本地时间为指定日期对象设置月份 setDate():根据本地时间为指定的日期对象设置月份中的第几天 setHours():根据本地时间为指定日期对象设置小时数 setMinutes():根据本地时间为指定日期对象设置分钟数 setSeconds():根据本地时间为指定日期对象设置秒数 setMilliseconds():根据本地时间为指定日期对象设置毫秒数 setTime():通过指定从 1970-1-1 00:00:00 UTC 开始经过的毫秒数来设置日期对象的时间, 对于早于 1970-1-1 00:00:00 UTC的时间可使用负值。 对于该系列的方法,我们经常用于倒计时,如下: // 2017 年 IMWebconf 大会开始时间为: 2017-09-16 09:30:00 // 计算大会时间的倒计时 var nowTime = Date.now(); // 1502189810994,这个时间会变动 var confDate = new Date(2017, 8, 16, 9, 30, 0), confTime = confDate.getTime(); // 1505525400000 var diffTime = parseInt((confTime - nowTime) / 1000); if(diffTime > 0) { var days = parseInt(diffTime / (60 * 60 * 24)); // 得到剩余天数 var hours = parseInt((diffTime % (60 * 60 * 24)) / (60 * 60)); // 得到剩余小时 var minutes = parseInt(((diffTime % (60 * 60 * 24)) % (60 * 60)) / 60); // 得到剩余分钟 var seconds = ((diffTime % (60 * 60 * 24)) % (60 * 60)) % 60; // 得到剩余秒 // 距离大会还剩38天14:33:9,依赖于 nowTime 为 1502189810994 的计算 console.log('距离大会还剩' + days + '天' + hours + ':' + minutes + ':' + seconds); } else { console.log('大会已经圆满结束,敬请期待下一次大会!') } 同样对于倒计时,也有很多库可用:分享12个效果精美的 JavaScript 倒计时脚本 ``` ### 参考资料 Date | MDN :https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date Date对象 :http://javascript.ruanyifeng.com/stdlib/date.html ## 7. 白屏时间 ![](https://raw.githubusercontent.com/lz109896/Web-datum/26225a54652ca39c2ad27c426ebae233fba8c7d6/%E7%99%BD%E5%B1%8F%E6%97%B6%E9%97%B4%201.png) ![](https://raw.githubusercontent.com/lz109896/Web-datum/26225a54652ca39c2ad27c426ebae233fba8c7d6/%E7%99%BD%E5%B1%8F%E6%97%B6%E9%97%B4%202.png) ![](https://raw.githubusercontent.com/lz109896/Web-datum/26225a54652ca39c2ad27c426ebae233fba8c7d6/%E7%99%BD%E5%B1%8F%E6%97%B6%E9%97%B4%203.png) ## 8. 首屏时间 (abovethefold) ```JS 首屏时间:比如一个移动端的页面内容,用户看到第一屏,及不滚动屏幕,屏幕窗口能看到的内容完整加载完成的时间点。 首屏时间 = 首屏加载完成的时间点 - 页面开始请求的时间点 首屏时间的计算比较复杂,以下只是简单方法之一,不同的网页场景有不同的计算方法 ``` ![](https://raw.githubusercontent.com/lz109896/Web-datum/26225a54652ca39c2ad27c426ebae233fba8c7d6/%E9%A6%96%E5%B1%8F%E6%97%B6%E9%97%B4%201.png) ![](https://raw.githubusercontent.com/lz109896/Web-datum/26225a54652ca39c2ad27c426ebae233fba8c7d6/%E9%A6%96%E5%B1%8F%E6%97%B6%E9%97%B4%202.png) ## 9. [资料] 业务中如何计算白屏和首屏时间 ### 业务中如何计算白屏和首屏时间 ```JS 白屏时间和首屏时间是我们衡量网站加载性能的两个重要指标。在开发中,我们需要根据业务页面的具体情况, 相应地统计页面白屏时间和首屏时间。对于白屏时间和首屏时间,计算的原理是不变的,但计算的的方式可能 会根据页面情况有所改变,因此大家需要具体问题具体分析。 ``` ### 白屏时间 ```JS 白屏时间指的是浏览器开始显示内容的时间。因此我们只需要知道是浏览器开始显示内容的时间点, 即页面白屏结束时间点即可获取到页面的白屏时间。 通过浏览器工作原理,我们可以知道:https://www.html5rocks.com/zh/tutorials/internals/howbrowserswork/#Painting ``` ![](https://raw.githubusercontent.com/lz109896/Web-datum/26225a54652ca39c2ad27c426ebae233fba8c7d6/%E4%B8%9A%E5%8A%A1%E4%B8%AD%E5%A6%82%E4%BD%95%E8%AE%A1%E7%AE%97%E7%99%BD%E5%B1%8F%E5%92%8C%E9%A6%96%E5%B1%8F%E6%97%B6%E9%97%B4%200.png) * 浏览器在加载页面的刚开始,页面是处于空白的状态,只有当页面发生绘制操作时会开始显示内容。 * 浏览器加载页面是一个渐进的过程。为达到更好的用户体验,呈现引擎会力求尽快将内容显示在屏幕上。它不必等到整个 HTML 文档解析完毕之后,就会开始构建呈现树和设置布局。在不断接收页面内容的同时,呈现引擎会将部分内容解析并显示出来。 * 非可视化的 DOM 元素不会显示到窗口中,例如 <head>,这就意味着浏览器在绘制之前,至少需要先解析完head元素中的内容。 ### 计算白屏时间 ```JS 因此,我们通常认为浏览器开始渲染 <body> 标签或者解析完 <head> 标签的时刻就是页面白屏结束的时间点。 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>白屏</title> <script type="text/javascript"> // 不兼容performance.timing 的浏览器,如IE8 window.pageStartTime = Date.now(); </script> <!-- 页面 CSS 资源 --> <link rel="stylesheet" href="common.css"> <link rel="stylesheet" href="page.css"> <script type="text/javascript"> // 白屏时间结束点 window.firstPaint = Date.now(); </script> </head> <body> <!-- 页面内容 --> </body> </html> 因此白屏时间则可以这样计算出有以下两种情况: ``` ### 可使用 Performance API 时 ```JS 白屏时间 = firstPaint - performance.timing.navigationStart; ``` ##### 不可使用 Performance API 时 ```JS 白屏时间 = firstPaint - pageStartTime; ``` ### 首屏时间 ```JS 首屏时间是指用户打开网站开始,到浏览器首屏内容渲染完成的时间。对于用户体验来说,首屏时间是用户对一个网站的重要体验因素。 通常一个网站,如果首屏时间在5秒以内是比较优秀的,10秒以内是可以接受的,10秒以上就不可容忍了。超过10秒的首屏时间用户会 选择刷新页面或立刻离开。 ``` ![](https://raw.githubusercontent.com/lz109896/Web-datum/26225a54652ca39c2ad27c426ebae233fba8c7d6/%E4%B8%9A%E5%8A%A1%E4%B8%AD%E5%A6%82%E4%BD%95%E8%AE%A1%E7%AE%97%E7%99%BD%E5%B1%8F%E5%92%8C%E9%A6%96%E5%B1%8F%E6%97%B6%E9%97%B4%201.png) ### 计算首屏时间 ```JS 明白了首屏时间的概念后,我们计算首屏时间则更加清晰了。现实中,不同业务的首屏内容并不是一样的。因此计算首屏时间, 需要根据业务页面情况,相应地选择计算首屏时间的方法。 通常计算首屏的方法有 ``` * 首屏模块标签标记法 * 统计首屏内加载最慢的图片的时间 * 自定义首屏内容计算法 #### 1、首屏模块标签标记法 ```JS 首屏模块标签标记法,通常适用于首屏内容不需要通过拉取数据才能生存以及页面不考虑图片等资源加载的情况。我们会在 HTML 文档 中对应首屏内容的标签结束位置,使用内联的 JavaScript 代码记录当前时间戳。如下所示: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首屏</title> <script type="text/javascript"> window.pageStartTime = Date.now(); </script> <link rel="stylesheet" href="common.css"> <link rel="stylesheet" href="page.css"> </head> <body> <!-- 首屏可见模块1 --> <div class="module-1"></div> <!-- 首屏可见模块2 --> <div class="module-2"></div> <script type="text/javascript"> window.firstScreen = Date.now(); </script> <!-- 首屏不可见模块3 --> <div class="module-3"></div> <!-- 首屏不可见模块4 --> <div class="module-4"></div> </body> </html> 此时首屏时间等于 firstScreen - performance.timing.navigationStart; 事实上首屏模块标签标记法 在业务中的情况比较少,大多数页面都需要通过接口拉取数据才能完整展示, 因此我们会使用 JavaScript 脚本来判断首屏页面内容加载情况。 ``` #### 2、统计首屏内图片完成加载的时间 ```JS 通常我们首屏内容加载最慢的就是图片资源,因此我们会把首屏内加载最慢的图片的时间当做首屏的时间。 由于浏览器对每个页面的 TCP 连接数有限制,使得并不是所有图片都能立刻开始下载和显示。因此我们在 DOM树 构建完成后将会 去遍历首屏内的所有图片标签,并且监听所有图片标签 onload 事件,最终遍历图片标签的加载时间的最大值,并用这个最大值减去 navigationStart 即可获得近似的首屏时间。 此时首屏时间等于 加载最慢的图片的时间点 - performance.timing.navigationStart; ``` #### 3、自定义模块内容计算法 由于统计首屏内图片完成加载的时间比较复杂。因此我们在业务中通常会通过自定义模块内容,来简化计算首屏时间。如下面的做法: * 忽略图片等资源加载情况,只考虑页面主要 DOM * 只考虑首屏的主要模块,而不是严格意义首屏线以上的所有内容 ### 总结 ```JS 对于首屏时间和白屏时间,业界并没有一个统一的计算标准。大家不能通过死记硬背来实现首屏时间和白屏时间的统计,而应该根据首屏时间 和白屏时间的具体原理,切合自身业务情况来制定统计的方法。统计首屏时间和白屏时间是为了让我们能够更明白我们业务页面的情况, 而不是为了统计而去统计。 ``` ### 更多阅读 浏览器的工作原理:https://www.html5rocks.com/zh/tutorials/internals/howbrowserswork/#Painting ## 10. 使用谷歌自带 network 分析页面 ```JS 页面加载慢,优化页面之前要考虑瓶颈在哪里? 图片?还是样式的加载?还是脚本上的加载慢? 点击开发者工具,打开network 分析页面从上到下: 工具栏 筛选栏 抓取的文件 概览图显示资源加载时间线,如果发现多条时间线垂直重叠,这个部分多个资源并行加载 默认按请求顺序排序单击单个文件,会有很多信息(请求内容,) 鼠标移动到时间线,更为详细的请求情况 蓝色字表示,页面文档完全加载兵解析完毕的时间,红色字表示,所有资源加载完成的时间 摄影机图标:清空缓存并硬性重新加载,会显示白屏时间,首屏时间 ``` ![](https://raw.githubusercontent.com/lz109896/Web-datum/26225a54652ca39c2ad27c426ebae233fba8c7d6/%E4%BD%BF%E7%94%A8%20network%20%E5%88%86%E6%9E%90%E9%A1%B5%E9%9D%A2%201.png) ```JS 使用到 NetWork 来分析页面的加载情况。通过 NetWork 我们可以获取到许多信息 页面请求总数为 53 个,从底部的请求总结区域可以看到 页面白屏时间为 529 ms,从顶部的页面快照区域可以看到 页面 DOM 树构建完成时间为 691 ms,当DOM 树构建完成时会触发 DOMContentLoaded 事件, 我们可从底部的请求总结区域看到触发的时间 页面加载完毕时间为 934 ms,当页面加载完成时会触发 Load 事件,我们可从底部的请求总结区域看到触发的时间 ``` ## 11. 优化手段 ```JS 浏览器发送请求页面内容到服务器,然后服务器返回页面内容到浏览器 1.减少请求文件数,一次性从服务器返回数据 2.减少资源体积,把不必要的东西丢弃,服务器返回数据的速度就会更快 3.提高网络传输,替换请求的方法,从而更快的传输 ``` ## 12. 减少请求数 ```JS 1.小图片合并雪碧图或者使用 iconfont 2.JS、CSS 文件合并 3. ..... ``` ![](https://raw.githubusercontent.com/lz109896/Web-datum/26225a54652ca39c2ad27c426ebae233fba8c7d6/%E5%87%8F%E5%B0%91%E8%AF%B7%E6%B1%82%E6%95%B0%201.png) ## 13. 减少资源体积 ```JS 1.使用精简代码 2.压缩CSS、JS、图片 :可以使用在线工具或工具包:clean-css,UglifyJS,imagemin 3.开启 Gzip :压缩技术方案,当开启后,将输出到用户浏览器的数据进行压缩的处理,减少通过网络传输的数据量来提高浏览的速度 ``` ![](https://raw.githubusercontent.com/lz109896/Web-datum/26225a54652ca39c2ad27c426ebae233fba8c7d6/%E5%87%8F%E5%B0%91%E8%B5%84%E6%BA%90%E4%BD%93%E7%A7%AF%201.png) ## 14. 提高网络传输 ```JS CDN(内容分发网络) 是将源站内容分发至最接近用户的节点,使用户可就近取得所需内容,提高用户访问的响应速度和成功率。 解决因分布、带宽、服务器性能带来的访问延迟问题,适用于站点加速、点播、直播等场景。 合并请求 的主要目的是减少浏览器对服务器发起的请求数,从而减少在发起请求过程中花费的时间。 Gzip 是一种压缩技术,可以将资源在服务端进行压缩,然后发送给浏览器后再进行解压,这种方式会降低传输大小,提高网页加载性能。 通过工具移除代码中不必要的字符 如所有的注释和空白字符,可以减少代码资源文件体积,提高资源加载速度。 1.使用浏览器缓存 : 节约网络资源加载,使用户更快速浏览页面,会把用户最近请求过的页面的一些文件和资源进行缓存, 当用户再次访问时,会从浏览器缓存中直接取出这些文件和资源,最终使用户更快速获取到页面的内容 ``` ![](https://raw.githubusercontent.com/lz109896/Web-datum/26225a54652ca39c2ad27c426ebae233fba8c7d6/%E6%8F%90%E9%AB%98%E7%BD%91%E7%BB%9C%E4%BC%A0%E8%BE%93%201.png) ``` 2.使用 CDN : Content Delivery Network :内容分发网络 使用户就近的取得所需的内容,解决网络拥挤的状况,提高用户访问网站的响应速度 ``` ![](https://raw.githubusercontent.com/lz109896/Web-datum/26225a54652ca39c2ad27c426ebae233fba8c7d6/%E6%8F%90%E9%AB%98%E7%BD%91%E7%BB%9C%E4%BC%A0%E8%BE%93%202.png) ![](https://raw.githubusercontent.com/lz109896/Web-datum/26225a54652ca39c2ad27c426ebae233fba8c7d6/%E6%8F%90%E9%AB%98%E7%BD%91%E7%BB%9C%E4%BC%A0%E8%BE%93%203.png) ## 15. [资料] 对于 CDN 的疑问,都在这 ### CDN 相关 ```JS 为了提高网页应用的加载速度,我们会使用到浏览器缓存,然而浏览器缓存只能提升二次访问的速度。对于加速首次访问的速度, 我们最常见的手段则是使用 CDN 加速。 CDN 的全称是 Content Delivery Network,即内容分发网络。通过将静态资源缓存到离用户很近的相同网络运营商的 CDN 节点上, 使用户可以就近取得所需的内容,解决网络拥塞状况,提高用户访问网站的响应速度。 事实上,在一些较大型的公司来说,通常是由公司的运维开发人员来负责部署 CDN 服务的, 前端人员只需要了解使用 CDN 服务的大致流程即可。 ``` ### 1 选择 CDN 供应商 ```JS 事实上,现在还有许多的 CDN 服务厂家,我们需要根据需求的情况去选择相应的厂商。现阶段 CDN 云服务商的竞争已经由 技术 逐渐取代价格成为 CDN 厂商在客户谈判时最关键因素,技术更高的 CDN 服务能够降低带宽成本、提升用户体验。 如今 CDN 各大厂商都会提供十分详尽的接入文档,使我们接入的开发成本变得更低。这里列举国内比较出名的 CDN 厂商: 又拍云 腾讯云 七牛云 阿里云 ``` ### 2 连接 CDN 服务 ```JS 通常购买了 CDN 服务后,该 CDN 服务会提供相应的接口让我们去上传和部署我们的资源。这部分的工作通常是由我们运维人员 去负责的,对于一些小公司可能则需要前端或者后台人员去负责连接 CDN 服务,使业务能够部署静态资源到相应的服务器上。 ``` ### 3 前端工程静态资源部署 使用 CDN 服务,对前端工程产生了一定的影响,我们需要对静态资源的部署做两项改变: #### 3.1 将静态资源部署到不同网络线路的服务器中 由于用户的网络线路有很多种,如网通、电信、移动等,为了让不同地区的用户会访问到离自己最近的相同网络线路上的 CDN 节点。因此我们需要将我们的资源部署到不同的网络线路的服务器中,然后通过这些服务器同步到不同线路的 CDN 节点上。 #### 3.2 加载静态资源时需使用与页面不同的域名 使用不同的域名来加载 CDN 服务的静态资源,一方面便于接入为 CDN 时设置 DNS 的智能解析。另一方面当静态资源和主页面使用不 同的域名,在加载静态资源时 HTTP 请求并不会带上主域页面的 Cookie 等数据,减少了请求时的数据传输量,进一步加快网络访问。 #### 3.3 资源路径的修正 通常情况下,我们的资源都是在本地,比如有个 JS 文件,我们在 HTML 里面按照相对目录引用它: <script src="js/script.js"></script> 使用了 CDN 的话,资源都部署到了 CDN 服务器上去咯,这个时候我们必须用绝对路径来引用: <script src="http://xxx.xxx.xxx/js/script.js"></script> 所有啊,必须有个修正资源路径的过程,而这个过程当然不能手动,通常都是在工程化里面解决这个问题。 ### 总结 如今 CDN 服务基本上已经成为现代大型网页应用的标配。这项技术是一种十分常用的网络性能优化手段。在未来的前端开发中,我们会经常与 CDN 打交道。因此如果能够清楚了解了 CDN 服务的相关原理和概念,将会让我们在将来的开发中能够更加得心应手。 ### 更多阅读 盘点国内网站常用的一些CDN公共库加速服务