有关图片上传的民用摘要

<input
type=”file”>——在vue中我们可以给input控件一个ref属性,然后大家得以采纳this.$refs.(前边那东西的属性值,其实就是一个锚点)去得到这一个控件,然后去调用那一个控件的files属性,大家就可以得到控件里面获得到的多寡了。当然,他是一个目标,这么些数量也是储存在对象的一个特性当中,具体什么的自己去打印看看。然后那么些目的有个name属性,顾名思义,就是您收获的公文名,还有一个性能是length,咱们可以运用那些特性去看清控件到底里面有没有数量。倘使你协调去做过,你会发现有上边一种情景。

前端性能优化

  • 削减HTTP请求数量
    • CSS Sprites
    • 内联图片(图片base64)
    • 最大化合并JS、CSS模块
    • 使用浏览器缓存
  • 减小HTTP请求大小
    • 压缩HTTP响应包(Accept-Encoding: gzip, deflate)
    • 压缩HTML、CSS、JS模块
  • DOM方面
    • 离线操作DOM
    • 行使innerHTML举办大气的DHTML操作
    • 选取事件代理
    • 缓存布局音讯
    • 移除页面上不存在的事件处理程序
  • JavaScript语言本身的优化
    • 行使一些变量代替全部变量,裁减职能域链遍历标识符的时光
    • 压缩对象成员及数组项的追寻次数
    • 幸免选拔with语句和eval函数
  • ajax优化
    • get或者post请求
    • multipart XHR
    • ajax缓存
  • 其它方面的习性优化
    • 动用CDN加载静态资源
    • CSS样式放在头顶
    • JS脚本放在底部
    • 幸免选拔CSS表达式
    • 外联JS、CSS
    • 减少DNS查找
    • 避免URL重定向

——场景场景场景——–

转载请申明出处: 前端性能优化

1.首先次用控件获取一张图片,大家看看控件获取到了数据

减去HTTP请求数量

2.次之次点开同样的控件,不过…..

CSS Sprites

将八个图片合并成一张图,只像图片发送三回呼吁的技能。此时可以透过background-position据悉职分一定到不相同的图形。尽管联合之后的一张图纸包涵附加的空域区域,会令人觉得比单个图片合并起来的图片要大。实际上,合并后的图纸会比分其他图形的总数要小,因为一来将反复呼吁合并成了一回,二来下落了图片自身的付出(颜色表,格式信息等等)。

举个例证,假使有亟待请求五个25k的图形,那么直接呼吁100k的图样会比发送四回呼吁要快一些。因为频仍http请求会生出性能用度和图表自身的花费。

3.本身啥也不选

内联图片

经过行使data:
URL格局可以在Web页面包涵图表但无需任何附加的HTTP请求。data:
URL中的URL是通过base64编码的。格式如下

<img src="data:image/gif;base64....." alt="home">

鉴于应用内联图片(图片base64)是内联在HTML中的,由此在超越页面时不会被缓存。一般情形下,不要将网站的Logo做图片base64的拍卖,因为编码过的Logo会导致页面变大。可将图片作为背景,放在CSS样式表中,此时CSS可被浏览器缓存

.home {
 background-image: url(data:image/gif;base64.....)
}

4.控件里面原来的数额被清空了,貌似向来没来过这一个满世界

最大化JS、CSS的合并

设想到HTTP请求会带动极度的特性开销,因而下载单个100kb的文件比下载4个25kb的文件更快。最大化合并JS、CSS将会改正性能。

那明显不太协调,于是动动脑子,你可以那样做

利用浏览器缓存

削减展现页面时所必不可少的HTTP请求的多寡是加速用户体验的极品情势。能够因此最大化浏览器缓存组件的能力来完毕。

    data () {
       return {
          fileName: null
      }
   }

如何是缓存

即使组件(HTML、CSS、JavsScript、图片资源等)被缓存到浏览器中,在下次重新加载的时候有可能从组件中取得缓存,而不是向服务器发送HTTP请求。缩减HTTP请求有利于前端性能优化


浏览器如何缓存

浏览器在下载组件(HTML、CSS、JavsScript、图片资源等),会将他们缓存到浏览器中。假如某个组件确实更新了,然而仍然在缓存中。那时候可以给组件添加版本号的办法(md5)幸免读取缓存。

