nginx 部署 vue 笔记

Vue 项目写完后,打包并且使用 Nginx 部署测试打包程序的 dist,同时反向代理后端 API 域名以解决跨域。

解决跨域:

开发环境中配置的跨域在将项目打包为静态文件时是没有用的 ,需要用 nginx 通过反向代理的方式解决这个问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 工作模式与连接数上限
events {
   ...
}

# 设定http服务器
http {

    ...

    server {
        listen       8080; # 默认端口是 80,如果端口没被占用可以不用修改
        server_name  localhost;
        root        /Users/owenliu//xxxxxx/dist; # vue 项目的打包后的 dist

        location / {
            try_files $uri $uri/ @router; # 需要指向下面的 @router 否则会出现 vue 的路由在 nginx 中刷新出现 404
            index  index.html index.htm;
        }
        # 对应上面的 @router,主要原因是路由的路径资源并不是一个真实的路径,所以无法找到具体的文件
        # 因此需要 rewrite 到 index.html 中,然后交给路由在处理请求资源
        location @router {
            rewrite ^.*$ /index.html last;
        }

        location /apis {
            rewrite    ^/apis/(.*) /$1 break;  # 重写 URI
            proxy_pass http://localhost:8081; # 代理接口地址
        }
    }

    # .......其他部分省略
}

  1. root /Users/owenliu/xxxxxx/dist; 的含义,这里配置的路径 /Users/owenliu//xxxxxx/dist是我当前将 vue 文件打包后存放在 liunx 下的路径 ,可以通过 `http://localhost:8080/ 访问到 vue 打包的静态文件。

  2. location /apis 指拦截以 /apis 开头的请求,http请求格式为 http://localhost:8080/apis/***?page=1&size=10,。

  3. proxy_pass http://localhost:8081; 当拦截到需要处理的请求时,将拦截请求代理到的接口地址。
  4. rewrite, 这里是重写 URL,当拦截请求时,URI 回原样转到代理地址,也就是说请求地址为 http://localhost:8081/apis/***?page=1&size=10, 如果要像把 /apis 去掉,需要配置 rewrite ^/apis/(.*) /$1 break;, ⚠️注意这里不能配置成 rewrite ^/apis/ / break;,转发效果会是 http://localhost:8081/?page=1&size=10

参考链接:https://juejin.im/post/5b4489016fb9a04f8d6ba269

静态文件失效

  • 组件效果不显示

    显示内容:

    ngxin_dist_static_failed

    F12 报错:

    image-20190228141145847

    添加以下配置就好了

    1
    2
    3
    4
        # 文件扩展名与文件类型映射表
        include       mime.types;
        # 默认文件类型
        default_type  application/octet-stream;
    
  • 图标不显示:

    被误导了,之前由于不知道是 nginx 配置的问题导致的,所以按照网上的博客说的, 把 assetsPublicPath 的 / 改为 ./

    1
    2
        assetsSubDirectory: 'static',
        assetsPublicPath: './',
    

    图标不显示,我又改回原来的 / 就好了, 这里不用动原来的默认配置。

Docker 部署前端

  1. vhost 反向代理(xxxxxx.conf) /data/server/nginx/conf/vhosts

    服务器的 nginx 会根据 server_name 反向代理到相应的 url

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    server {
        listen  80;
        server_name xxxx.com;
    
        access_log /data/log/nginx/xxxxx.com.access.log main;
        error_log /data/log/nginx/xxxxx.com.error.log error;
    
        location / {
            proxy_pass http://localhost:6501;
        }
    }
    
  2. 修改本地 hosts 文件

    1
    sudo echo 'ip xxxx.com' >> /etc/hosts
    
  3. 挂载到容器的 ngxin.conf, 放到 vue 项目的 build 目录下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    user  nginx;
    worker_processes  1;
    
    error_log  /dev/stderr warn;
    pid        /var/run/nginx.pid;
    
    events {
        worker_connections  1024;
    }
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
    
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  /dev/stdout  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        keepalive_timeout  65;
    
        gzip  on;
        gzip_types application/javascript image/* text/css;
        server {
            listen 6501;
            root /usr/share/nginx/html;
            index index.html;
    
            location / {
                try_files $uri $uri/ @router;
                index  index.html index.htm;
            }
    
            location @router {
                rewrite ^.*$ /index.html last;
            }
    
            location ~* \.(jpg|jpeg|png|gif|ico|svg)$ {
                expires 30d;
            }
    
            location ~* \.(css|js)$ {
               expires 7d;
            }
    
            location /apis {
                rewrite    ^/apis/(.*)$ /$1 break;  # 重写 URI
                proxy_pass http://localhost:8081; # 代理接口地址
            }
        }
        include /etc/nginx/conf.d/*.conf;
    }
    
  4. Dockerfile 放在 vue 项目的根目录

    1
    2
    3
    4
    FROM nginx:1.15-alpine
    
    COPY dist /usr/share/nginx/html
    COPY build/nginx.conf /etc/nginx/nginx.conf
    

    构建 docker image

    1
    2
    3
     // -t 指定了镜像 tag 为 docker-vue:v1.0.0
     // . 代表着当前目录
     docker build -t docker-vue:v1.0.0 .
    

    启动容器

    1
    2
     // -d 后台运行容器,并返回容器ID
     docker run -p 88:80 -d docker-vue:v1.0.0
    
  5. 本地浏览器访问 http://xxxx.com

⚠️注:这里有个小插曲,由于刚接触前端,不太清楚运行流程,本来我以为前浏览器访问前端,前端在请求后端 API 时是前端的后台 Docker 容器进程发送的请求,然而,并不是这样的,后端的请求也是在浏览器发出的,所以 vhost 配置需要加入后端服务的反向代理, + 号部分为添加的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server {
    listen  80;
    server_name xxxx.com;

    access_log /data/log/nginx/xxxx.com.access.log main;
    error_log /data/log/nginx/xxxx.com.error.log error;

    location / {
        proxy_pass http://localhost:6501;
    }

+    location /apis {
+        rewrite    ^/apis/(.*)$ /$1 break;
+        proxy_pass http://localhost:8081;
+    }
}