从业前端4年对于前端部署自然掌握一点,部署过许多静态网站、PHP站点、vue项目,每当要进行配置的时候总会耽误点时间,毕竟配置是低频的,部署才是高频,刚好手头比较闲也想写一些文档来提炼一下自己,如果能够帮助正在阅读的你,我也是倍感荣幸。虽然网上关于此类文章比比皆是,但是总是零零散散,掌握不到原理,下次配置时依旧需要度娘。
想必大家都查阅过资料,譬如:一个域名如何配置多个vue项目?nginx try_files 详解,nginx php代理转发等等,这些在我这篇文档当中基本都已涵盖,我不经常写文章,所以文笔不是很好,如果有什么说的不明白或者不好的请大家帮忙指出。
本文通过nginx配置vue项目的例子来帮助大家理解nginx的使用以及原理:
- nginx路由匹配规则与优先级
- nginx日志输出调试
- nginx重定向、代理转发
- nginx root和alias区别
- 真正的 nginx
try_files
详解 vue-router
的两种模式- 一个域名配置一个vue项目
- 一个域名配置多个vue项目
nginx 路由匹配规则与优先级
通常我们所说的nginx路由匹配其实就是 nginx location匹配,下面我们简单进行介绍:
location路由匹配规则
命令 | 说明 |
---|---|
~ | 波浪线表示执行一个正则匹配,区分大小写 |
~* | 执行一个正则匹配,不区分大小写 |
^~ | 普通字符匹配,如果该选项匹配,只匹配该选项,不匹配别的选项,一般用来匹配目录 |
= | 普通字符精确匹配 |
@ | "@" 定义一个命名的 location,使用在内部定向时,例如 error_page, try_files |
示例:
#精准匹配
location = / {
#只匹配www.xxx.com
}
location / {
#匹配任何URI
}
nginx 路由匹配优先级
看过官方文档或者实践过的同学都知道,location匹配规则不是从上往下按顺序匹配的,而是根据nginx匹配规则来匹配的。比如:你医院排队挂号时有老人、军人以及军属优先挂号的规则。
下面为nginx 路由匹配规则:
-
=前缀的指令严格匹配这个查询。如果找到,停止搜索。
-
所有剩下的常规字符串,最长的匹配。如果这个匹配使用^〜前缀,搜索停止。
-
正则表达式,在配置文件中定义的顺序。
-
如果第3条规则产生匹配的话,结果被使用。否则,使用第2条规则的结果。
nginx日志输出调试
在我们设置了 location 匹配规则之后,不确定自己的匹配是否生效时,可以尝试使用nginx的access_log
来输出指定log_format
模板日志。由于只做调试使用,我们选择使用nginx默认的main
模板,如果感兴趣的朋友,可以自己去查阅相关文档。
首先,确认设置nginx规则之后是否重启nginx服务。
其次,确认无误之后在我们设置的nginx location规则里面,利用access_log
输出日志。示例如下:
http {
...
#日志模板 main
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
server {
...
location /ar-meet {
#输出日志,日志文件保存在/val/log/nginx/access1.log,使用的是main的日志模板(默认的)
access_log /var/log/nginx/access1.log main;
...
}
}
}
最后,使用 tail
命令查看是否有日志输出,从而来判断是否进入匹配的规则中,如果刷新浏览器有日志输出,则说明匹配成功进一步排查问题,反之未匹配成功,检查规则正则是否正确。
tail -f /val/log/nginx/access1.log
nginx重定向、代理转发
下面我们将以几个例子开讲解 nginx重定向 和 nginx代理转发。
以HTTPS站点为例:
- nginx重定向,当用户访问 HTTP站点时,我们需要重定向至 HTTPS的站点上。
- HTTPS 代理转发,当我们的服务不支持HTTPS时,我们可以利用HTTPS代理转发至HTTP服务上。
在创建https站点之前,我们需要先创建 SSL
证书,再将证书放到服务器上。此处不着重介绍SSL
证书,请自行百度,如果有阿里云服务器可以在阿里云后台购买免费的证书。
nginx重定向
server {
listen 80;
server_name www.xxx.com xxx.com;
#重定向https
rewrite ^(.*)$ https://$host$1 permanent;
}
HTTPS 代理转发
server {
listen 443;
server_name www.xxx.com xxx.com;
index index.html;
#ssl证书配置
ssl on;
ssl_certificate /usr/local/nginx_ssl/www.xxx.com.pem;#配置ssl证书
ssl_certificate_key /usr/local/nginx_ssl/www.xxx.com.key;#配置ssl证书
ssl_session_timeout 5m;
location / {
#代理转发,当用户访问https://www.xxx.com/yourapi/getInfo时
#实际访问的是 http://xx.xx.xx.xx:6666/yourapi/getInfo
if ($request_uri ~ ^/yourapi(/)?.*){
proxy_pass http://xx.xx.xx.xx:6666$request_uri;
}
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
nginx root和alias区别
通过以上配置,我们分别使用了root
和alias
指定静态资源目录,我们可以看出两者的区别:
root实例:
location /ar-meet {
root /home/www/;
}
当请求URI为 www.xxx.com/ar-meet/a.html
nginx会返回 /home/www/ar-meet/a.html
文件。
alias实例:
location /ar-call {
alias /home/www/ar-call/dist/;
}
当请求URI为 www.xxx.com/ar-call/a.html
nginx会返回 /home/www/ar-call/dist/a.html
文件,如果此处不是alias 而是 root,那么nginx 返回 /home/www/ar-call/dist/ar-call/a.html
总结:alias 会忽略location后面的路径,而root只是更改根目录指向。
nginx try_files
精解
如果你没有动力看下去,或者觉得很难看下去,那么先看这一句话然后再慢慢看下去。其实它就是重定向,按照这个思路往下阅读。
try_files 按顺序检查文件是否存在,返回第一个找到的文件。它提供三个参数:
参数 | 说明 |
---|---|
$url | 代表nginx会去指定路径(root或alias)中查找文件,如果找到则返回该文件,否则继续匹配第二个参数。 |
$url/ | 如果第一个参数没有找到文件,则会在路径后面添加一个/ ,继续查询,同样找到文件返回该文件,否则重定向到最后一个参数。 |
重定向URL | 以上都不符合要求时,重定向至指定页面,比如:=404 ,通过以上两个例子,我们来分析一下 try_files; |
例子:
假设请求URI为 demos.xxx.com/ar-meet
location /ar-meet {
root /home/www/;
#在重置root根目录之后,此时nginx指向了`/home/www/ar-meet`
#由于当前location继承http的 `index` 属性,即:index index.html;
#默认打开html文件,也就是说此时nginx指向了 `/home/www/ar-meet/index.html`
}
假设请求URI为 demos.xxx.com/ar-meet/meet/123
location /ar-meet {
root /home/www/;
#在重置root根目录之后,此时nginx指向了`/home/www/ar-meet`
#但是在ar-meet的目录里找不到meet
#因此nginx会返回404
try_files $url $urs/ /ar-meet/index.html;
#重定向至demos.xxx.com/ar-meet/index.html;
}
vue-router的两种模式
为什么vue-router
的 history 模式需要配置,而 hash 模式则不需要呢?因为history
模式利用HTML5 historyAPI来完成URL跳转,而hash则是监听hash变化,除此之外我们经常使用hash来防止浏览器跳转。
下面不妨我们来测试一下这两种模式:
1. hash模式
由于 hash
模式为vue-router
默认模式,所以我们无需配置,直接在main.js
中监听hash变化事件。
window.addEventListener('hashchange', (e) => {
console.log('hash值发生了改变 ', e);
}, false);
2. history模式
首先,我们需要将vue-router
的模式改为history
模式。
const router = new VueRouter({
mode: 'history',
routes: [...]
})
同样,我们在main.js
中监听HTML5History变化事件:
window.addEventListener('popstate', function(e) {
console.log('HTML5History路由变化了', e);
}, false);
vue是个单页面应用,通过解析URL的hash或者通过 history的 API 来实现页面跳转和渲染。
一个域名配置一个项目
单项目配置比较简单,所以我们直接上代码。参考官方配置。
server {
listen 443;
server_name www.xxx.com xxx.com;
index index.html;
ssl on;
ssl_certificate /usr/local/nginx_ssl/www.xxx.com.pem;#配置ssl证书
ssl_certificate_key /usr/local/nginx_ssl/www.xxx.com.key;#配置ssl证书
ssl_session_timeout 5m;
location / {
#project为项目目录,我们将build之后的目录
root /usr/share/nginx/html/project;
try_files $uri $uri/ /index.html;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
一个域名配置多个vue项目
在开始配置之前,我们来看看如何分配这些路由:
域名URL | Vue 项目 | Demo |
---|---|---|
demos.xxx.com | 重定向 | 访问demos.anyrtc.io 将会重定向 至 www.anyrtc.io/demo |
demos.xxx.com/ar-meet | ar-meet | demos.anyrtc.io/ar-meet/ |
demos.xxx.com/ar-call | ar-call | demos.anyrtc.io/ar-call/ |
... | ... |
要实现一个域名配置多个项目,我们需要用到:
- nginx location匹配:字符串匹配 和 精准匹配
- vue 项目配置
publicPath
属性,此处以vue-cli@3.0
为例,如果是2.0需要设置vue-router的base
属性,以及更改webpack中,静态资源的路径前缀。最好通过vue脚手架3.0构建项目。
vue项目配置及打包
更改根目录的vue.config.js
的publicPath
属性,该属性不仅为打包之后静态资源的前缀,也是路由的前缀。如果根目录没有vue.config.js
请自行创建。
下面以ar-meet为例:
//vue.config.js
module.exports = {
lintOnSave: false,
publicPath: "/ar-meet/"
};
本地测试npm run serve
可以发现,我们的站点的url前面多了一个/ar-meet/
。示例:
publicPath | 首页 | 静态资源 |
---|---|---|
/ | www.xxx.com | www.xxx.com/css/a.css |
/ar-meet/ | www.xxx.com/ar-meet | www.xxx.com/ar-meet/css/a.css |
配置完publicPath
之后,我们将项目编译打包npm run build
。
nginx location配置
根据我们分配的路由,我们添加三个location匹配,示例:
server {
listen 443;
server_name demos.xxx.com;
index index.html;
#这里为你的项目目录
root /home/www;
ssl on;
ssl_certificate /usr/local/nginx_ssl/www.xxx.com.pem;#配置ssl证书
ssl_certificate_key /usr/local/nginx_ssl/www.xxx.com.key;#配置ssl证书
ssl_session_timeout 5m;
#精准匹配,重定向至https://www.xxx.com/demo
#可以根据自己的需要来调整,比如换成一个vue项目
location = / {
rewrite ^.*$ https://www.xxx.com/demo;
}
#字符串 /ar-meet 匹配
location /ar-meet {
#输出日志,检查是否匹配成功
access_log /var/log/nginx/access1.log main;
#利用root指定资源
#创建ar-meet目录,将vue编译之后dist目录下面的文件放置到该目录下面,非dist目录
root /home/www/;
try_files $uri $uri/ /ar-meet/index.html;
}
#字符串 /ar-call 匹配
location /ar-call {
#利用alias指定资源
#直接将vue编译之后的dist目录放到ar-call的目录下面
alias /home/www/ar-call/dist;
try_files $uri $uri/ /ar-call/index.html;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
简单的总结一下:
nginx 使用 access_log
输出日志来检查location路由是否匹配成功,添加location 路由匹配规则,利用root或alias指定资源路径,使用try_files
重定向至vue项目的index.html入口文件。