你会用nginx部署前端项目吗
前端项目的部署以前一直是把静态资源放到后端工程中,随后端部署一起部署。随着前后端分离开发模式的流行,前端项目可以单独部署了,目前最流行的方式使用nginx
来部署。
对于前端项目来说,nginx
主要有两个功能:
- 对静态资源做托管,即作为一个静态资源服务器;
- 对动态资源做反向代理,即代理后台接口服务,防止跨域;
路由配置
对nginx
配置最多就是路由配置,路由配置又有几种写法。
1. =
location = /111/ {
default_type text/plain;
return 200 "111 success";
}
location
和路径之间加了个 =
,代表精准匹配,也就是只有完全相同的 url
才会匹配这个路由。
在路径后面添加了aa
,那么就不是精确匹配了,所以是404
。
2. 不带 =
代表根据前缀匹配,后面可以是任意路径
location /222 {
default_type text/plain;
// 这里的 $uri 是取当前路径。
return 200 $uri;
}
3. 支持正则匹配~
// 匹配以/333/bbb开头,以.html结尾的路径
location ~ ^/333/bbb.*\.html$ {
default_type text/plain;
return 200 $uri;
}
上面的~
是区分大小写的,如果不区分大小写是~*
// 匹配以/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
语法一共有四种:
location = /aaa
是精确匹配/aaa
的路由;location /bbb
是前缀匹配/bbb
的路由。location ~ /ccc.*.html
是正则匹配,可以再加个*
表示不区分大小写location ~* /ccc.*.html
;location ^~ /ddd
是前缀匹配,但是优先级更高。
这 4 种语法的优先级是这样的:
精确匹配(=) > 高优先级前缀匹配(^~) > 正则匹配(~ / ~*) > 普通前缀匹配
root 与 alias
nginx
指定文件路径有两种方式root
和alias
,root
与alias
主要区别在于nginx
如何解释location
后面的uri
,这会使两者以不同的方式将请求映射到服务器文件上。
root
的处理结果是:root
路径 +location
路径;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
后面配置的路径丢弃掉,把当前匹配到的目录指向到指定的目录。
二级目录
有时候需要在一个端口下,部署多个项目,那么这时可以采用二级目录的形式来部署。
采用二级目录来部署会有一些坑,比如,当我请求 http://xxxxxxxx.com/views/basedata
的时候,浏览器自动跳转到了http://xxxxxxxxm:8100/store/views/basedata/
。
这是什么原因呢?
最根本的问题是因为http://xxxxxxxx.com/views/basedata
后面没有/
,所以就触发了nginx
的301
重定向,重定向到了http://xxxxxxxxm:8100/store/views/basedata/
,因此,只要避免触发重定向即可。
如果你能忍受直接使用如 http://xxxxxxxxm:8100/store/views/basedata/
这样最后带/
的地址,那也就没有什么问题了。
那为什么会触发重定向呢?
当用户请求 http.xxxxxx.cn/osp
时,这里的 $uri
就是 /osp
,nginx
会尝试到alias
或 root
指定的目录下找这个文件。
如果存在名为 {alias指定目录}/osp
的文件,注意这里是文件,不是目录,就直接把这个文件的内容发送给用户。
很显然,目录中没有叫 osp
的文件,于是就看 osp/
,增加了一个 /
,也就是看有没有名为 {alias指定目录}/osp/
的目录。
即,当我们访问 uri 时,如果访问资源为一个目录,并且 uri 没有以正斜杠 /
结尾,那么nginx
服务就会返回一个301跳转,目标地址就是要加一个正斜杠/
。
一种最简单的方式就是直接访问一个具体的文件,如 http.xxxxxx.cn/osp/index.html
,这样就不会发生重定向了。但是,这样方式不够优雅,每次都要输入完整的文件路径。
另一种方式是调整 nginx
中关于重定向的配置,nginx
重定向中的三个配置:absolute_redirect
、server_name_in_redirect
、port_in_redirect
。
absolute_redirect
通过该指令控制 nginx
发出的重定向地址是相对地址还是绝对地址:
1、如果设置为 off
,则 nginx
发出的重定向将是相对的,没有域名和端口
, 也就没有server_name_in_redirect
和port_in_redirect
什么事儿了。
加了这个配置后,尽管也会发生重定向,但是不会在路径上加上域名和端口
了。
2、如果设置为 on
,则 nginx
发出的重定向将是绝对的;只有 absolute_redirect
设置为 on
,server_name_in_redirect
和 port_in_redirect
的设置才有作用。
nginx
开启 gzip
静态压缩提升效率
gzip
是一种格式,也是一种 linux 下的解压缩工具,我们使用 gzip
对 app.js
文件压缩后,原始文件就变为了以.gz
结尾的文件,同时文件大小从 42571 减小到 11862。
目前,对静态资源压缩有两种形式:
- 动态压缩: 服务器在返回任何的静态文件之前,由服务器对每个请求压缩在进行输出。
- 静态压缩:服务器直接使用现成的扩展名为 .gz 的预压缩文件,直接进行输出。
我们知道 gzip
是 CPU
密集型的,实时动态压缩比较消耗 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
后缀的文件上传到服务器中即可。
2. 在 nginx 开启支持静态压缩的模块
在nginx
配置中加上如下配置:
gzip_static on;
如果不加的话,访问的时候就会找不到,报404错误,因为服务器只有.gz
的文件,没有原始文件。
总结
前端项目nginx
部署主要的配置基本上就是上面提到的这些。
首先是location
路由的四种写法;
接着就是分清楚root
和alias
的区别;
当项目较多时需要使用二级路由时,需要注意重定向的配置;
如果你的项目文件较大,可以开启gzip
作者:小p
来源:juejin.cn/post/7270902621065560120
压缩提升传输效率。