使用 Nginx 部署 Vue 项目

Vue 项目在 build 之后通常都需要部署到服务器才能够访问,本文介绍如果使用 Nginx 部署 Vue 项目

更多精彩

首先需要说明可能存在的误区

  1. 我这个项目是使用的 Vue + SpringBoot 实现前后分离的项目
  2. 也就是说在部署时,前端和后端要分别单独部署,前端通过请求后端的接口实现数据交互
  3. 一开始我是打算将 build 后的 Vue 项目直接放到 Tomcat 的 /webapps/ 目录中,然后启动 Tomcat
  4. 后端由于是 SpringBoot ,所以不打算借助 Tomcat ,会直接通过 java -jar xxx.jar 启动
  5. 由于前后端分别使用了不同的服务部署,两者之间会出现端口号不一致的情况
  6. 这个时候就需要使用 Nginx 来实现代理转发,所以我就准备 使用 Nginx 将部署在 Tomcat 中的前端项目发出的请求代理转发到通过 SpringBoot 单独启动的后端项目中
  7. BUT ,这个思路实际上是 不行的!!!
  8. 因为比如部署前端项目的 Tomcat ,使用的端口号是 8082 ,那么前端项目的访问地址就会是 http://192.168.7.8:8082/teamnote/#/ ,与之对应的从前端项目发送出去的请求,比如请求任务列表就会是 http://192.168.7.8:8082/teamnote/api/tasks
  9. 后端项目由于是通过 SpringBoot 单独启动,其接收任务列表请求的接口就会是 http://192.168.7.8:2592/teamnote/api/tasks
  10. 如果使用 Nginx ,理所应当的我认为是监听 8082 端口,然后将 /teamnote/api/ 开头的请求转发到 http://192.168.7.8:2592/teamnote/api/
  11. 看上去好像没毛病,但当在 Nginx 的 nginx.conf 中改完保存并重启时,则会抛出以下错误
1
.... 0.0.0.0:8082 failed (98: Address already in use)
  1. 这是因为,8082 端口已经被部署了前端项目的 Tomcat 使用了,Nginx 无法监听一个已经被使用的端口,所以上述好像没啥毛病的部署思路,全是错的!!! ,这让我在一条死胡同里耗了一个多小时

正确的部署方式

  1. 既然是使用 Nginx 部署项目,那么就应该直接将 Vue 项目部署到 Nginx 的服务目录,因为 Nginx 和 Tomcat 一样,都是服务器

将打包好的前端项目文件放到指定目录中

  1. 一开始我会想要把打包后的项目文件放到 Nginx 默认的目录,但这样实际上是不好的,项目文件完全可以放在单独的目录中方便统一管理,如下图
    • asl-teamnote-1.0.jar 是打包好的后端项目包
    • run-backend.sh 是后端项目包的一键启动脚本
    • teamnote 则是将前端项目 build 之后的 dist 目录改名后的文件目录

修改 Nginx 配置,指向上述目录

  1. 一般来说就是修改 Nginx 的默认配置文件 nginx.conf 即可,但不推荐这么做,既然上面使用了单独的目录管理项目文件,那么这里也推荐创建单独的 Nginx 配置文件来管理此项目的 Nginx 配置
  2. 在 Nginx 的默认配置文件 nginx.conf 中,最后一行写着 include /etc/nginx/conf.d/*.conf;
  3. 这说明只要是该目录下文件后缀为 conf 的文件都会被自动加载到 Nginx 配置中
  4. 所以可以前往该目录,创建此项目的配置文件,例如 asing1elife.conf ,如下图

编写自定义的 Nginx 配置文件

  1. 具体配置方式参考自
server {
    # 需要被监听的端口号,前提是此端口号没有被占用,否则在重启 Nginx 时会报错
    listen       8888;
    # 服务名称,无所谓
    server_name  localhost;

    # 上述端口指向的根目录
    root /opt/asing1elife/teamnote;
    # 项目根目录中指向项目首页
    index index.html;

    client_max_body_size 20m; 
    client_body_buffer_size 128k;

    # 根请求会指向的页面
    location / {
      # 此处的 @router 实际上是引用下面的转发,否则在 Vue 路由刷新时可能会抛出 404
      try_files $uri $uri/ @router;
      # 请求指向的首页
      index index.html;
    }

    # 由于路由的资源不一定是真实的路径,无法找到具体文件
    # 所以需要将请求重写到 index.html 中,然后交给真正的 Vue 路由处理请求资源
    location @router {
      rewrite ^.*$ /index.html last;
    }

    # 关键步骤,这里表示将所有的 http://192.168.7.8:8888/teamnote/api/ 开头的请求都转发到下面 proxy_pass 指定的链接中
    # 这里使用 /teamnote/api/ 而不是 /teamnote/ ,是因为前端项目本身的访问链接就是 http:192.168.7.8:8888/teamnote/
    # 为了防止在访问页面时请求就被 Nginx 代理转发,这里需要更具体的配置,才能和前端访问请求区分开
    location /teamnote/api/ {
          # 后端的真实接口
          proxy_pass http://192.168.7.8:2592/teamnote/api/;
          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_set_header   Cookie $http_cookie;
          # for Ajax
          #fastcgi_param HTTP_X_REQUESTED_WITH $http_x_requested_with;
          proxy_set_header HTTP-X-REQUESTED-WITH $http_x_requested_with;
          proxy_set_header HTTP_X_REQUESTED_WITH $http_x_requested_with;
          proxy_set_header x-requested-with $http_x_requested_with;
          client_max_body_size 10m;
          client_body_buffer_size 128k;
          proxy_connect_timeout 90;
          proxy_send_timeout 90;
          proxy_read_timeout 90;
          proxy_buffer_size 128k;
          proxy_buffers 32 32k;
          proxy_busy_buffers_size 128k;
          proxy_temp_file_write_size 128k;
    }
}

重新启动 Nginx

  1. 使用 nginx -s reload 可以重新加载 Nginx 的配置文件,但如果配置文件有错,不一定会抛出异常
  2. 使用 nginx -s stop 先停止 Nginx 服务,再使用 nginx 尝试启动 Nginx 服务,如果配置文件有异常,则会抛出异常告知启动失败

更新前端项目包

  1. 将更新后的前端项目打包,直接传到之前的前端文件目录即可,Nginx 不需要重启