├── 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 |
nginx-lua-static-merger
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 |
how nginx-lua-static-merger work
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 --------------------------------------------------------------------------------