if (this.$refs.imgFile.files.length !== 0) {
   this.fileImg = this.$refs.imgFile.files
} else {
   this.$refs.imgFile.files = this.fileImg
   return
 }
浏览器再度下载组件时,怎么样确认是缓存的组件

下面是vue的写法,因为近期用vue写项目,所以偷个懒。用原生的话做的形式相同

1.Expires头

可以因而服务端配置,将某个组件的过期时间设置的长一些。比如,集团Logo不会平时转移等。浏览器在下载组件时,会将其缓存。在后续页面的查看中,假设在指定时间内,评释组件是未过期的,则可以直接读取缓存,而不用走HTTP请求。假诺在指定时间外,则申明组件是逾期的,此时并不会立马发起一个HTTP请求,而是发起一个标准化GET请求。

好了,现在您会发现,不会再有地点那种非友好的用户体验了,当然那一个并重,有人说那是个fetch,我觉着它很多时候是个bug…..

2.条件GET请求

如果缓存的组件过期了(或者用户reload,refresh了页面),浏览器在重用它前边务必先检查它是否依旧有效。那称为一个准绳GET请求。那个请求是浏览器必须发起的。假若响应底部的Last-Modified(最终修改时间,服务器传回的值)与请求尾部的If-Modified-Since(最新修改时间)得值极度,则会回来304响应(Not-Modified),即直接从浏览器中读取缓存,而不是走HTTP请求。

我们跟着唠

3.Etag(实体标签)

Etag其实和标准化GET请求很像,也是因而检测浏览器缓存中的组件与原来服务器上的机件是还是不是匹配。假使响应尾部的Etag与请求尾部的If-None-Match的值相互协作,则会回去304响应。

Etag存在的片段题材:

  1. 倘若唯有一台服务器,使用Etag没有怎么问题。借使有多台服务器,从不相同服务器下载相同的组件再次回到的Etag会分裂,即便内容一致,也不会从缓存中读取,而是发起HTTP请求。
  2. Etag下跌了代办缓存的作用。
  3. If-None-Match比If-Modified-Since拥有更高的预先级。即使条件GET请求的响应尾部和请求尾部的八个值相同,在富有多台服务器的场所下,不是从缓存中读取,而是如故会倡导HTTP请求。

有三种办法得以缓解那个题材

  1. 在服务端配置Etag。
  2. 在服务端移除Etag。移除Etag可以削减响应和持续HTTP请求头的轻重缓急。Last-Modified可以提供完全等价的新闻

接下去,大家会变卦一个图纸对象,你能够用createElement的点子仍然用new
Image的点子,那个不纠结

削减HTTP请求大小

请看那里

1.组件(HTML, CSS, JavaScript)压缩处理
let imgRender = new FileReader()//用来把文件读入内存,并且读取文件中的数据。FileReader接口提供了一个异步API,使用该API可以在浏览器主线程中异步访问文件系统,读取文件中的数据
imgRender.readAsDataURL(file)//将文件读取为DataURL
2.安插请求底部信息:Accept-encoding: gzip, deflate。此时服务器再次来到的响应尾部中会包罗Content-encoding: gzip的音讯,表明http响应包被缩减。

 具体文献链接:http://blog.csdn.net/zk437092645/article/details/8745647

DOM方面

如若你问如何是dataurl,我提议您自己先去找文章看看啊,我那有一篇不错的稿子链接你可以看看:http://www.webhek.com/post/data-url.html

离线DOM操作

比方急需给页面上某个元素进行某种DOM操作时(如伸张某个子节点或者扩张某段文字或者去除某个节点),倘若直接对在页面上拓展更新,此时浏览器必要重新总计页面上有所DOM节点的尺码,进行重排和重绘。现场开展的DOM更新更加多,所费用的时刻就越长。重排是指某个DOM节点暴发地方变动时(删除、移动、CSS盒模型等),重新绘制渲染树的进度。重绘是指将发出位置变动的DOM节点重新绘制到页面上的历程。

var list = document.getElementById("myList"),
   item,
   i;
for (i=0; i < 10; i++) {
 item = document.createElement("li");
 list.appendChild(item);
 item.appendChild(document.createTextNode("Item " + i));
}

上述因素进行了20次现场更新,有10次是将li插入到list元素中,其它10次文本节点。那里就暴发了20次DOM的重排和重绘。此时可以运用以下方法,
来压缩DOM元素的重拍和重绘。

一是采用文档碎片(),一是将li元素最后才插入到页面上

一:使用文档碎片(推荐)
var list = document.getElementById("myList"),
   item,
   i,
   frag = document.createDocumentFragment();  // 文档碎片
for (i=0; i < 10; i++) {
 item = document.createElement("li");
 frag.appendChild(item);
 item.appendChild(document.createTextNode("Item " + i));
}
document.body.appendChild(frag)

二:循环结束时插入li
var list = document.getElementById("myList"),
   item,
   i;
for (i=0; i < 10; i++) {
 item = document.createElement("li");
 item.appendChild(document.createTextNode("Item " + i));
}
list.appendChild(item);

然后,我们使用canvas,先安装大小,于是可以那样做

采用innerHTML方法

有两种在页面上开创 DOM 节点的法子:使用诸如 createElement()和
appendChild()之类的DOM
方法,以及利用innerHTML。对于小的DOM更改而言,二种艺术功能都大致。但是,对于大的
DOM 更改,使用 innerHTML 要比拔取正规 DOM 方法创造同样的 DOM
结构快得多。当把innerHTML设置为某个值时,后台会成立一个HTML解析器,然后拔取其中的DOM
调用来成立 DOM
结构,而非基于JavaScript的DOM调用。由于内部方法是编译好的而非解释施行的,所以进行快得多。

var ul = document.querySelector('ul')
var html = ''
for (var i = 0; i < 10; i++) {
 html += '<li>'+ i +'</li>'
 // 避免在for循环中使用innerHTML, 因为在循环中使用innerHTML会导致现场更新!
}
ul.innerHTML = html   // 循环结束时插入到ul元素中

那段代码构建了一个 HTML 字符串,然后将其指定到
list.innerHTML,便创制了特需的DOM结构。固然字符串连接上两次三番有点性能损失,但那种方式依然要比举办多少个DOM操作更快。

let canvas = document.createElement('canvas')
canvas.width = targetWidth
canvas.height = targetHeight
缓存布局消息

当在实际上利用中要求获得页面上某个DOM节点的布局音信时,如offset dimension,
client
dimension或者是样式等,浏览器为了重回最新值,会刷新整个DOM树去取得。最好的做法是缓存布局信息,收缩布局音讯的得到次数。获取之后将其缓存到有的变量中,然后再操作此部分变量。

如,必要将某个DOM节点沿对角线移动,两遍活动一个像素,从100100
移动到500
500。

如果这样做,对于性能优化来说是低效的。
div.style.left = 1 + div.clientLeft + 'px'
div.style.top = 1 + div.clientTop + 'px'
if (div.style.clientLeft >= 500 && div.style.clientTop >= 500) {
  // 停止累加..
}

下面使用局部变量缓存布局信息,对于性能优化来说是高效的。
let left = div.clientLeft, right = div.clientTop
div.style.left = 1 + left + 'px'
div.style.top = 1 + right+ 'px'
if (div.style.clientLeft >= 500 && div.style.clientTop >= 500) {
  // 停止累加..
}

自己记得canvas对象默许的宽度是300,中度是150,你自己可以打印看看

事件代理

在javascript中,在页面渲染时添加到页面上的事件处理程序数量一贯关系到页面的完好运行性能。最直白的震慑是页面的事件处理程序更多,访问DOM节点的次数也就越来越多。其余函数是目标,会占据内存。内存中的目的更多,性能就越差。

事件代理就是焚林而猎’过多的事件处理程序’的。事件代理基于事件冒泡机制。由此,可以将一如既往事件类型的轩然大波都绑定到document对象上,根据事件目标的target属性下的id,
class
或者name属性,判断要求给哪个DOM节点绑定事件处理程序。那种事件代理体制在页面渲染时将做客很多次DOM节点减弱到了三遍,因为那时大家只需访问document对象。如下完毕

document.addEventListener('click', function (e) {
 switch (e.target.id) {
   case 'new':
     console.log('new')
     break
   case 'name':
     console.log('name')
     break
   case 'sex':
     console.log('sex')
     break
 }
}, false)

