一.React nginx部署代理
nignx是一款非常优秀的服务器软件,前端工程师在开发完项目后,通常要将项目部署到服务器,我在部署项目时用的就是nginx。
今天跟大家分享一下用nginx部署前端项目的一些经验。
React项目开发完成后,需要运行 build指令进行打包,打包完成后得到打包的文件,然后将这些文件部署到服务器。
关于打包这里通常有两种操作,一种是在本地打包,然后将打包文件利用scp指令或者其它一些软件将文件上传到服务器。
另一种方式是直接在服务器clone一下项目,每次更新项目后服务器进行同步并打包。
文中示例以本地服务器为例,不存在文件传输,这里不做赘述。
用nginx部署前端应用,最主要的工作是写配置文件,我在网上找到一份比较合适的配置文件,这里只展示了server模块的配置,代码如下:
server {
listen 8888;#默认端口是80,如果端口没被占用可以不用修改
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
#vue或者React项目的打包后的dist
root E:/vue/my_project/dist;
location / {
#需要指向下面的@router
try_files $uri $uri/ @router;
index index.html index.htm;
}
#对应上面的@router,
#主要原因是路由的路径资源并不是一个真实的路径,所以无法找到具体的文件
#因此需要rewrite到index.html中,然后交给前端路由再处理请求资源
location @router {
rewrite ^.*$ /index.html last;
}
#.......其他部分省略
}
server {
listen 443 ssl;
server_name ydxxtest.gemdale.com;
ssl_certificate keys/gemdale.com.pem;
ssl_certificate_key keys/gemdale.com.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
#防止无法识别js文件类
location ~ ^/(images|img|javascript|js|css|vue|flash|media|static)/ {
autoindex on;
access_log off;
#expires 0d;
}
location ~ ^/api/(.+\.php)$ {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://myscrm-test-ydxs.gemdale.com;
}
location /ydxs {
root /srv/qw ;
try_files $uri $uri/ /ydxs/index.html ; #/ydxs/index.html防止二次刷新之后找不到页面
index index.html index.htm;
}
}
location /ydxs {
root /srv/qw ;
try_files $uri $uri/ @router ;
index index.html index.htm;
}
location @router {
rewrite ^.*$ /ydxs/index.html last;
}
等于
location / {
root /srv/qw、ydxs ;
try_files $uri $uri/ @router ;
index index.html index.htm;
}
location @router {
rewrite ^.*$ /index.html last;
}
等于
location /ydxs {
root /srv/qw ;
try_files $uri $uri/ /ydxs/index.html ;
index index.html index.htm;
}
为什么只展示server模块的代码呢?因为我们部署项目的所有配置全部在server模块里面。
nginx的配置分为三个层级第一层为http模块,在这层模块配置http的一些功能,如http响应头。
在http模块内部是server模块,在这层模块主要配置服务器的一些功能,如路由匹配,网站根目录,监听端口。
在server模块内部是location模块,location模块主要负责理由匹配后的处理,如代理服务器,重定向等等。
在第七行的root配置里,root指定了服务器的根目录,前端项目的文件就放在这个目录中。
第八行的location通过指令模式与客户端请求的URI相匹配,这里匹配了任何以 “/” 开始的查询。关于location指令的匹配规则,我会另写文章说明,这里略过,在这里大家只需知道,以/开头的路径都会匹配到这个location。
接下来,location指令里面使用了一个try_files指令,try_files指令的功能是按顺序检测文件的存在性,并且返回第一个找到的文件的内容,如果第一个找不到就会自动找第二个,依次查找。
举个简单的例子:
location /abc {
try_files /4.html /5.html @qwe;
--检测文件4.html和5.html,如果存在正常显示,不存在就去查找@qwe值
}
上面的location模块中使用了try_files指令,该指令会依次按顺序检测根目录中的4.html文件和5.html文件,如果存在就正常显示,不存在就去执行@xxx指令。
比如请求http://localhost/abc,服务器匹配到“/”后进入location,执行try_files指令,去root指定的根目录下查找4.html,如果查到则返回4.html内容,如果没有查找到,则继续去root根目录下查找5.html,如果有的话,返回5.html的内容,如果没有就执行@xxx指令。
那@xxx是什么意思呢?@关键字指定一个location段。通常和location一起使用。
用“location @xxx”定义一个location段,这个location段不能被外部请求所访问,只能用于nginx内部配置指令使用,比如 try_files、error_page。需要特别注意的是用@定义的location段只能在nginx内部所使用。
回过头来再看配置文件的第十行:
try_files $uri $uri/ @router;
路由匹配到“/"后会执行try_files指令,$uri是nginx的一个内部变量,指的是当前请求的路径。当用户请求 http://localhost/example 时,这里的 $uri 就是 /example。
try_files 会到root根目录里尝试找这个文件。如果存在就直接把这个文件的内容发送给用户。
如果目录中没有叫 example 的文件。然后就看 $uri/,增加了一个 /,也就是看有没有名为 example/ 的目录,又找不到就会 fall back 到 try_files 的最后一个选项,@router。@router指令发起一个内部 “子请求”,这个请求会匹配到location @router中,那么在location @router中又做了哪些操作呢?
location @router {
rewrite ^.*$ /index.html last;
}
这里执行了rewrite操作,那么rewrite指令有哪些功能呢?其主要功能就是使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写以及重定向。
这里需要注意rewrite对url进行重写指的是重写真实请求路径,如果是同域内,浏览器不会发生跳转,如果是非同域浏览器会发生跳转。
还有就是,rewrite只能放在server{},location{},if{}中,本文只讨论其放在location中的情形。
rewrite指令只能对域名后边的除去传递的参数外的字符串起作用,例如 http://seanlook.com/a/we/index.php?id=1&u=str 只对/a/we/index.php重写。
rewrite的使用语法为rewrite regex replacement [flag]。
regex是正则表达式,用于匹配URL,replacement是替换内容,flag是命令执行模式。
这个语法啥意思呢,在nginx程序触发rewrite指令,程序会去匹配正则regex,匹配成功后,将请求的url中的regex部分换成replacement,然后发送请求,将请求结果返回给客户端,然后根据flag执行下一步动作。
首先我们先验证一下,rewrite在同域内的使用情况。举个简单的例子,代码如下:
location / {
rewrite ^/test1 /test2 ;
}
location = /test2 {
return 200 "/test2";
}
我们访问:http://localhost/test1,结果如图:
虽然我们访问的是/test1但是结果返回的确实/test2,这说明nginx内部对我们的请求进行了重定向,但是浏览器不会感知到,其url不会发生变化。
再验证一下rewrite在处理非同域的情况,看代码:
location / {
rewrite ^/test1 "http://www.baidu.com" ;
}
2.工作中遇到的一个大坑,nginx代理到index.html,首次刷新访问正常,第二次刷新无法识别文件了,原因分析:(js css gif 是静态资源的后缀,不是文件夹的名字)反向代理的路径下找不到文件,需要单独指定js css文件的访问路径。
案列分析,按F12就可以查出类型,content-type application/javascript