前端性能优化 - 面试总结

前端性能优化总结

页面层面

减少HTTP请求, 合理设置HTTP缓存.

原因:

  • http是无状态的应用层协议, 意味着每次请求都需要建立通信链路, 进行数据传输.
  • 服务器端每个http都需要启动独立的线程去处理.

解决方法:

  • 合并CSS, 合并JavaScript, 合并图片等.将浏览器一次需要的这些文件合并成一个, 那么就只需要一次请求了.
  • 使用缓存.第二次访问服务器返回304, 只有Header没有Body, 可以节省带宽.

使用浏览器缓存.

原因:

  • 一个网站, css, js, logo, 图标等一些静态文件更新的频率较低. 几乎每次请求都需要, 先把这些文件缓存到浏览器中, 可以很好的改善性能.

方法

  • 使用http头中的cache-controlexpiress属性可以设定浏览器缓存.
  • 如果需要更新文件, 更改文件名即可. 即更新js文件, 并不是更新js文件内容, 而是生成一个新的js文件并更新html文件中的引用.
  • 更新静态资源时候应该采用逐量更新, 避免客户端浏览器大量缓存失效, 集中更新, 造成服务器负载骤增, 网络阻塞.

压缩文件

原因

  • html, css, js等文件都能够进行压缩处理, 极大的减少文件大小. 能够减少通信传输的数据量

方法

  • 可以把外部的脚本, 样式进行合并, 多个合并为一个.
  • 文本文件压缩率可以达到80%以上, 极大地节省空间.

CSS Sprites

原因

  • 在CSS中的图片, 能够通过背景图的位置进行控制.

方法

  • 多个css所用到图片, 放到一张上面, 然后通过css进行控制.

Lazy Load Image(图片懒加载)

原因

  • 在页面刚刚加载的时候, 只加载第一屏, 这样的话, 可以保证第一屏的页面第一时间正常显示
  • 并不能加载HTTP请求, 只能在减少第一次发处HTTP请求.

方法

  • 首次加载的时候, 只加载第一屏图片.
  • 后面的图片当监听到用户滚动屏幕的时候再进行加载.

CSS放到顶部, JS放到底部

原因

  • css: 用户在下载完css才会对整个页面进行一个渲染. 如果css没有下载完开始解析body, 可能导致无css状态, 跳转到css状态, 页面变化较大.
  • js: 加载js立即执行, 有可能阻塞整个页面, 造成页面显示慢.

方法

  • css放到顶部先加载.
  • js放到最后页面显示完了再加载.

异步加载

原因:

  • 如果直接直接写个异步: 那么会增加首次加载的负担, 推迟DOMLoaded和window.onload事件触发时机.

方法:

  • 可以在DOMLoaded事件触发时加载.
  • 通过setTimeout方式来灵活控制.

减少cookie传输

原因

  • cookie包含在每次请求和响应中, 太大的cookie回严重影响数据传输
  • 某些静态资源的访问, 如CSS, JS等, 发送cookie没有意义.

方法

  • 数据写入cookie需要谨慎. 尽量减少cookie中传输的数据量.
  • 静态资源使用独立域名访问, 避免静态医院发送cookie, 减少cookie传输次数.

JavaScript代码优化

DOM

  • 在脚本中, document.images, document.forms, getElementsByTagName()返回的都是HTMLCollection类型的集合.
  • 一般情况下我们均用作数组使用, 但这并非一个静态的结果. 每次访问时都会重新执行这个查询从而更新查询结果.
  • 每次访问集合, 包括访问集合的length属性, 访问集合中的某个元素.都会重新进行查询.
  • 当你需要重新遍历HTML Collection的时候, 可以将其转换为数组, 以便提高性能.

with

  • with(obj){}
  • 修改代码块的执行环境, 将参数放到作用域链的最前面. 在代码块中访问非局部变量都是从obj中开始查找, 如果没有再次按作用域链向上查找, 因此with相当于增加了作用域链长度.
  • 每次查找作用域链, 都需要消耗性能.
  • 除非能肯定在代码块中访问obj属性, 否则不要使用with

避免使用eval和Function

  • eval(): 计算传入其中的string的值, 并执行其中的js代码. 只能接受原始字符串作为参数
  • Function(): 函数构造函数
  • 每次作用字符串表示的源代码时, 脚本引擎都需要将源代码转化为可执行的代码. 极大的浪费资源.
  • eval()函数效率特别低. Function不会影响周围代码, 但是速度也是很慢
  • eval()和Function不利于JavaScript压缩工具执行压缩

减少作用域链的查找

  • 在循环中尤其注意作用域链的查找.
  • 如果不断需要查找作用域链, 我们需要在遍历之前用局部变量缓存该变量.

减少闭包使用

代码实现

// 低效
var globalVar = 1; 
function myCallback(info){ 
    for( var i = 100000; i--;){ 
        //每次访问 globalVar 都需要查找到作用域链最顶端,本例中需要访问 100000 次 
        globalVar += i; 
    }
} 
// 高效
var globalVar = 1; 
function myCallback(info){ 
    //局部变量缓存全局变量 
    var localVar = globalVar; 
    for( var i = 100000; i--;){ 
    //访问局部变量是最快的 
    localVar += i; 
    } 
    //本例中只需要访问 2次全局变量
    在函数中只需要将 globalVar中内容的值赋给localVar 中
    globalVar = localVar; 
}

数据访问

  • 在js中数据访问包括对直接量(字符串, 正则表达式), 变量, 对象属性以及数组.
  • 对直接量和局部变量的访问最快.
  • 对象属性和数组的访问开销最大.
  • 建议把需要访问的对象属性放入局部变量.
  • 建议把需要访问数组成员放入局部变量.
  • 尽量减少对对象以及数组的深度访问.

CSS选择符优化

待记录.

  • 注意一点: 浏览器对选择符的解析是从右到左的. 因此最右边越准备越好

服务器方面

CDN加速

  • CDN(content distribute network, 内容分发网络)
  • 本质是一种缓存. 将数据缓存在离用户最近的地方.
  • 使得用户以最快速度获取数据, 即所谓的网络访问第一跳.
  • CDN网站架构

反向代理

  • 传统代理服务器代理浏览器将http请求发送到互联网上.
  • 反向代理服务器代理WEB服务器接受http请求.
  • 反向代理示意图
  • 可通过缓存功能加速web请求.
  • 当用户第一次访问静态内容的时候, 静态内容被缓存在反向代理服务器上, 这样当其他用户访问该静态内容时候, 就可直接从反向服务器返回, 加速请求响应, 减轻负载压力.
  • 事实上动态内容也会缓存在代理服务器上, 加速用户访问速度
  • 动态内容由变化时, 通过内部通知机制通知反向代理缓存失效, 反向代理重新加载最新的动态内容.
  • 反向代理也能实现负载均衡功能, 通过负载均衡构建的应用集群可以提高系统总体处理, 进而改善在高并发情况下的性能.

参考

posted @ 2017-10-18 08:58  张润昊  阅读(757)  评论(0编辑  收藏  举报