前端性能调优

前几天,对九霄项目进行了一次大范围的性能优化,效果还不错,首屏从最开始的899个请求4.98s加载,到最后29个请求998ms加载,提高了79%以上。这里记录一下优化的过程,方便有须要的朋友。css

开篇

新工做已经4个多月,从0开始到如今三个子系统并行,每一个子系统负责滴滴业务线的数据分析,业务量和业务逻辑至关复杂。不过随着业务的扩展,性能也随之会成为阻碍系统运转的瓶颈,性能优化势在必行。html

现状

目前前端技术架构是:前端

seajs + arale + koa + gulp + lesshtml5

页面部署是:node

+ router.js
      - entry[入口]
      - express[快车]
      - hitch[顺风车]
      - daijia[代驾]

页面是由路由依次进入四个页面。因为是单页面应用,因此资源文件都是一次加载,致使子系统越多,加载文件越多,网站也愈来愈慢。nginx

优化

优化一: 按需加载

从上面的架构来看,seajs模块combo在一块儿,合成一个 nsky.min.js 的原始发布方案已经不能知足需求了,须要划分子系统按需加载。git

按需加载的意思是,进入首页时加载首页必须依赖的模块,不加载其余页面(快车,顺风车,代驾)所需资源。github

seajs请求资源的原理是正则扫描每一个模块中require的字符串,从而提取模块的依赖。加载模块时,首先加载其依赖文件,所以咱们可以经过 combo 的方式把模块合并到一个文件。另外,seajs中提供 require.async 来实现异步加载。web

所以,咱们在router里面转发到不一样页面的时候使用 require.async,从而实现分子系统按需加载。express

优化结果以下:

首屏请求数量直接从899个优化到57个,结果仍是可喜。

优化二:请求合并

观察请求瀑布流,发现请求文件仍是太多,好比系统资源加载(class.js/events.js/overlay.js等),还有业务代码较多,咱们能够把这些资源合并在一块儿,发出combo请求。

好比发出

http://d.kuaidadi.com/path/??class.js,events.js,overlay.js,xxx.js

而后服务端响应此 combo 请求,返回 class.js, events.js, overlay.js, xxx.js的合集,这样就能够实现请求合并。

首先,须要浏览器发出相似 ??a.js,b.js,c.js 的combo请求。seajs发出combo请求很简单,经过seajs combo插件就能够了:

seajs.config({
    preload: "seajs-combo"
 });

其次,须要服务器端响应相似 ??a.js,b.js,c.js 的combo请求。

seajs combo插件中文文档中提到,服务端实现combo请求是经过Nginx-Http-Concat实现。

可是因为线上服务器是经过 Nginx 来实现数台生产机器间负载均衡,经过 Nginx Proxy Pass实现非80端转发到80端口。通过试验发现,Nginx的 Proxy PassNginx-Http-Concat不能同时使用,其做者也说过暂时不支持。,因此此路不通。

所以,只能本身实现Node Combo。因而又找了很多node-combo项目(好比node-combo),研究其实现思路,准备本身写koa-node-combo插件了。

后来搜索npm仓库,发现有多个这样的插件,尝试发现koa-combo-parse可行:

app.use(comboParse({
    base: path.resolve(__dirname, '../client/')
}));

可是,问题又来了。combo到一块儿后系统仍然不能运行,由于文件之间没有识别的id。须要寻找工具来对每一个模版补全id和依赖(deps),combo后就能互相识别了。即须要从:

define(function(require, exports, module){
    var a = require('a'),
        b = require('b'); 
    module.exports = {};
});

变成:

define('moduleId', ['a', 'b'], function(require, exports, module){
    var a = require('a'),
        b = require('b');
    module.exports = {};
});

在此过程当中调研了 spmgulp-seajs-combo等,发现都不知足需求。

因而本身实现了node小工具 iddeps,并写成了gulp插件gulp-ids-deps

最终,前端发出combo请求后,后端响应combo请求,效果以下:

请求数量从57减小到37,请求时间从1.4s减小到了1.18s。

优化三:模版文件预编译

从上面的瀑布流能看出,tpl文件既大又多,占用很多请求时间。

在handlebars中,有预编译的思想,能够在运行前把模版文件预编译成为 js 文件。

业界没有相应的工具,因而本身写了一个node小工具tpl-2-js,并改写成gulp插件gulp-tpl-2-js

Handlebars预编译的过程是:

//  node
   var preCompileData = handlebars.precompile(data);
// web 
   var Handlebars = require('handlebars'),
    template = Handlebars.template;

   template(preCompileData)({data});

预编译的过程,是Handlebars precompile建立了一个函数,把每一个template存储在 Handlebars.templates里面。

更多详细请看:gulp-tpl-2-js

通过模版预编译后、Combo后,效果以下:

能够看到,请求结果从上次的37减小到29,请求时间从1.18s减小到998ms

后续

总体结果优化的效果差很少了,请求数变到最小,时间首屏时间也符合指望。

后续的优化,能够考虑经过 html5 的 appcache 缓存不常常的更新资源文件,把 200 的资源文件变成 302。

本文是记录本身优化系统的心路历程,有不一样意见或者有所收获的能够留言讨论。

原创文章,欢迎转载。转载请注明:转载自Fs21 ' s Home,谢谢!
原文连接地址:前端性能调优

相关文章
相关标签/搜索