前端重构总结
前端重构总结
前端重构其实可以分为两个方面:
性能优化
和模块化
。
下面我们先总结一下性能优化方面的东西:
首先列举一下常规的优化手段:
CSS置顶,JS置底
静态资源外联、合并、压缩
图片优化
图片延迟加载
使用CSS Sprite,首屏图片全部合并到一张图上
静态文件上CDN
静态文件设置强缓存
HTML压缩
图片预加载
增强型的手段:
基础库定制(用代码分析代码,自动打包被使用到的方法作为基础库)
页面数据存储优化(从原来的的直接写json形式的script,变为将json隐藏在textarea中,初始化或用到的时候才去提取并进行解析)
首屏CSS检测,将不属于首屏的css代码单独打包并移到首屏之外进行延迟加载
js按需加载
监控和测量
性能优化最重要的工作不是优化而是监控。这个道理很简单,没有监控体系就没办法衡量性能优化的效果,那么你做的任何工作都是盲目的。
我们对性能的监控是从多个维度展开的,包括平均时间、时段分布、浏览器分布、省份、运营商等。便于发现和定位任何一个细节的问题。
而在平均时间这一维度,我们又分为四个级别:
Head时间:head标签加载完成的时间
TTi时间:页面可交互时间(首屏第一次渲染出来的时间)
Dom时间:Dom Ready的时间
Load时间:页面完全加载完成的时间
这样划分的好处是,页面加载每个环节的耗时一目了然:
Head:CSS加载时间
TTI:整体HTML加载和渲染时间
DOM-TTI:js文件网络传输时间和在浏览器进行解析的时间
Load减Dom:js初始化+图片加载的时间
页面加载的瓶颈就在script的下载和解析时间。
那么,优化方案就很明显了:最大限度地减小js文件大小,以减小网络传输时间,提升页面性能。
通过后来的优化工作我们发现:js代码压缩、Gzip后每减小1k,页面加载时间就能减小10ms左右。
按需加载:
这是除了js压缩外,能想到的最有效减小js文件大小的办法了。
图片优化
样式代替图片。支持CSS3的浏览器越来越多,半透明、圆角、阴影、高光、渐变等都可以使用CSS3来实现
选择最合适的图片。jpg,png,gif
使用图片压缩工具
Icon font 缺点是只支持纯色图标。
SVG:对于绝大多数图案、图标等,矢量图更小,且可缩放无需生成多套图。
data url:Base64是网络上最常见的用语传输8Bit字节的编码方式之一,可用以在http环境下传递较长的标示信息。将图片转化为base64编码格式,资源内嵌于CSS或HTML中,不必单独请求。该方式的优点是:
-
减少了http请求
-
避免了图片重新上传,还要清理缓存的问题
缺点:IE6,IE7不支持该类型编码的图片作为背景图,增加了CSS文件的大小,维护成本较高
按照Http协议设置合理的缓存
RWD设计
图片延迟加载
为img标签src设置统一的图片链接,将真实链接地址装在自定义属性中,所以开始时候图片是不会加载的,我们将满足条件的图片的src重置为自定义属性便可实现延迟加载功能
function imgLazyLoad(container){
container=container || $(window);
var imgArr={};
initImg();
lazyLoad();
container.scroll(function(){
lazyLoad();
})
$(window).resize(function(){
initImg();
})
function initImg(){
$('img').each(function(){
var el=$(this);
if(el.attr('lazy-src')&&el.attr('lazy-src')!=''){
var offset=el.offset();
if(!imgArr[offset.top]){
imgArr[offset.top]=[];
}
imgArr[offset.top].push(el);
}
})
}
function lazyLoad(){
var height=container.height();
var scrollHeight=container.scrollTop();
for(var k in imgArr){
if(parseInt(k)<scrollHeight+height){
var _imgs=imgArr[k];
for(var i=0;lens=_img.length;i++){
var temImg=_img[i];
if(tmpImg.attr('lazy-src')&&temImg.attr('lazy-src')!=''){
tmpImg.attr('src',tmpImg.attr('lazy-src'));
temImg.removeAttr('lazy-src');
}
}
delete imgArr[k];
}
}
}
}
imgLazyLoad($('#con'));
上述代码没有考虑到页面空闲的情况,当页面空闲的情况就不需要延迟加载了。
进行一下改进:
function imgLazyLoad(container) {
var imgLazyLoadTimer = null;
var resetImglazy = null;
container = container || $(window); //需要时jquery对象
var imgArr = {};
initImg();
lazyLoad();
imgLazyLoadTimer = setTimeout(autoLoad, 5000);
container.scroll(function () {
lazyLoad();
});
$(window).resize(function () {
initImg();
});
$(document).mousemove(function () {
if (imgLazyLoadTimer) clearTimeout(imgLazyLoadTimer);
if (resetImglazy) clearTimeout(resetImglazy);
resetImglazy = setTimeout(function () {
autoLoad();
}, 5000);
});
function initImg() {
$('img').each(function () {
var el = $(this);
if (el.attr('lazy-src') && el.attr('lazy-src') != '') {
var offset = el.offset();
if (!imgArr[offset.top]) {
imgArr[offset.top] = [];
}
imgArr[offset.top].push(el);
}
});
}
function lazyLoad() {
var height = container.height();
var srollHeight = container.scrollTop();
for (var k in imgArr) {
if (parseInt(k) < srollHeight + height) {
var _imgs = imgArr[k];
for (var i = 0, len = _imgs.length; i < len; i++) {
var tmpImg = _imgs[i];
if (tmpImg.attr('lazy-src') && tmpImg.attr('lazy-src') != '') {
tmpImg.attr('src', tmpImg.attr('lazy-src'));
tmpImg.removeAttr('lazy-src');
}
}
delete imgArr[k];
}
}
} //lazyLoad
function autoLoad() {
var _key = null;
for (var k in imgArr) {
if (!_key) {
_key = k;
break;
}
}
if (!_key) return false;
var _imgs = imgArr[_key];
for (var i = 0, len = _imgs.length; i < len; i++) {
var tmpImg = _imgs[i];
if (tmpImg.attr('lazy-src') && tmpImg.attr('lazy-src') != '') {
tmpImg.attr('src', tmpImg.attr('lazy-src'));
tmpImg.removeAttr('lazy-src');
}
}
delete imgArr[_key];
if (imgLazyLoadTimer) {
clearTimeout(imgLazyLoadTimer);
}
imgLazyLoadTimer = setTimeout(autoLoad, 1000);
}
} //imgLazyLoad
imgLazyLoad($('#con'));
另外一种方式:
原理,当页面载入的时候,使用jquery来循环遍历每一个img,判断每一个图片是否在当前可是区域内,需要的数据:
浏览器可是区域的高度
图片相对于文档的偏移量
当图片相对于文档的偏移量小于浏览器可视区域的高度的时候,表明图片已经进入可视区域,代码如下:
$(document).ready(function(){
$('img').each(function(){
if($(this).offset().top < $(window).height()){
$(this).attr('src',$(this).attr("x-src"));
}
})
})
当用户操作滚动条时,我们还需要知道滚动条的高度:
$(window).scroll(function(){
$('img').each(function(){
if($(this).attr('src')==""){
if($(this).offset().top<$(window).height()+$(window).scrollTop()){
$(this).attr("src",$(this).attr("x-src"));
}
}
})
})
静态文件设置强缓存
通常一个web网站最大的流量来源于静态图片文件,使用缓存后可以减少同一客户端对同一静态资源的重复下载。
缓存并不是浏览器缓存后就不会和服务端产生通信,它需要和服务器端确认一下它缓存的东西是不是最新的,如果是则使用,不是则重新下载,因此浏览器缓存后并不会减少与服务器的交互次数,但是会降低与服务端的连接时长,变相地减少了服务端的并发。
因此浏览器缓存对于服务端来说节省了带宽,对于客户端来说减少了重复下载同一资源的次数,也就加快了访问速度。
浏览器缓存某一信息后再次访问时需要基于某一标识来确认一下它缓存的东西是否是最新的,这个标识有两种:
Last_modified:
E-tag: