nginx部署vue应用与spring-boot后台

前言

之前写过一篇关于nginx部署spring-boot的文章,这次再加上前端vue的部署,这样也算是整整齐齐了。

之前文章指路:阿里云CentOS-Nginx子域名转发-https访问-SpringBoot使用jar包部署一套完成!

添加子域名
  1. 登录云解析控制台
  2. 在主域名下添加记录解析即为子域名
  3. 这次分别是两个,一个是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的启动日志,自然是因为端口占用而启动失败的。


版权声明:本文为Sunsscode原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。