openresty中使用淘宝的concat进行css和js合并

75 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

背景

我们在访问淘宝的时候,会看到代码中的js和css文件是通过一次请求获得的,我们知道浏览器一次请求只能并发访问数个资源,这样的处理错输在网络传输层面可以大大节省时间,这里使用的技术就是把css、js等静态资源合并为一个资源。淘宝使用的tengine是基于nginx的web服务器,从11年底开源。所使用的是mod_concat模块,合并多个文件在一个响应报文中。

实战

先查看下当前openresty的版本和配置信息

/usr/local/openresty/nginx/sbin/nginx -Vnginx version: openresty/1.15.8.1built by gcc 4.4.7 20120313 (Red Hat 4.4.7-23) (GCC) built with OpenSSL 1.0.1u  22 Sep 2016 (running with OpenSSL 1.0.1e-fips 11 Feb 2013)TLS SNI support enabledconfigure arguments: --prefix=/usr/local/openresty/nginx --with-cc-opt=-O2 --add-module=../ngx_devel_kit-0.3.1rc1 --add-module=../echo-nginx-module-0.61 --add-module=../xss-nginx-module-0.06 --add-module=../ngx_coolkit-0.2 --add-module=../set-misc-nginx-module-0.32 --add-module=../form-input-nginx-module-0.12 --add-module=../encrypted-session-nginx-module-0.08 --add-module=../srcache-nginx-module-0.31 --add-module=../ngx_lua-0.10.15 --add-module=../ngx_lua_upstream-0.07 --add-module=../headers-more-nginx-module-0.33 --add-module=../array-var-nginx-module-0.05 --add-module=../memc-nginx-module-0.19 --add-module=../redis2-nginx-module-0.15 --add-module=../redis-nginx-module-0.3.7 --add-module=../rds-json-nginx-module-0.15 --add-module=../rds-csv-nginx-module-0.09 --add-module=../ngx_stream_lua-0.0.7 --with-ld-opt=-Wl,-rpath,/usr/local/openresty/luajit/lib --user=www --group=www --with-http_stub_status_module --with-http_sub_module --with-http_ssl_module --with-http_v2_module --with-http_gunzip_module --with-http_realip_module --with-http_geoip_module --with-pcre --with-file-aio --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module

下载最新淘宝的nginx-http-concat模块

cd /rootgit clone git://github.com/alibaba/nginx-http-concat.git

下载对应版本的openresty

注意不需要执行gmake install,执行gmake install是覆盖安装

wget https://openresty.org/download/openresty-1.15.8.1.tar.gztar -xzvf openresty-1.15.8.1.tar.gzcd openresty-1.15.8.1#配置 最后新增 --add-module=../nginx-http-concat./configure --prefix=/usr/local/openresty/nginx \--with-cc-opt=-O2 --add-module=../ngx_devel_kit-0.3.1rc1 \--add-module=../echo-nginx-module-0.61 --add-module=../xss-nginx-module-0.06 \--add-module=../ngx_coolkit-0.2 --add-module=../set-misc-nginx-module-0.32 \--add-module=../form-input-nginx-module-0.12 --add-module=../encrypted-session-nginx-module-0.08 \--add-module=../srcache-nginx-module-0.31 --add-module=../ngx_lua-0.10.15 \--add-module=../ngx_lua_upstream-0.07 --add-module=../headers-more-nginx-module-0.33 \--add-module=../array-var-nginx-module-0.05 --add-module=../memc-nginx-module-0.19 \--add-module=../redis2-nginx-module-0.15 --add-module=../redis-nginx-module-0.3.7 \--add-module=../rds-json-nginx-module-0.15 --add-module=../rds-csv-nginx-module-0.09 \--add-module=../ngx_stream_lua-0.0.7 --with-ld-opt=-Wl,-rpath,/usr/local/openresty/luajit/lib \--user=www --group=www --with-http_stub_status_module --with-http_sub_module --with-http_ssl_module \--with-http_v2_module --with-http_gunzip_module --with-http_realip_module --with-http_geoip_module \--with-pcre --with-file-aio --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module \--add-module=../nginx-http-concatgmake#注意不需要执行gmake install,执行gmake install是覆盖安装

