├── README.md
├── conf
└── nginx.conf
├── install
├── lua
└── lua-nginx_static_merger.lua
└── test
├── cold.css.data.by.ngx_static_merger.1.png
├── cold.css.data.by.ngx_static_merger.2.png
├── cold.js.by.ngx_static_merger.2.png
├── cold.js.data.data.by.ngx_static_merger.1.png
├── hot.js.data.data.by.ngx_static_merger.png
├── normal.http.get.1.png
└── normal.http.get.2.png
/README.md:
--------------------------------------------------------------------------------
1 | # nginx-lua-static-merger
2 |
3 |
4 |
5 | # About
6 |
7 | 详细教程请看:[http://homeway.me/2015/06/22/nginx-lua-static-merger/](http://homeway.me/2015/06/22/nginx-lua-static-merger/)
8 |
9 | `nginx-lua-static-merger`是一个基于openresty的模块,主要用于合并静态文件,减少http请求,加快静态文件访问速度的模块。
10 |
11 | 使用`nginx-lua-static-merger` 需要在编译nginx时候添加openresty的模块,或者直接安装openresty作为服务器。
12 |
13 | `nginx-lua-static-merger`可以让你的js、css请求不要那么多,一个就够了。
14 |
15 |
16 |
17 |
18 |
19 |
20 | # Usage
21 |
22 | ## install openresty
23 |
24 | [http://openresty.org/cn/](http://openresty.org/cn/)
25 |
26 | ```
27 | wget http://openresty.org/download/ngx_openresty-1.7.10.1.tar.gz
28 | tar xzvf ngx_openresty-1.7.10.1.tar.gz
29 | cd ngx_openresty-1.7.10.1/
30 | ./configure
31 | make
32 | make install
33 |
34 | ```
35 |
36 | ## install nginx-lua-static-merger
37 |
38 | > $git clone https://github.com/grasses/nginx-lua-static-merger
39 |
40 | > $cd nginx-lua-static-merger
41 |
42 | > $chmod +x install
43 |
44 | > $./install
45 |
46 | Remember install openresty before run install script.
47 |
48 |
49 | ## file path
50 |
51 | |--/usr/local/openresty/nginx
52 | | `--lua
53 | | `--nginx-lua-static-merger.lua
54 | | `--conf
55 | | `--nginx.lua
56 | |--/www/openresty/static
57 | | `--js
58 | | `--css
59 | | `--cache
60 |
61 | 注意
62 |
63 | 1、`nginx.conf`中的`lua_package_path "/usr/local/openresty/lualib/?.lua;;";`和
64 | `lua_package_cpath "/usr/local/openresty/lualib/?.so;;";`,如果你是编译nginx而不是直接安装openresty,目录记得放对。
65 |
66 | 2、确保`/www/openresty/static`有Lua写的权限。
67 |
68 | ## use
69 |
70 | 前端调用方法如下:
71 |
72 |
73 |
74 |
75 |
76 |
77 | # How it work
78 |
79 | Nginx在location通过 `content_by_lua_file` 把接下来的处理丢个Lua做逻辑。
80 |
81 | Lua通过uri进行md5编码,判断cache是否存在,如果cache不存在,循环分割、遍历uri,访问响应的路径,查找静态文件,存在则记录,最后写cache入文件,方便下次访问。
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | # Version
90 |
91 | 15.06.22
92 |
93 | * Beta Version
94 |
95 | 15.06.26
96 |
97 | * Fix a bug (single static file error)
98 |
99 | * Add install script
100 |
101 |
102 |
103 |
104 |
105 |
106 | # License
107 |
108 | ## GPL
--------------------------------------------------------------------------------
/conf/nginx.conf:
--------------------------------------------------------------------------------
1 | #user nobody;
2 | worker_processes 1;
3 |
4 | error_log /usr/local/openresty/nginx/logs/nginx.error.log;
5 | error_log /usr/local/openresty/nginx/logs/nginx.error.log notice;
6 | error_log /usr/local/openresty/nginx/logs/nginx.error.log info;
7 |
8 | pid /usr/local/openresty/nginx/logs/nginx.pid;
9 |
10 | events {
11 | worker_connections 256;
12 | multi_accept on;
13 | }
14 |
15 | http {
16 | include mime.types;
17 | default_type application/octet-stream;
18 |
19 | server_names_hash_bucket_size 128;
20 | client_header_buffer_size 32k;
21 | large_client_header_buffers 4 32k;
22 | client_max_body_size 50m;
23 |
24 | sendfile on;
25 | tcp_nopush on;
26 |
27 | keepalive_timeout 60;
28 | tcp_nodelay on;
29 |
30 | fastcgi_connect_timeout 300;
31 | fastcgi_send_timeout 300;
32 | fastcgi_read_timeout 300;
33 | fastcgi_buffer_size 64k;
34 | fastcgi_buffers 4 64k;
35 | fastcgi_busy_buffers_size 128k;
36 | fastcgi_temp_file_write_size 256k;
37 |
38 | gzip on;
39 | gzip_min_length 1k;
40 | gzip_buffers 4 16k;
41 | gzip_http_version 1.0;
42 | gzip_comp_level 2;
43 | gzip_types text/plain application/x-javascript text/css application/xml;
44 | gzip_vary on;
45 | gzip_proxied expired no-cache no-store private auth;
46 | gzip_disable "MSIE [1-6]\.";
47 |
48 | #limit_conn_zone $binary_remote_addr zone=perip:10m;
49 | ##If enable limit_conn_zone,add "limit_conn perip 10;" to server section.
50 |
51 | server_tokens off;
52 | #log format
53 | log_format access '$remote_addr - $remote_user [$time_local] "$request" '
54 | '$status $body_bytes_sent "$http_referer" '
55 | '"$http_user_agent" $http_x_forwarded_for';
56 |
57 | #include lua lib
58 | lua_package_path "/usr/local/openresty/lualib/?.lua;;";
59 | lua_package_cpath "/usr/local/openresty/lualib/?.so;;";
60 |
61 | server {
62 | listen 8080 default;
63 | server_name localhost;
64 | index index.html index.htm index.php;
65 |
66 | root /www/openresty;
67 |
68 | location ~ [^/]\.php(/|$) {
69 | # comment try_files $uri =404; to enable pathinfo
70 | try_files $uri = 404;
71 | fastcgi_pass 127.0.0.1:9000;
72 | fastcgi_index index.php;
73 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
74 | include fastcgi_params;
75 | }
76 |
77 | location ~ .*\.(js|css|woff|ttf|svg)$ {
78 | root /www/openresty/static;
79 | set $static_root /www/openresty/static;
80 | set $cache_root /www/openresty/static/cache;
81 | content_by_lua_file "/usr/local/openresty/nginx/lua-nginx_static_merger.lua";
82 | }
83 |
84 | access_log /usr/local/openresty/nginx/logs/openresty.access.log access;
85 | error_log /usr/local/openresty/nginx/logs/openresty.error.log;
86 | }
87 | include /usr/local/openresty/nginx/vhost/*.conf;
88 | }
--------------------------------------------------------------------------------
/install:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | prefix="/usr/local/openresty"
4 | nginx=$prefix"/nginx";
5 |
6 | echo "Install script will rewrite `nginx.conf`, do install? (y/n)"
7 | read y
8 |
9 | if [ $y != "y" ]; then
10 | echo "You choose no, thank you."
11 | exit 1;
12 | fi
13 |
14 | sudo mkdir $nginx"/lua";
15 | sudo mkdir $nginx"/conf";
16 |
17 | echo "===================== move confgure file ==================="
18 |
19 | sudo cp -fr "lua/lua-nginx_static_merger.lua" $nginx"/lua/lua-nginx_static_merger.lua";
20 | sudo cp -fr "conf/nginx.conf" $nginx"/conf/nginx.conf";
21 |
22 | echo "===================== reload nginx ==================="
23 | sudo nginx -s reload;
24 | echo "===================== install completed ==================="
25 |
--------------------------------------------------------------------------------
/lua/lua-nginx_static_merger.lua:
--------------------------------------------------------------------------------
1 | -- package : ngx_static_merger
2 | -- version : 15.07.10
3 | -- author : https://github.com/grasses
4 |
5 | local str = require "resty.string"
6 | local resty_md5 = require "resty.md5"
7 |
8 | local uri = ngx.var.uri
9 | local cache_root = ngx.var.cache_root
10 | local static_root = ngx.var.static_root
11 |
12 | local M = {
13 | log_level = ngx.NOTICE,
14 | _VERSION = "15.07.10",
15 | }
16 |
17 | --[[
18 | @param string msg
19 | @param string level => ngx.STDERR , ngx.EMERG , ngx.ALERT , ngx.CRIT , ngx.ERR , ngx.WARN , ngx.NOTICE , ngx.INFO , ngx.DEBUG
20 | @return nginx => log file
21 | ]]
22 | M.log = function (msg, level)
23 | level = level or M.log_level
24 | ngx.log(level, msg)
25 | end
26 |
27 | --[[
28 | @param string str
29 | @param string split_char => split rule
30 | @return table split => string split array
31 | ]]
32 | M.uri_split = function (str, split_char)
33 | local sub_str_tab = {}
34 | local i = 0
35 | local j = 0
36 | while true do
37 | j = string.find(str, split_char, i+1)
38 | if j == nil then
39 | if(table.getn(sub_str_tab)==0) then
40 | table.insert(sub_str_tab, str)
41 | end
42 | break
43 | end
44 | table.insert(sub_str_tab, string.sub(str, i+1, j-1))
45 | i = j
46 | end
47 | return sub_str_tab
48 | end
49 |
50 | --[[
51 | @param string uri => request uri
52 | @param string version => request param "v"
53 | @return fun => M.generate_file or M.return_file
54 | @function => check if cache file exist, if not, create it then retrun
55 | ]]
56 | M.check_version = function(uri, version)
57 | local md5 = resty_md5:new()
58 | if not md5 then
59 | M.log("Failed to create md5 object", ngx.ERR)
60 | return
61 | end
62 |
63 | local ok = md5:update(uri)
64 | if not ok then
65 | M.log("Check_version => md5 module => failed to add data", ngx.ERR)
66 | return
67 | end
68 |
69 | local digest = md5:final()
70 | local fpath = cache_root.."/"..str.to_hex(digest).."?v="..version
71 | --ngx.say("file path => ", fpath)
72 | local fp,err = io.open(fpath, "r")
73 | if fp~=nil then
74 | M.return_file(fp)
75 | else
76 | M.generate_file(fpath)
77 | end
78 | end
79 |
80 | --[[
81 | @param string fpath => cache file path
82 | @return string => return ngx.say(data)
83 | @function => generate cache file
84 | ]]
85 | M.generate_file = function(fpath)
86 | local data = ""
87 | local parts = M.uri_split(uri..";", ";")
88 | -- read table and get static data
89 | for key, value in ipairs(parts) do
90 | local fp1, err = io.open(static_root..value, "r")
91 | if fp1~=nil then
92 | data = data..fp1:read("*all")
93 | fp1:close()
94 | else
95 | M.log("Generate_file => file not exist => "..value, ngx.NOTICE)
96 | end
97 | end
98 | -- save cache file
99 | local fp2, err = io.open(fpath, "w")
100 | if fp2~=nil then
101 | fp2:write(data)
102 | fp2:close()
103 | else
104 | M.log("Generate_file => file not exist => "..fpath, ngx.NOTICE)
105 | end
106 | -- return data to client
107 | ngx.say(data)
108 | end
109 |
110 | --[[
111 | @param string fp => file open pointer
112 | @return => return ngx.say(data)
113 | ]]
114 | M.return_file = function(fp)
115 | if fp~=nil then
116 | ngx.say(fp:read("*all"))
117 | fp:close()
118 | else
119 | M.log("Return_file() => file not exist => "..v, ngx.NOTICE)
120 | end
121 | end
122 |
123 | M.main = function()
124 | -- check cache path
125 | local fp = io.open(cache_root, "r")
126 | if fp == nil then
127 | os.execute('mkdir '..cache_root)
128 | M.log("Main() => cache path not exist => "..cache_root, ngx.NOTICE)
129 | end
130 | local arg = ngx.req.get_uri_args()
131 | if arg["v"] ~= nil then
132 | M.check_version(uri, arg["v"])
133 | else
134 | M.check_version(uri, os.date("%Y-%m-%d"))
135 | end
136 | end
137 |
138 | M.main()
--------------------------------------------------------------------------------
/test/cold.css.data.by.ngx_static_merger.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grasses/nginx-lua-static-merger/0c4f640082cebb3e258a5027a86925ba95fab6c5/test/cold.css.data.by.ngx_static_merger.1.png
--------------------------------------------------------------------------------
/test/cold.css.data.by.ngx_static_merger.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grasses/nginx-lua-static-merger/0c4f640082cebb3e258a5027a86925ba95fab6c5/test/cold.css.data.by.ngx_static_merger.2.png
--------------------------------------------------------------------------------
/test/cold.js.by.ngx_static_merger.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grasses/nginx-lua-static-merger/0c4f640082cebb3e258a5027a86925ba95fab6c5/test/cold.js.by.ngx_static_merger.2.png
--------------------------------------------------------------------------------
/test/cold.js.data.data.by.ngx_static_merger.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grasses/nginx-lua-static-merger/0c4f640082cebb3e258a5027a86925ba95fab6c5/test/cold.js.data.data.by.ngx_static_merger.1.png
--------------------------------------------------------------------------------
/test/hot.js.data.data.by.ngx_static_merger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grasses/nginx-lua-static-merger/0c4f640082cebb3e258a5027a86925ba95fab6c5/test/hot.js.data.data.by.ngx_static_merger.png
--------------------------------------------------------------------------------
/test/normal.http.get.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grasses/nginx-lua-static-merger/0c4f640082cebb3e258a5027a86925ba95fab6c5/test/normal.http.get.1.png
--------------------------------------------------------------------------------
/test/normal.http.get.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grasses/nginx-lua-static-merger/0c4f640082cebb3e258a5027a86925ba95fab6c5/test/normal.http.get.2.png
--------------------------------------------------------------------------------