使用事件代理有以下优点:

  1. 可以在页面生名周期的其他时间点上添加添加事件处理程序(无需等待DOMContentLoaded和Load事件)。换句话说,只要某个须要加上事件处理程序的要素存在页面上,就足以绑定相应的轩然大波。
  2. DOM节点访问次数收缩。
  3. 事件处理程序时函数,而函数是目的。对象会占有内存。事件处理程序减弱了,所占有的内存空间就少了,就可见晋级全体性能。

下一场我们做上面一件事

移除事件处理程序

借使有那样一个须求:页面上有一个按钮,在点击时索要替换成某个文本。要是一直互换该按钮,由于该按钮的事件处理程序已经存在内存中了,此时移除按钮并没有将事件处理程序一同移除,页面仍旧有所对该按钮事件处理程序的引用。一旦那种景色出现很多次,那么原来增加到元素中的事件处理程序会占用内存。在事变代理中也谈过,函数是目标,内存中的对象越多,性能有越差。除了文本替换外,还可能出现在移除(removeChild)、替换(replaceChild)带有事件处理程序的DOM节点。

而正确的做法是,在移除该按钮的同时,移除事件处理程序。

<div class="content">
 <button class='btn'>点击</button>
</div>
var btn = document.querySelector('.btn')
btn.addEventListener('click', function func(e) {
 btn.removeEventListener('click', func, false) // 在替换前,移除该按钮的事件处理程序
 document.querySelector('.content').innerHTML = '替换button按钮拉!'
}, false)
let canvasCtx = canvas.getContext('2d')

JavaScript的优化

为了省去某些同学去翻资料,我表达下啥意思===>指定了你想要在画布上制图的体系。当前唯一的官方值是
“2d”,它指定了二维绘图,并且导致那些点子重临一个条件目标,该对象导出一个二维绘图
API(那是网上的表明,我只是个搬运工)。

使用部分变量代替全局变量,收缩在功能域链上找寻标识符的大运

在JavaScript中,效用域分为函数功效域和词法作用域。当大家执行了某个函数时,会创制一个推行环境。即使在推行环境中想寻找某个变量,会经历以下行为:

率先从眼前词法功效域早先查找,若是找到了这些变量,那么就终止搜索,重返该变量;如果找不到,那么就会寻找外层的词法功效域,平素发展冒泡;即使照旧没有在全局意义域下如故没有检索到该变量,浏览器就会报RefferceError类型的错误,此错误表示与功效域相关。最终,此函数的履行环境被销毁。

从性质方面考虑,假使将某个变量放在全局意义域下,那么读写到该变量的时间会比部分变量多很多。变量在成效域中的地点越深,访问所需时间就越长。由于全局变量总是(document,
window对象)处在成效域链的最末尾,因而访问速度是最慢的。
图片 1
图片 2

举个例证吗。比如大家操作DOM元素时,必不可免的会选拔到document对象。那些目标是window对象下的一个性能,也总算一个全局变量吧。由此,当我们操作DOM时,可以将其缓存,作为局地变量存在,那么就防止了职能域链搜索全局变量的历程。

let func = () => {
  let doc = document  // document作为局部变量存在
  let body = doc.body  // body作为局部变量存在
  let p = doc.createElement('p')
  let text = doc.createTextNode('document和body作为局部变量存在')
  body.appendChld(p)
}

接下来大家用这么些目的的fillRect方法,可以设定这么些条件目的的横坐标、纵坐标、宽度、高度。然后是最后一步,用drawImage方法向画布上制图图像、画布或视频。如同下边

减掉对象成员数组项的检索次数

这一点首要反映在循环体上。以for循环为例,缓存数高管度,而不是在历次循环中赢得。

假设有有一个arr数组,长度为50000
// 低效的, 每次都要获取数组长度
for (var i = 0; i < arr.length; i++) {
  // do something...
}
// for循环性能优化:缓存数组长度
for ( var i = 0, len = arr.length; i < len; i++) {
  // do something
}
canvasCtx.fillStyle = '#fff'
canvasCtx.fillRect(0, 0, canvas.width, canvas.height)// set the default background color of png  to white
canvasCtx.drawImage(图片对象files[0], 0, 0, targetWidth, targetHeight)

Ajax方面的优化

OK,那面的步调很简短有木有。总的来说,大家照旧用canvasCtx环境目的做一些’动作’

get或者post请求

这里可以扯一下get和post请求的分歧。

