0x01 Tengine简介

介绍此功能之前需要先介绍一下Tengine,因为此功能依赖于Tengine。Tengine是由淘宝网发起的Web服务器项目。它在Nginx的基础上,针对大访问量网站的需求,添加了很多高级功能和特性,其中就包括我们需要用到的concat模块。该模块类似于apache中的mod_concat模块,用于合并多个文件在一个响应报文中。 请求参数需要用两个问号(’??‘)例如:

http://example.com/??style1.css,style2.css,foo/style3.css

参数中某位置只包含一个‘?’,则’?‘后表示文件的版本,例如:

http://example.com/??style1.css,style2.css,foo/style3.css?v=102234

0x02 Tengine安装和配置

之前我写过一篇记录编译安装Tengine+PHP-FPM运行 Wordpress 的过程,其中就写了Tengine的安装脚本,只是目前的最新版是2.1.2,再次贴一下安装脚本:

wget -c http://tengine.taobao.org/download/tengine-2.1.2.tar.gz
tar zxf tengine-2.1.2.tar.gz
cd tengine-2.1.2
./configure --prefix=/usr/local/nginx \
--user=www-data \
--group=www-data \
--with-http_stub_status_module \
--without-http-cache \
--with-http_ssl_module \
--with-http_gzip_static_module \
--with-http_concat_module
CPU_NUM=$(cat /proc/cpuinfo | grep processor | wc -l)
if [ $CPU_NUM -gt 1 ];then
    make -j$CPU_NUM
else
    make
fi
make install

注意的是一定要加上--with-http_concat_module

然后配置一下nginx.conf,在http或server段添加如下配置:

    concat on;
    concat_types text/css text/html application/javascript;
    concat_max_files 30;

注意concat_types要加上application/javascript,然后合并的文件数量不要超过设置的concat_max_files,不然会遇到400的错误。

0x03 修改主题

经过上面的配置之后,现在只需要将主题中引入css和js文件的地方合并分别为一个链接即可。 如果你不想手动合并,我也写了一个插件,在你Hexo主题的scripts目录添加一个js文件,任意命名,复制下面的代码:

'use strict';

var cheerio = require('cheerio');
var siteurl = hexo.config.url;

function concat(source) {
  var $ = cheerio.load(source, {
    decodeEntities: false
  });

  if (hexo.config.concat.css) {
    var elements = [];
    var urls = [];
    $('link', 'head').each(function(i, e) {
      var link = $(e);
      var skip = link.attr("skip");
      if (!skip && (link.attr('rel') == 'stylesheet' || link.attr('type') == 'text/css')) {
        urls.push(link.attr('href') + ",");
        elements.push(link);
      }
    });

    if (elements.length && urls.length && elements.length == urls.length) {
      for (var i = 0; i < elements.length - 1; i++) {
        elements[i].remove();
      };

      var concatUrl = urls.join('');
      var link = elements[elements.length - 1];
      link.attr('href', siteurl + "??" + concatUrl.substring(0, concatUrl.length - 1));
    }
  }

  if (hexo.config.concat.js) {
    var elements = [];
    var urls = [];
    $('script').each(function(index, element) {
      var script = $(element).attr("src");
      var skip = $(element).attr("skip");
      if (script && !skip) {
        urls.push(script + ",");
        elements.push($(element));
      }
    });

    if (elements.length && urls.length && elements.length == urls.length) {
      for (var i = 0; i < elements.length - 1; i++) {
        elements[i].remove();
      };

      var concatUrl = urls.join('');
      var script = elements[elements.length - 1];
      script.attr('src', siteurl + "??" + concatUrl.substring(0, concatUrl.length - 1));
    }

  }
  return $.html();
}

if (hexo.config.concat.js || hexo.config.concat.css) {
  hexo.extend.filter.register('after_render:html', concat);
}

然后在Hexo根目录下的_config.yml添加如下代码以开启插件功能。

concat:
	js: true
	css: true

0x04 效果对比

就我的博客而言,没有开启css和js合并的时候共有34个请求。

concat_before
concat_before

开启css和js合并之后变为27个请求,减少了7个请求。而且页面的加载完成时间也大大的缩短了。如果你的Hexo博客放在自己的服务器上,强烈建议你使用Tengine开启此功能。

concat_after
concat_after