前言
之前写过一篇关于nginx部署spring-boot的文章,这次再加上前端vue的部署,这样也算是整整齐齐了。
之前文章指路:阿里云CentOS-Nginx子域名转发-https访问-SpringBoot使用jar包部署一套完成!
添加子域名
- 登录云解析控制台
- 在主域名下添加记录解析即为子域名
- 这次分别是两个,一个是vue的(xinqiao.nevercome.net),还有一个是spring-boot的(xinqiaoapi.nevercome.net)
vue的打包
vue的打包要注意两点:
1 publicPath
publicPath虽然说是可以带子路径的,就比如说你用tomcat来部署,放在了webapps里面,那么目录的名称就是访问路径的子路径,比如说(www.nevercome.net/xinqiao)但是这里面有不少坑点,这和vue-router有点不太搭,如果vue-router的路由是后台动态拉取的总是会把配置的子路径给吞掉,目前我也没有找到好的处理方式,那么最好就是避免带上子路径,而且带着子路径的访问域名也不好看,远不如二级域名来得简洁直观。
也就是说理论上可以这样:
module.exports = {
// 部署生产环境和开发环境下的URL。
// 默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上
// 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl(publicPath) 为 /admin/。
publicPath: process.env.NODE_ENV === "production" ? "/xinqiao/" : "/",
utputDir: 'dist'
// others...
}
但最好还是这样,以避免vue-router的bug
module.exports = {
publicPath: process.env.NODE_ENV === "production" ? "/" : "/",
utputDir: 'dist'
// others...
}
2 axios的baseURL
在开发环境下,也就是npm run dev,webpack是会提供一个devServer的,它可以根据配置来转发请求。就比如说这样子的配置:
devServer: {
host: '0.0.0.0',
port: port,
proxy: {
// detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VUE_APP_BASE_API]: {
target: `http://localhost:8095`,
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''
}
}
},
disableHostCheck: true
}
但是当build之后,vue项目被webpack打包成了纯静态文件,你需要把它部署在服务器上才可以被访问,这个时候也不存在devServer,那么你的axios的请求应该直达后台服务器,配置是这样子的:
const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: process.env.NODE_ENV === 'production' ? 'https://xinqiaoapi.nevercome.net/' : process.env.VUE_APP_BASE_API,
// 超时
timeout: 10000
})
nginx部署vue
因为项目用的是ruoyi-vue进行的二次开发,所以这里的nginx配置也是参考了官方文档中给出的配置方式,它是完全正确的。我自己的是https部署的,下面是相关部分的配置文件,它被include在nginx.conf中。当你的nginx部署了多个应用站点的时候,我也推荐你使用这样子的配置方式:
server {
listen 443 ssl;
server_name xinqiao.nevercome.net;
ssl_certificate /etc/letsencrypt/live/xinqiao.nevercome.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/xinqiao.nevercome.net/privkey.pem;
ssl_session_cache shared:SSL:10m;
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;
location / {
root /usr/local/spring-boot/xinqiao/vue/dist;
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
location /prod-api/ {
proxy_pass http://localhost:8095;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 80;
server_name xinqiao.nevercome.net;
return 301 https://xinqiao.nevercome.net$request_uri;
}
其中server_name就是配置的二级域名。
里面配置了两个location,一个是根路径,这代表了所有的落在vue上的请求,root指向的是vue打包后目录;/prod-api/一般都是图片的访问请求,这个会通过代理转发到本地的后台,与axios直接请求后台的域名是不一样的。
3 题外话
把build后的vue放到云服务器上,可以在本地用 tar -zcvf dist.tar.gz ./dist
打包之后发送到云服务器上,再解压缩 tar zxvf dist.tar.gz
为了复制上面的nginx的配置文件,vim把内容复制到vim之外又比较麻烦,我就直接把配置文件sz xinqiao.conf了下来,不是那么合理。
nginx设置允许跨域
因为spring-boot后台用nginx设置代理转发的内容在上一篇文章中已经写过了,所以这里不再复述,只讲一下会遇到的跨域问题。
很明显,前端项目所在的域名是xinqiao.nevercome.net , 而后台所在的域名是xinqiaoapi.nevercome.net,浏览器访问肯定会有跨域问题,你可以在应用层面解决跨域问题,比如说加上@CrossOrigin注解,像这样:
@CrossOrigin(origins = "https://xinqiao.nevercome.net", maxAge = 3600)
当然也可以通过nginx解决,只要在配置文件里面添加几个add_header字段即可,配置文件主要内容如下:
location / {
add_header 'Access-Control-Allow-Origin' 'https://xinqiao.nevercome.net' always;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' '*';
proxy_pass http://localhost:8095;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
这里需要注意的是不能nginx配置了允许跨域,后台应用也设置了允许跨域,这样子的话浏览器就会报 multiple values 错误了。
其他问题
1 出现了405
这里要注意的是,就我自己这个项目而言正确配置部署的话是不会出现这个问题的,早期出现这个是因为我在axios的baseURL里面错填了前端的域名,也就是填成了https://xinqiao.nevercome.net,这才造成了报405问题。
如果真的配置和部署都正确还是405的话,处理也比较简单,只要添加一句error_page 405 =200 $uri;配置即可:
location / {
root /usr/local/spring-boot/xinqiao/vue/xinqiao_v3;
error_page 405 =200 $uri;
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
2 惨痛的教训
一般来说非常诡异的bug都是很小的一个疏忽导致的,这次我再次遇到了这种情况,事情是这样子的:
在我的这个服务器上还有一个ruoyi开发的项目,这个项目配置了两个版本,一个spring-boot后台端口是8090,另一个是8091.
当我部署这个新的项目的时候,我给它分配的后台启动端口是8091,很明显和服务器上的重复了,但在最开始的时候我并没有意识到。
我一如既往地用nohup命令启动jar,启动之后我检查了一下8091端口的监听情况,注意这里我没有去看启动日志,而是检查端口是否被java应用监听了,非常遗憾的,原先8091端口就是被别的spring-boot应用占用着的,我检查端口是否被监听当然可以看到是正在被监听的,而我想要部署的这个应用却是因为端口占用而启动失败的。
后续的配置我也都是按照后台成功部署在8091端口上来操作的了,两个ruoyi项目上又恰好在登录接口上有一点差异,测试的时候报错就让我摸不着头脑,不过还好它们有差异,不然我就该去检查数据库了。
当我突然回想起另一个项目是有两个端口监听的时候,其中一个是8090,那另外一个是…自然就是8091了。
这时候我再去看nohup的启动日志,自然是因为端口占用而启动失败的。