对此get请求来说,紧要用于获取(查询)数据。get请求的参数须求以query
string的办法添加在URL后边的。当我们必要从服务器获取或者查询某数码时,都应当使用get请求。优点在于gei请求比post请求要快,同时get请求可以被浏览器缓存。缺点在于get请求的参数大于2048个字符时,领先的字符会被截取,此时亟需post请求。

对于post请求来说,首要用于保存(增添值、修改值、删除值)数据。post请求的参数是作为请求的重点提交到服务器。优点在于没有字节的限制。缺点是力不从心被浏览器缓存。

get和post请求有一个共同点:就算在呼吁时,get请求将参数带在url前面,post请求将参数作为请求的基本点提交。可是请求参数都是以name1=value1&name2=value2
的法门发送到服务器的。

let data ['name1=value1', 'name2=value2']
let xhr = new window.XMLHttpRequest()
xhr.addEventListener('readystatechange', () => {
  if (xhr.readyState === 4) {
    if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
      console.log(xhr.responseText)
    }
  }
}, false)
let getPram = '?' + data.join('&')
let postPram = data.join('&')
// open方法:
xhr.open('get', 'url' + getPram, true)
// post方法, 作为请求的主体提交
// xhr.send(postPram)

之所以,扯了那么多。要留心的是,get请求用于查询(获取)数据,post请求用于保存(增删改)数据。

接下去的动作就很简单了,我们看上面

跨域JSONP

由于同源政策的界定,ajax只可以在同域名、同协议、同端口的事态下才足以访问。也就是说,跨域是格外的。不过足以选取JSONP的情势绕过同源政策。

JSONP完毕的法则:动态创设script标签。通过src属性添加须求拜访的地址,将回来的多少作为参数封装在回调函数中

let script = document.createElement('script')
script.src = 'url...'
script.id = 'script'
document.head.appendChild(script)

script.addEventListener('load', e => {
  if (this.readyState === 'complete') {
    let data = e
    // do something...
  }
}, false)

JSONP的优点:

  1. 跨域请求。
  2. 鉴于再次来到的参数是JavaScript代码,而不是当做字符串须求进一步处理。所以速度快

JSONP的缺点:

  1. 只好以get请求发送。
  2. 没辙为不当、失利事件设置事件处理程序。
  3. 不能设请求头。
let picBase64 = canvas.toDataURL('image/jpeg', 1)//canvas里面是二进制二进制2222222222222
let fd = new FormData()
let blob = ImgUtil.base64ToBlob(picBase64)//不是blob,你传不了,这里不多解释这个,网上解释很多----你可以用atob()这个方法来,但是这个方法有挺大的缺陷,不过兼容性很好了,而且
你要对它进行切割切割,因为前面会有些emmit----》九九归一,来个new Blob()统统搞定
fd.append('pic', blob)
multipart XHR

临时未选取过,占位占位、等应用过了再立异:)

 OK,到此处,你可以拿上您的接口,把那东西甩过去了。当然,并不是装有意况都是那样子,你得和您的后端小伙伴协定好,到底要怎样的多寡。

ajax缓存

先占位。近日正在开发一个袖珍类jQuery库。首要目标有:熟谙面向对象编程思想,熟知DOM操作。到时候开发完ajax模块再重回填坑。

其余方面的习性优化

将样式表放在顶部

CSS样式表可以置身四个地点,一是文档尾部,一是文档尾部。地方的两样会带动不相同的体会。

当样式表放在文档尾部时,分化浏览器会出现不相同的机能

IE浏览器在新窗口打开、刷新页面时,浏览器会阻塞内容的渐渐展现,取而代之的是白屏一段时间,等到CSS样式下载完结之后再将内容和样式渲染到页面上;在点击链接、书签栏、reload时,浏览器会先将内容日益呈现,等到CSS样式加载已毕之后再一次渲染DOM树,此时会暴发无样式内容的闪亮问题

火狐浏览器不管以怎么样办法打开浏览器都会将内容日益显现,然后等到css样式加载达成之后再另行渲染DOM树,暴发无样式内容的闪光的题材。

当样式表放在文档顶部时,就算浏览器需求先加载CSS样式,速度可能比位居底部的慢些,不过由于可以使页面内容日益展现,所以对用户来时仍旧快的。因为有内容展现了而不是白屏,暴发无样式内容的闪亮,用户体验也会自己些。毕竟,有内容比白屏要好广大吧…

将样式放在文档顶部有二种方法。当使用link标签将样式放在head时,浏览器会使内容日益显示,可是会暴发无样式内容的闪光问题;当使用@import规则,由于会时有暴发模块(图片、样式、脚本)下载时的无序性,可能会油可是生白屏的气象。其余,在style标签下可以使用三个import规则,不过必须放置在其他规则此前。link和@import引入样式也存在性能问题,推荐引入样式时都利用link标签。

参照小说:link标签和@import规则的性质不相同

文章中,不难易行的说就是都是用link标签或者都是用@import规则加载CSS样式时会并行下载而混用link标签和@import规则导致体制不可以并行下载,而是逐个下载。由于@import规则会招致模块下载的无序性问题,所以照旧引进全体接纳link标签引入css样式

将脚本放在尾部

将脚本放在文档顶部会招致如下问题:

  1. 脚本会阻塞其后组件的交互下载和执行
  2. 脚本会阻塞其后页面的渐渐显示

HTTP1.1规定,提议每个浏览器从服务器并行下载五个零部件。那也意味,增添服务器的多少,并行下载的多少也会扩大。即使有两台服务器,那么并行下载组件的数据为4。
图片 3
图片 4
除去将脚本放在底部可以缓解这么些以上八个问题,script标签`的async和defer属性也足以缓解那四个问题。

asnyc属性(异步脚本)表示脚本可以即时下载,下载达成后自动执行,但不应妨碍页面中的其他操作。比如下载其余模块(图片、样式、脚本)。由于是异步的,所以剧本下载没有先后顺序,没有种种的本子就要保障每个脚本不会相互依赖。只对表面脚本文件有效。异步脚本一定会在页面load事件前执行,但可能会在DOMContentLoaded事件触发前后执行。由于async属性可以异步加载脚本,所以可以置身页面的其他地点。

defer属性(延迟脚本)表示脚本能够即时下载,不过会延迟到文档完全被解析和出示之后再举行。在DOMContentLoaded事件之后,load事件从前实施。由于defer属性可以延缓脚本的执行,由此得以放在页面的任何职责。

在没有asnyc属性和defer属性的script标签时,由于js是单线程的案由,所以不得不下载完第二个script才能下载第三个,才到第多个,第七个……

防止选取CSS表明式

以此理应很少人用吧…毕竟网上对css表达式介绍的少之又少…反正我是没用过的

外联javascript、css

外联javascript、css文件相对于内联有以下优点。外联的法子得以经过script标签或者link标签引入,也可以透过动态格局创造script标签和link标签(动态脚本、动态样式),此时通过动态格局开创的台本和体裁不会阻塞页面其他零件的下载和表现。

通用函数
let loadScript = (url, cb) => {
  let script = document.createElement('script')
  支持readystatechange事件的浏览器有IE、Firefox4+和Opera,谷歌不支持该事件。存在兼容性问题。
  if (script.readyState) {
    script.addEventListener('readystatechange', function change () {
      if (script.readyState === 'loaded' || script.readyState === 'complete') {
        // 移除readystatechange,避免触发两次
        script.removeEventListener('readystatechange', change, false)
        cb()
      }
    }, false)
  } else {
    script.addEventListener('load', () => {
      cb()
    }, false)
  }
  script.src = url
  document.body.appendChild(script)
}

// 依次解析和执行a.js、b.js、c.js。
loadScript('./a.js', () => {
  alert('a done')
  loadScript('./b.js', () => {
    alert('b done')
    loadScript('./c.js', () => {
      alert('c done')
    })
  })
})
  1. 能够被浏览器缓存。
  2. 作为组件复用。
减少DNS查找

DNS的功能是将域名解析为IP地址。平常意况下,浏览器查找一个给定主机名的IP地址须求开销20-120ms。在DNS服务器查找完结在此之前,浏览器无法从服务器那里下载任何东西。裁减DNS查找的章程如下。

  1. 收缩服务器数量。裁减服务器数量意味着并行下载组件的数码也会压缩,不过此时会削减DNS查找的时日。应根据现实事务场景做取舍。
  2. 浏览器缓存DNS记录。可以通过服务器配置DNS缓存的年华。
  3. 配置Keep-alive。由于客户端服务器连接是从头到尾的,因而无需DNS查找。
避免url重定向

先占位。