最新消息:欢迎访问Android开发中文站!商务联系微信:loading_in

做个前端,来点Nginx

热点资讯 loading 1213浏览 0评论

自从Nodejs火了,前端能做的事、要做的事越来越多了;同时对前端的要求也就越来越高,如果现在还只是停留在浏览器端写页面做交互,估计很难找到(更好的)工作了,Node中间层、Node微服务、网关这些可以和业务分离的地方以后可能都是前端的事了;Nodejs是把锋利的瑞士军刀,但你也不要想多了;合理的选型,各司其职,职尽其能,才能发挥各自最大的作用;毕竟一切从实际出发,实事求是,理论联系实际才是最佳的方法论;比如Nodejs可以做反向代理(http-proxy),可以很快的搭建静态资源站,但这些并不是Nodejs最擅长的,这些交给Nginx显然是个更好的选择,既可以把这些事做更好,还给Nodejs服务减压了!

一、快速拾起Nginx

Nginx是一个高性能的Web和反向代理服务器,稳定、强大、系统资源占用低,这些就不说了;

在nginx.conf这个配置文件里,一个server {}块可以对应一个站点的服务,每个server {}块里可以配置多个location {}块来对站点进行路由级别的控制,既可以通过proxy_pass target设置反向代理的server,也可以直接通过root dir来访问目录下的静态文件;server_name设置访问的域,多个用空格隔开,或者用通配符和正则;location后面可以是正则以及nginx提供的丰富的匹配符和变量;记住大括号前面的空格不能省,每行结束语句的分号不能省;

a. 比如用Nodejs启动了一个站点监听3000端口,用a.famanoder.cn来访问

server {
    listen 80;
    server_name a.famanoder.cn;

	location / {
        proxy_pass http://localhost:3000;
    }
}

b. 比如把所有的静态资源放到了dist目录,用cdn.famanoder.cn来访问

server {
    listen 80;
    server_name cdn.famanoder.cn;

	location / {
        index index.html;
        root D:\sources\dist;
    }
}

c. 用vue做的一个移动端的项目,用m.famanoder.cn来访问,所有数据接口由famanoder.cn提供;

server {
    listen 80;
    server_name m.famanoder.cn;

	location /api {
		# 代理api,以免跨域
        proxy_pass https://famanoder.cn;
    }
    location / {
        index index.html;
        root D:/vue/dist;
    }
}

以上只是最简单的站点和反向代理设置,通过匹配符和正则可以做更多的控制;

二、常用匹配符和变量

=   等于,严格匹配

!=  不等于

~   区分大小写匹配

!~  区分大小写不匹配

~*  不区分大小写匹配

!~* 不区分大小写不匹配

*   任意字符

-f和!-f 判断是否存在文件

-d和!-d 判断是否存在目录

-e和!-e 判断是否存在文件或目录

-x和!-x 判断文件是否可执行

对于location,匹配的优先级为:

(location =) > (location 完整路径) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 部分起始路径) > (/)

Nginx里有if指令,但是没有else指令和&&判断,但可以通过set变通的实现:

比如限制GET请求参数中的SQL关键词:

set $invalidQuery 1;
if( $request_method = GET ){
	set $invalidQuery '${invalidQuery}1';
} 
if( $query_string ~* "select|union|exec" ){
	set $invalidQuery '${invalidQuery}1';
} 
if( $invalidQuery = '111' ){
	return 403;
}

常用变量:

$args : 请求行中的参数,同$query_string。等于js中的location.search.slice(1)。

$content_type : 请求头中的Content-Type字段。

$document_root : 当前请求在root指令中指定的值。

$host : 请求主机头字段,否则为服务器名称。等于js中的location.host。

$http_user_agent : 客户端agent信息。等于js中的navigator.userAgent。

$http_cookie : 客户端cookie信息。等于js中的document.cookie。

$limit_rate : 这个变量可以限制连接速率。

$request_method : 客户端请求的动作,通常为GET或POST。

$remote_addr : 客户端的IP地址。

$remote_port : 客户端的端口。等于js中的location.port。

$http_referer :网页来源。等于js中的document.referer。

$remote_user : 已经经过Auth Basic Module验证的用户名。

$request_filename : 当前请求的文件路径,由root或alias指令与URI请求生成。

$scheme : HTTP方法(如http,https)。等于js中的location.protocol。

$server_protocol : 请求使用的协议,通常是HTTP/1.0或HTTP/1.1。

$server_addr : 服务器地址,在完成一次系统调用后可以确定这个值。

$server_name : 服务器名称。

$server_port : 请求到达服务器的端口号。

$request_uri : 包含请求参数的原始URI,不包含主机名,等于js中的location.pathname+location.search。

$uri : 不带请求参数的当前URI,$uri不包含主机名,等于js中的location.pathname。

$document_uri : 与$uri相同。

三、常见设置

1、worker_processes 4   # 开启多进程,一般为cpu核数,等于Nodejs中的require(‘os’).cpus().length

2、error_log  logs/error.log  info;   # log文件的地址和级别(debug, info, notice, warn, error, crit)

3、log_format 格式名称 具体格式   # 定义日志内容的格式可以包含$remote_addr $status $http_user_agent等参数

4、开启gzip

gzip  on;

gzip_proxied any;

gzip_min_length  1024;

gzip_buffers     4 8k;

gzip_types       text/css application/javascript application/atom+xml application/rss+xml text/plain image/svg+xml application/json text/javascript;

默认的配置文件中只有gzip on作用不大,需要自行配置后续gzip字段;给所有需要开启gzip的资源添加mimeType,图片不需要gzip(没有明显效果,体积还可能增大),白白损耗性能;

四、解决前端跨域问题

在前后端分离的时候,前后端搭建了两套环境,前端请求数据的时候会跨域,一般是用Nodejs做中转,比如使用http-proxy和request模块,或者在webpack的dev-server里配置proxy,浏览器兼容性比较理想的情况下还可以直接设置CORS;这样对于打包上线也不需要做太多改动;当然有时候还需要jsonp;

1. 设置CORS

server {
    listen 80;
    server_name cdn.famanoder.cn;

    location / {
    	add_header Access-Control-Allow-Origin *;  
        add_header Access-Control-Allow-Credentials true;  
        add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
        index index.html;
        root D:/sources/dist;
    }
}
# 如果不想设置星号的话,这个变通的做法貌似更灵活,还可以通过跨域反过来限制某些资源的是否可访问
if ($http_referer ~* 'famanoder.cn') {  
    add_header Access-Control-Allow-Origin *;  
    add_header Access-Control-Allow-Credentials true;  
    add_header Access-Control-Allow-Methods GET,POST,OPTIONS;  
}

2. 做api中转

server {
    listen 80;
    server_name m.famanoder.cn;

    location /api {
    	proxy_pass https://localhost:3000;
    }
}

五、从http切换到https

对于一般的散户来说,Letsencrypt是个不错的选择,可以免费为多个域名提供一套证书(散户福利!Nodejs多站点切换Htpps协议);可以新建一个站点专门为申请证书服务,以免以后重新申请时重启应用或再次搭建;对于切换到https,只需在80端口上直接对指定域名做301跳转到https对应地址,server块内做很小改动即可:

server {
    listen 80;
    server_name *.famanoder.com famanoder.com;

    location / {
    	# 迁移到https
        return 301 https://$host$request_uri;
    }

    location ~* 'acme-challenge' {
		# 2333端口留做以后申请证书用
        proxy_pass http://localhost:2333;
    }
}
server {
	# 监听443端口,开启ssl
    listen 443 ssl;
    server_name cdn.famanoder.cn;
    # 把申请到的证书加进来
    ssl_certificate      D:/crt.pem;
	ssl_certificate_key  D:/key.pem;

	location / {
        index index.html;
        root D:\sources\dist;
    }
}

六、Nginx真的超级强大,而且配置起来并不繁琐,常常简单的设置就可以达到非常强大的功能,比如做安全访问限制、负载均衡等;

如果你很喜欢一个东西,那么是否应该拿它来做更多有意义的事情!如果你很喜欢JS,那么是否应该拿它来做更多有意义的事情!那么好的,听说新版Nginx开始支持js语法了!如果你已在路上,就勇敢的向前吧!

转载请注明:Android开发中文站 » 做个前端,来点Nginx

您必须 登录 才能发表评论!