你会用nginx部署前端项目吗

3,854 阅读4分钟

前端项目的部署以前一直是把静态资源放到后端工程中,随后端部署一起部署。随着前后端分离开发模式的流行,前端项目可以单独部署了,目前最流行的方式使用nginx来部署。

对于前端项目来说,nginx主要有两个功能:

  • 对静态资源做托管,即作为一个静态资源服务器
  • 对动态资源做反向代理,即代理后台接口服务,防止跨域

路由配置

nginx配置最多就是路由配置,路由配置又有几种写法。

1. =

location = /111/ {
    default_type text/plain;
    return 200 "111 success";
}

location 和路径之间加了个 =,代表精准匹配,也就是只有完全相同的 url 才会匹配这个路由。

image.png

在路径后面添加了aa,那么就不是精确匹配了,所以是404

image.png

2. 不带 =

代表根据前缀匹配,后面可以是任意路径

location /222 {
    default_type text/plain;
    // 这里的 $uri 是取当前路径。
    return 200 $uri;
}

image.png

3. 支持正则匹配~

// 匹配以/333/bbb开头,以.html结尾的路径
location ~ ^/333/bbb.*\.html$ {
    default_type text/plain;
    return 200 $uri;
}

image.png

但是它是区分大小写的,比如这样就不行了:

image.png

换成小写就可以:

image.png

如果想让正则不区分大小写,可以再加个 *

// 匹配以/333/bbb开头,以.html结尾的路径
location ~* ^/333/bbb.*\.html$ {
    default_type text/plain;
    return 200 $uri;
}

4. ^~代表优先级

下面的配置有两个路径是以/444开头的:

location ~* ^/444/AAA.*\.html$ {
    default_type text/plain;
    return 200 $uri;
}
location ~ /444/ {
    default_type text/plain;
    return 200 $uri;
}

如果访问/444/AAA45.html,就会直接命中第一个路由,如果我想命中/444/呢? 加上^~就好了。

注意是^~, 不是^

location ^~ /444/ {
    default_type text/plain;
    return 200 $uri;
}

也就是说 ^~ 能够提高前缀匹配的优先级。

总结一下,location 语法一共有四种:

  1. location = /aaa 是精确匹配 /aaa 的路由;

  2. location /bbb 是前缀匹配 /bbb 的路由。

  3. location ~ /ccc.*.html 是正则匹配,可以再加个 * 表示不区分大小写 location ~* /ccc.*.html;

  4. location ^~ /ddd 是前缀匹配,但是优先级更高。

这 4 种语法的优先级是这样的:

精确匹配(=) > 高优先级前缀匹配(^~) > 正则匹配(~ / ~*) > 普通前缀匹配

root 与 alias

nginx指定文件路径有两种方式rootaliasrootalias主要区别在于nginx如何解释location后面的uri,这会使两者以不同的方式将请求映射到服务器文件上。

  1. root的处理结果是:root路径 + location路径;
  2. alias的处理结果是:使用alias路径替换location路径;

alias是一个目录别名的定义,root则是最上层目录的定义。

需要注意的是alias后面必须要用/结束,否则会找不到文件的,而root则可有可无。另外,alias只能位于location块中。

root示例:

location ^~ /test/ {
    root /www/root/html/;
} 

如果一个请求的 uri 是 /test/a.html时,web服务器将会返回服务器上的/www/root/html/test/a.html的文件。

alias示例:

location ^~ /test/ {
    alias /www/root/html/new_test/;
}

如果一个请求的 uri 是 /test/a.html 时,web服务器将会返回服务器上的/www/root/html/new_test/a.html的文件。

注意, 这里是new_test,因为alias会把location后面配置的路径丢弃掉,把当前匹配到的目录指向到指定的目录。

二级目录

有时候需要在一个端口下,部署多个项目,那么这时可以采用二级目录的形式来部署。

假设所有前端项目放在 /usr/share/nginx/html 下(Nginx 默认静态文件目录)

mkdir -p /usr/share/nginx/html/project1 # 项目1目录(对应二级目录 /project1) 
mkdir -p /usr/share/nginx/html/project2 # 项目2目录(对应二级目录 /project2)

将两个项目的打包后的 dist 文件分别放入对应目录, 例如:project1 的 dist 内容复制到 /usr/share/nginx/html/project1, project2 的 dist 内容复制到 /usr/share/nginx/html/project2。

编辑 Nginx 的配置文件(通常路径:/etc/nginx/nginx.conf/etc/nginx/conf.d/default.conf),核心配置如下:

# 配置项目1:访问 http://IP/project1 时指向 project1 目录
location /project1 {
    # 1. 指定项目1的静态文件根目录
    root   /usr/share/nginx/html;
    # 2. 启用索引文件(index.html)
    index  index.html index.htm;
    # 3. 解决前端路由刷新404问题(history模式)
    try_files $uri $uri/ /project1/index.html;
}

# 配置项目2:访问 http://IP/project2 时指向 project2 目录
location /project2 {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /project2/index.html;
}

# 可选:默认访问根路径时跳转至某个项目(如 project1) 
location / { 
  rewrite ^/$ /project1 permanent; 
}

如果前端项目直接打包部署,会出现静态资源路径错误,需要根据框架适配,修改 vite.config.js 配置 base 为二级目录名:

import { defineConfig } from 'vite' 
import vue from '@vitejs/plugin-vue' 
export default defineConfig({ 
plugins: [vue()], 
// 关键:配置二级目录(project1 对应 Nginx 的 /project1) 
base: '/project1/'
})

nginx 开启 gzip 静态压缩提升效率

gzip 是一种格式,也是一种 linux 下的解压缩工具,我们使用 gzipapp.js 文件压缩后,原始文件就变为了以.gz结尾的文件,同时文件大小从 42571 减小到 11862。

image.png

目前,对静态资源压缩有两种形式:

  • 动态压缩: 服务器在返回任何的静态文件之前,由服务器对每个请求压缩在进行输出。
  • 静态压缩:服务器直接使用现成的扩展名为 .gz 的预压缩文件,直接进行输出。

我们知道 gzipCPU 密集型的,实时动态压缩比较消耗 CPU 资源。为进一步提高 nginx 的性能,我们可以使用静态 gzip 压缩,提前将需要压缩的文件压缩好,当请求到达时,直接发送压缩好的.gz文件,如此就减轻了服务器 CPU 的压力,提高了性能。

因此,我们一般采用静态压缩的方式,实现静态压缩有以下两个步骤:

1. 生成gzip压缩文件

在利用webpack打包的时候,我们就把文件进行压缩,配置如下:

const isProduction = process.env.NODE_ENV === 'production'

if (isProduction) {
  config.plugins.push(
    new CompressionWebpackPlugin({
      // 采用gzip进行压缩
      algorithm: 'gzip',
      test: /\.js$|\.html$|\.json$|\.css/,
      threshold: 10240
    })
  )
}

可以看到,多生成了一个以.gz结尾的文件,然后把.gz后缀的文件上传到服务器中即可。

image.png

2. 在 nginx 开启支持静态压缩的模块

nginx配置中加上如下配置:

gzip_static on;

如果不加的话,访问的时候就会找不到,报404错误,因为服务器只有.gz的文件,没有原始文件。

总结

前端项目nginx部署主要的配置基本上就是上面提到的这些。

首先是location路由的四种写法;

接着就是分清楚rootalias的区别;

当项目较多时需要使用二级路由时,需要注意重定向的配置;

如果你的项目文件较大,可以开启gzip压缩提升传输效率。