续上一篇javascript
内联脚本或者样式能够减小HTTP请求,按理来讲能够提升页面加载的速度。然而在实际状况中,当脚本或者样式是从外部引入的文件,浏览器就有可能缓存它们,从而在之后加载的时候可以直接使用缓存,而HTML文档的大小减少,从而提升加载速度。css
影响因素:html
一、每一个用户产生的页面浏览量越少,内联脚本和样式的论据越强势。譬如一个用户每月只访问你的网站一两次,那么这种状况下内联将会更好。而若是该用户可以产生不少页面浏览量,那么缓存的样式和脚本将会极大减小下载的时间,提交页面加载速度。前端
二、若是你的网站不一样的页面之间使用的组件大体相同,那么使用外部文件能够提升这些组件的重用率。java
加载后下载node
有时候咱们但愿内联样式和脚本,但又能够为接下来的页面提供外部文件。那么咱们能够在页面加载完成止呕动态加载外部组件,以便用户接下来的访问。python
在该页面中,JavaScript和CSS被加载两次(内联和外部)。要使其正常工做,必须处理双重定义。将这些组件放到一个不可见的IFrame中是一个比较好的解决方式。jquery
当咱们在浏览器的地址栏输入网址(譬如: www.linux178.com) ,而后回车,回车这一瞬间到看到页面到底发生了什么呢?linux
域名解析 --> 发起TCP的3次握手 --> 创建TCP链接后发起http请求 --> 服务器响应http请求,浏览器获得html代码 --> 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等) --> 浏览器对页面进行渲染呈现给用户web
域名解析是页面加载的第一步,那么域名是如何解析的呢?以Chrome为例:
1.Chrome浏览器 会首先搜索浏览器自身的DNS缓存(缓存时间比较短,大概只有1分钟,且只能容纳1000条缓存),看自身的缓存中是否有www.linux178.com 对应的条目,并且没有过时,若是有且没有过时则解析到此结束。
注:咱们怎么查看Chrome自身的缓存?可使用 chrome://net-internals/#dns 来进行查看
2.若是浏览器自身的缓存里面没有找到对应的条目,那么Chrome会搜索操做系统自身的DNS缓存,若是找到且没有过时则中止搜索解析到此结束.
注:怎么查看操做系统自身的DNS缓存,以Windows系统为例,能够在命令行下使用 ipconfig /displaydns 来进行查看
3.若是在Windows系统的DNS缓存也没有找到,那么尝试读取hosts文件(位于C:WindowsSystem32driversetc),看看这里面有没有该域名对应的IP地址,若是有则解析成功。
4.若是在hosts文件中也没有找到对应的条目,浏览器就会发起一个DNS的系统调用,就会向本地配置的首选DNS服务器(通常是电信运营商提供的,也可使用像Google提供的DNS服务器)发起域名解析请求(经过的是UDP协议向DNS的53端口发起请求,这个请求是递归的请求,也就是运营商的DNS服务器必须得提供给咱们该域名的IP地址),运营商的DNS服务器首先查找自身的缓存,找到对应的条目,且没有过时,则解析成功。若是没有找到对应的条目,则有运营商的DNS代咱们的浏览器发起迭代DNS解析请求,它首先是会找根域的DNS的IP地址(这个DNS服务器都内置13台根域的DNS的IP地址),找打根域的DNS地址,就会向其发起请求(请问www.linux178.com这个域名的IP地址是多少啊?),根域发现这是一个顶级域com域的一个域名,因而就告诉运营商的DNS我不知道这个域名的IP地址,可是我知道com域的IP地址,你去找它去,因而运营商的DNS就获得了com域的IP地址,又向com域的IP地址发起了请求(请问www.linux178.com这个域名的IP地址是多少?),com域这台服务器告诉运营商的DNS我不知道www.linux178.com这个域名的IP地址,可是我知道linux178.com这个域的DNS地址,你去找它去,因而运营商的DNS又向linux178.com这个域名的DNS地址(这个通常就是由域名注册商提供的,像万网,新网等)发起请求(请问www.linux178.com这个域名的IP地址是多少?),这个时候linux178.com域的DNS服务器一查,诶,果然在我这里,因而就把找到的结果发送给运营商的DNS服务器,这个时候运营商的DNS服务器就拿到了www.linux178.com这个域名对应的IP地址,并返回给Windows系统内核,内核又把结果返回给浏览器,终于浏览器拿到了www.linux178.com对应的IP地址,该进行一步的动做了。
注:通常状况下是不会进行如下步骤的
若是通过以上的4个步骤,尚未解析成功,那么会进行以下步骤:
5.操做系统就会查找NetBIOS name Cache(NetBIOS名称缓存,就存在客户端电脑中的),那这个缓存有什么东西呢?凡是最近一段时间内和我成功通信的计算机的计算机名和Ip地址,就都会存在这个缓存里面。什么状况下该步能解析成功呢?就是该名称正好是几分钟前和我成功通讯过,那么这一步就能够成功解析。
6.若是第5步也没有成功,那会查询WINS 服务器(是NETBIOS名称和IP地址对应的服务器)
7.若是第6步也没有查询成功,那么客户端就要进行广播查找
8.若是第7步也没有成功,那么客户端就读取LMHOSTS文件(和HOSTS文件同一个目录下,写法也同样)
若是第八步尚未解析成功,那么就宣告此次解析失败,那就没法跟目标计算机进行通讯。只要这八步中有一步能够解析成功,那就能够成功和目标计算机进行通讯。
DNS也是开销,一般浏览器查找一个给定域名的IP地址要花费20~120毫秒,在完成域名解析以前,浏览器不能从服务器加载到任何东西。那么如何减小域名解析时间,加快页面加载速度呢?
当客户端DNS缓存(浏览器和操做系统)缓存为空时,DNS查找的数量与要加载的Web页面中惟一主机名的数量相同,包括页面URL、脚本、样式表、图片、Flash对象等的主机名。减小主机名的 数量就能够减小DNS查找的数量。
减小惟一主机名的数量会潜在减小页面中并行下载的数量(HTTP 1.1规范建议从每一个主机名并行下载两个组件,但实际上能够多个),这样减小主机名和并行下载的方案会产生矛盾,须要你们本身权衡。建议将组件放到至少两个但很少于4个主机名下,减小DNS查找的同时也容许高度并行下载。
精简
精简就是从代码中移除没必要要的字符以减小文件大小,下降加载的时间。代码精简的时候会移除没必要要的空白字符(空格,换行、制表符),这样整个文件的大小就变小了。
混淆
混淆是应用在源代码上的另一种方式,它会移除注释和空白符,同时它还会改写代码。在混淆的时候,函数和变量名将会被转换成更短的字符串,这时代码会更加精炼同时难以阅读。一般这样作是为了增长对代码进行反向工程的难度,这也同时提升了性能。
缺点:
混淆自己比较复杂,可能会引入错误。
须要对不能改变的符号作标记,防止JavaScript符号(譬如关键字、保留字)被修改。
混淆会使代码难以阅读,这使得在产品环境中调试问题更加困难。
在以上提到了关于用gzip之类的压缩方式来压缩文件,这边说明一下,就算使用gzip等方式来压缩文件,精简代码依然是有必要的。通常来讲,压缩产生的节省是高于精简的,在生产环境中,精简和压缩同时使用可以最大限度的得到更多的节省。
CSS的精简
CSS的精简带来的节省通常来讲是小于JavaScript精简的,由于CSS中注释和空白相对较少。
除了移除空白、注释以外,CSS能够经过优化来得到更多的节省:
合并相同的类;
移除不使用的类;
使用缩写,譬如
上面.right是正确的的写法,颜色使用缩写,使用0代替0px,合并能够合并的样式。另外,在精简的时候其实样式最后一行的';'也是能够省略的。
来看看精简的例子:
以上分别是jquery-2.0.3的学习版(未精简)和精简版,可见精简文件的大小比源文件小了155k,并且,在精简版中jquery还作了混淆,譬如用e代替window等,从而得到最大的节省。
什么是重定向?
重定向用于将用户从一个URL从新路由到另外一个URL。
经常使用重定向的类型
301:永久重定向,主要用于当网站的域名发生变动以后,告诉搜索引擎域名已经变动了,应该把旧域名的的数据和连接数转移到新域名下,从而不会让网站的排名因域名变动而受到影响。
302:临时重定向,主要实现post请求后告知浏览器转移到新的URL。
304:Not Modified,主要用于当浏览器在其缓存中保留了组件的一个副本,同时组件已通过期了,这是浏览器就会生成一个条件GET请求,若是服务器的组件并无修改过,则会返回304状态码,同时不携带主体,告知浏览器能够重用这个副本,减小响应大小。
重定向如何损伤性能?
当页面发生了重定向,就会延迟整个HTML文档的传输。在HTML文档到达以前,页面中不会呈现任何东西,也没有任何组件会被下载。
来看一个实际例子:对于ASP.NET webform开发来讲,对于新手很容易犯一个错误,就是把页面的链接写成服务器控件后台代码里,例如用一个Button控件,在它的后台click事件中写上:Response.Redirect("");然而这个Button的做用只是转移URL,这是很是低效的作法,由于点击Button后,先发送一个Post请求给服务器,服务器处理Response.Redirect("")后就发送一个302响应给浏览器,浏览器再根据响应的URL发送GET请求。正确的作法应该是在html页面直接使用a标签作连接,这样就避免了多余的post和重定向。
重定向的应用场景
跟踪内部流量
重定向常常用于跟踪用户流量的方向,当拥有一个门户主页的时候,同时想对用户离开主页后的流量进行跟踪,这时可使用重定向。例如: 某网站主页新闻的连接地址http://a.com/r/news,点击该连接将产生301响应,其Location被设置为http://news.a.com。经过分析a.com的web服务器日志能够得知人们离开首页以后的去向。
咱们知道重定向是如何损伤性能的,为了实现更好的效率,可使用Referer日志来跟踪内部流量去向。每一个HTTP请求都有一个Referer表示原始请求页(除了从书签打开或直接键入URL等操做),记录下每一个请求的Referer,就避免了向用户发送重定向,从而改善了响应时间。
跟踪出站流量
有时连接可能将用户带离你的网站,在这种状况下,使用Referer就不太现实了。
一样也可使用重定向来解决跟踪出站流量问题。以百度搜索为例,百度经过将每一个连接包装到一个302重定向来解决跟踪的问题,例如搜索关键字“前端性能优化”,搜索结果中的一个URL为https://www.baidu.com/link?url=pDjwTfa0IAf_FRBNlw1qLDtQ27YBujWp9jPN4q0QSJdNtGtDBK3ja3jyyN2CgxR5aTAywG4SI6V1NypkSyLISWjiFuFQDinhpVn4QE-uLGG&wd=&eqid=9c02bd21001c69170000000556ece297,即便搜索结果并无变,但这个字符串是动态改变的,暂时还不知道这里起到怎样的做用?(我的感受:字符串中包含了待访问的网址,点击以后会产生302重定向,将页面转到目标页面(待修改,求大神们给我指正))
除了重定向外,咱们还能够选择使用信标(beacon)——一个HTTP请求,其URL中包含有跟踪信息。跟踪信息能够从信标Web服务器的访问日记中提取出来,信标一般是一个1px*1px的透明图片,不过204响应更优秀,由于它更小,历来不被缓存,并且毫不会改变浏览器的状态。
在团队开发一个项目时,因为不一样开发者之间均可能会向页面中添加页面或组件,所以可能相同的脚本会被添加屡次。
重复的脚本会形成没必要要的HTTP请求(若是没有缓存该脚本的话),而且执行多余的JavaScript浪费时间,还有可能形成错误。
如何避免重复脚本呢?
造成良好的脚本组织。重复脚本有可能出如今不一样的脚本包含同一段脚本的状况,有些是必要的,但有些却不是必要的,因此须要对脚本进行一个良好的组织。
实现脚本管理器模块。
例如:
先检查是否插入过,若是插入过则返回。若是该脚本依赖其它脚本,则被依赖的脚本也会被插入。最后脚本被传送到页面,getVersion会检查脚本并返回追加了对应版本号的文件名,这样若是脚本的版本变化了,那么之前浏览器缓存的就会失效。
之前浏览器缓存的就会失效。
什么是ETag?
实体标签(EntityTag)是惟一标识了一个组件的一个特定版本的字符串,是web服务器用于确认缓存组件的有效性的一种机制,一般可使用组件的某些属性来构造它。
条件GET请求
若是组件过时了,浏览器在重用它以前必须首先检查它是否有效。浏览器将发送一个条件GET请求到服务器,服务器判断缓存还有效,则发送一个304响应,告诉浏览器能够重用缓存组件。
那么服务器是根据什么判断缓存是否还有效呢?有两种方式:
ETag(实体标签);
最新修改日期;
最新修改日期
原始服务器经过Last-Modified响应头来返回组件的最新修改日期。
举个栗子:
当咱们不带缓存访问www.google.com.hk的时候,咱们须要下载google的logo,这时会发送这样一个HTTP请求:
当须要再次访问相同组件的时候,同时缓存已通过期,浏览器会发送以下条件GET请求:
实体标签
ETag提供了另一种方式,用于检测浏览器缓存中的组件与原始服务器上的组件是否匹配。摘抄自书上的例子:
不带缓存的请求:
再次请求相同组件:
为何要引入ETag?
ETag主要是为了解决Last-Modified没法解决的一些问题:
一些文件也许会周期性的更改,可是他的内容并不改变(仅仅改变的修改时间),这个时候咱们并不但愿客户端认为这个文件被修改了,而从新GET;
某些文件修改很是频繁,好比在秒如下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改没法判断(或者说UNIX记录MTIME只能精确到秒);
某些服务器不能精确的获得文件的最后修改时间。
ETag带来的问题
ETag的问题在于一般使用某些属性来构造它,有些属性对于特定的部署了网站的服务器来讲是惟一的。当使用集群服务器的时候,浏览器从一台服务器上获取了原始组件,以后又向另一台不一样的服务器发起条件GET请求,ETag就会出现不匹配的情况。例如:使用inode-size-timestamp来生成ETag,文件系统使用inode存储文件类型、全部者、组和访问模式等信息,在多台服务器上,就算文件大小、权限、时间戳等都相同,inode也是不一样的。
最佳实践
若是使用Last-Modified不会出现任何问题,能够直接移除ETag,google的搜索首页则没有使用ETag。
肯定要使用ETag,在配置ETag的值的时候,移除可能影响到组件集群服务器验证的属性,例如使用size-timestamp来生成时间戳。
维基百科中这样定义Ajax:
AJAX即“Asynchronous JavaScript and XML”(异步的JavaScript与XML技术),指的是一套综合了多项技术的浏览器端网页开发技术。Ajax的概念由杰西·詹姆士·贾瑞特所提出。
传统的Web应用容许用户端填写表单(form),当提交表单时就向Web服务器发送一个请求。服务器接收并处理传来的表单,而后送回一个新的网页,但这个作法浪费了许多带宽,由于在先后两个页面中的大部分HTML码每每是相同的。因为每次应用的沟通都须要向服务器发送请求,应用的回应时间依赖于服务器的回应时间。这致使了用户界面的回应比本机应用慢得多。
与此不一样,AJAX应用能够仅向服务器发送并取回必须的数据,并在客户端采用JavaScript处理来自服务器的回应。由于在服务器和浏览器之间交换的数据大量减小(大约只有原来的5%)[来源请求],服务器回应更快了。同时,不少的处理工做能够在发出请求的客户端机器上完成,所以Web服务器的负荷也减小了。
相似于DHTML或LAMP,AJAX不是指一种单一的技术,而是有机地利用了一系列相关的技术。虽然其名称包含XML,但实际上数据格式能够由JSON代替,进一步减小数据量,造成所谓的AJAJ。而客户端与服务器也并不须要异步。一些基于AJAX的“派生/合成”式(derivative/composite)的技术也正在出现,如AFLAX。
Ajax的目地是为突破web本质的开始—中止交互方式,向用户显示一个白屏后重绘整个页面不是一种好的用户体验。
异步与即时
Ajax的一个明显的有点就是向用户提供了即时反馈,由于它异步的从后端web服务器请求信息。
用户是否须要等待的关键因素在于Ajax请求是被动的仍是主动的。被动请求是为了未来来使用而预先发起的,主动请求是基于用户当前的操做而发起的
什么样的AJAX请求能够被缓存?
POST的请求,是不能够在客户端缓存的,每次请求都须要发送给服务器进行处理,每次都会返回状态码200。(能够在服务器端对数据进行缓存,以便提升处理速度)
GET的请求,是能够(并且默认)在客户端进行缓存的,除非指定了不一样的地址,不然同一个地址的AJAX请求,不会重复在服务器执行,而是返回304。
Ajax请求使用缓存
在进行Ajax请求的时候,能够选择尽可能使用get方法,这样可使用客户端的缓存,提升请求速度。
做者:MarcoHan
出处:
http://www.cnblogs.com/MarcoHan/p/5295398.html
识别图中二维码,领取python全套视频资料