发现上面这个原来的配置参数,很多用到了相对目录 “--add-module=../" ,但是自己的目录上层目录并没有这些模块的文件夹,一开始想着是不是要去挨个下载,咨询了很多地方也没有好的答案,于是自己去github上把各个模块对应的版本都下载下来,放到了上层目录中,用上面这个命令configure,结果各种报错:

multiple definition of `ngx_http_rds_csv_output_more_field_data'

表示add-module中的已经自动包含,不需要add-module主动指定。

正确的做法,根本不用下载各个模块,因为执行configure的时候已经生成了对应的模块目录。

目录:/root/openresty-1.15.8.1/build/

./configure --prefix=/usr/local/openresty/nginx \--with-cc-opt=-O2 --with-ld-opt=-Wl,-rpath,/usr/local/openresty/luajit/lib \--user=www --group=www --with-http_stub_status_module --with-http_sub_module --with-http_ssl_module \--with-http_v2_module --with-http_gunzip_module --with-http_realip_module --with-http_geoip_module \--with-pcre --with-file-aio --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module \--add-module=../nginx-http-concat#注意不需要执行gmake install,执行gmake install是覆盖安装gmakecd build/nginx-1.15.8/objs/  && cp nginx /usr/local/openresty/nginx/sbin/nginx.new#找到原来的nginx执行命令ps -ef|grep nginx|grep master#原来的命令是 /usr/local/openresty/bin/openresty -c /usr/local/openresty/nginx/conf/nginx.conf#咱们用新构建的nginx测试下,加上 -t测试./nginx.new -c /usr/local/openresty/nginx/conf/nginx.conf -tnginx: [alert] could not open error log file: open() "/usr/local/openresty/nginx/nginx/logs/error.log" failed (2: No such file or directory)#发现多了一层nginx目录,看起来是configure的时候目录多了一个,重新来一遍gmake clean# --prefix 参数减少一个nginx目录./configure --prefix=/usr/local/openresty \--with-cc-opt=-O2 --with-ld-opt=-Wl,-rpath,/usr/local/openresty/luajit/lib \--user=www --group=www --with-http_stub_status_module --with-http_sub_module --with-http_ssl_module \--with-http_v2_module --with-http_gunzip_module --with-http_realip_module --with-http_geoip_module \--with-pcre --with-file-aio --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module \--add-module=../nginx-http-concat#注意不需要执行gmake install,执行gmake install是覆盖安装gmakecd build/nginx-1.15.8/objs/  && cp nginx /usr/local/openresty/nginx/sbin/nginx.new -fcd /usr/local/openresty/nginx/sbin/ && ./nginx.new -c /usr/local/openresty/nginx/conf/nginx.conf -t #输出如下信息,标识构建成功nginx: the configuration file /usr/local/openresty/nginx/conf/nginx.conf syntax is oknginx: configuration file /usr/local/openresty/nginx/conf/nginx.conf test is successful

备份老的nginx文件、覆盖最新的文件

mv /usr/local/openresty/nginx/sbin/nginx /usr/local/openresty/nginx/sbin/nginx.bakmv /usr/local/openresty/nginx/sbin/nginx.new /usr/local/openresty/nginx/sbin/nginx/usr/local/openresty/nginx/sbin/nginx -V#输出如下信息,那些相对目录的模块也都存在,说明没有错误nginx version: openresty/1.15.8.1built by gcc 4.4.7 20120313 (Red Hat 4.4.7-23) (GCC) built with OpenSSL 1.0.1e-fips 11 Feb 2013TLS SNI support enabledconfigure arguments: --prefix=/usr/local/openresty/nginx --with-cc-opt='-O2 -O2' --add-module=../ngx_devel_kit-0.3.1rc1 \--add-module=../echo-nginx-module-0.61 --add-module=../xss-nginx-module-0.06 --add-module=../ngx_coolkit-0.2 \--add-module=../set-misc-nginx-module-0.32 --add-module=../form-input-nginx-module-0.12 --add-module=../encrypted-session-nginx-module-0.08 \--add-module=../srcache-nginx-module-0.31 --add-module=../ngx_lua-0.10.15 --add-module=../ngx_lua_upstream-0.07 \--add-module=../headers-more-nginx-module-0.33 --add-module=../array-var-nginx-module-0.05 --add-module=../memc-nginx-module-0.19 \--add-module=../redis2-nginx-module-0.15 --add-module=../redis-nginx-module-0.3.7 --add-module=../rds-json-nginx-module-0.15 \--add-module=../rds-csv-nginx-module-0.09 --add-module=../ngx_stream_lua-0.0.7 \--with-ld-opt='-Wl,-rpath,/usr/local/openresty/luajit/lib -Wl,-rpath,/usr/local/openresty/luajit/lib' \--user=www --group=www --with-http_stub_status_module --with-http_sub_module --with-http_ssl_module \--with-http_v2_module --with-http_gunzip_module --with-http_realip_module --with-http_geoip_module --with-pcre \--with-file-aio --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module \--add-module=/root/openresty-1.15.8.1/../nginx-http-concat --with-stream --with-stream_ssl_preread_module#重启nginx /usr/local/openresty/bin/openresty -c /usr/local/openresty/nginx/conf/nginx.conf -s reload

concat配置说明:

使用??拼接多个文件

https://www.phpmianshi.com/??style1.css,style2.css,foo/style3.css

如果有第三个问号,则表示版本号

https://www.phpmianshi.com/??style1.css,style2.css,foo/style3.css?v=102234

concat

语法:concat [on|off]

默认:off

配置段:http, server, location

作用:允许在给定的配置段中进行串联

concat_types

语法:concat_types MIME types

默认:text/css application/x-javascript

配置段:http, server, location

作用:定义可以在给定配置段中串联的MIME类型。

concat_unique

语法:concat_unique [on|off]

默认:on

配置段:http, server, location

作用:定义是否只能串联给定MIME类型的文件,或者可以串联多个MIME类型。

concat_max_files

语法:concat_max_files编号

默认:10

配置段:http,服务器,位置

作用:定义在给定配置段中可以串联的最大文件数。

concat_delimiter

合并后的文件内容分隔符,用于区分不同文件的内容

concat_ignore_file_error

是否忽略404或403错误,选项:on | off,默认:off

配置concat配置文件,并再次重启nginx(最好是kill掉完全重启,否则有可能不生效

server {    listen 80;    server_name www.phpmianshi.com;     index  index.php;    root /data/nginx/www/www.phpmianshi.com;     location ~ [^/]\.php(/|$) {        try_files $uri =404;        fastcgi_pass  unix:/tmp/php-cgi.sock;        fastcgi_index index.php;        include fastcgi.conf;    }    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {        expires 30d;    }        location ~ .*\.(js|css)?$ {        expires 12h;    }    location / {        if (!-e $request_filename) {            rewrite  ^(.*)$  /index.php?s=$1  last;            break;        }    }    concat on;    concat_max_files 20;    concat_unique off;    concat_types text/css application/javascript;    access_log  /data/nginx/logs/access.log  json;}

测试

网站根目录写3个测试文件

#test1.jsconsole.log("11");#test2.jsconsole.log("22");#test.html<html><head><script type="text/javascript" src="./??test1.js,test2.js"></script></head><body>  这里是文档的主体 ... ...</body></html>

访问一下 www.phpmianshi.com/test.html ,控制台输出 11 22 ,看network网络请求,只有一次请求,说明配置完成

注意事项

--add-module=build/ngx_stream_lua-0.0.7不需要加,因为:

ngx_stream_lua_module is already enabled in OpenResty by default. Your linker errors clearly indicate that. You should remove the option --add-module=build/ngx_stream_lua-0.0.7.

官方git issue回复:

github.com/openresty/o…

multiple definition of `ngx_http_rds_csv_output_more_field_data':表示add-module中的已经自动包含,不需要add-module主动指定。

参考:

www.phpmianshi.com/?id=285

openresty.org/