万字前端效率大提速系列 🚀 :八、前端需要了解的运维部署工具

711 阅读6分钟

项目开发完之后,就该把项目部署到服务器上了。有的小伙伴可能会想,这不是运维同学干的事儿吗,跟我有啥关系。是一定有关系的,我们需要提供足够的部署信息才能顺利上线。这里从部署工具来了解部署准备和部署过程

Nginx

nginx 是当下最流行的反向代理服务器,它的功能就像一个服务器方的管家。用户发送一个请求到服务器端,通常是 nginx 先收到请求,根据请求的 url 来判断去具体的应用服务,举个例子(用百度为场景举例方便理解,不是百度官方的技术实现):

  1. 我访问 https://www.baidu.com,nginx 接收到这个 url,判断是访问页面,于是把请求转发给前端服务,前端服务返回了 html 文件

  2. 根据 html 文件,用户又发起了一些 css、js、img 请求,nginx 同样转给前端服务返回了对应资源

  3. 用户此时搜索 万字前端效率大提速系列,前端发起 XHR 请求假设为 https://api.baidu.com/search?word=万字前端效率大提速系列,nginx转发到后端服务,由后端服务返回接口数据。

基本的流程是:用户的请求,nginx来判断交给哪个服务,对应的服务处理完后,把处理结果交给nginx返回。那么 nginx 是怎么判断的呢,我们看下使用方式:

MacOS 下安装 nginx

使用 Homebrew 安装:

brew install nginx

# 以下是安装好之后的输出
==> Pouring nginx--1.21.5.big_sur.bottle.tar.gz
==> Caveats
# /usr/local/var/www 是默认静态文件目录
Docroot is: /usr/local/var/www

# /usr/local/etc/nginx/nginx.conf 是配置文件路径
The default port has been set in /usr/local/etc/nginx/nginx.conf to 8080 so that
nginx can run without sudo.

nginx will load all files in /usr/local/etc/nginx/servers/.

nginx 基础命令

# 启动,如果已经启动或者端口被占用则会报错
nginx

# 测试配置文件的语法是否正确,同时也会打印出配置文件的路径
nginx -t

# 上一步成功后,重启 nginx 以应用最新的配置,线上环境注意不要这样,要无感更新
nginx -s reload

启动之后,就可以在 http://localhost:8080/ 看到 Welcome to nginx!

nginx 常见应用场景的配置

我们先看一下 nginx 的默认配置中比较重要的一段

    server {
        # 监听端口 8080,所以能在 http://localhost:8080/ 看到返回内容 
        listen       8080;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html; 这里是静态文件服务对应的文件根目录,相对路径 /usr/local/opt/nginx/html
            index  index.html index.htm; 默认页面,即访问 http://localhost:8080/ 等于访问 根目录下的 index.html
        }

根据默认配置,我们显然稍作修改就可以作为本地静态服务器使用,可以修改端口、文件根目录、默认页面。但是工作中我们还会遇到其他的场景,一一来看:

  1. 开启 gzip 压缩,一般来说,静态文件服务无脑开就行了,想要更好的性能可以上 CDN
# 默认配置的 33 行把注释打开
gzip  on;
  1. 很多同学会烦恼代码更新了线上却不生效走了缓存,如果打包出的 js、css 文件有哈希值,作为索引的 html 文件可以配置不缓存
  location / {
    ## 以 htm|html 结尾的文件加上不缓存的请求头
    if ($request_filename ~* .*\.(?:htm|html)$)  
    {
        add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
    }
    root   html; 
    index  index.html index.htm;
  }
  1. 用 E-Tag 控制缓存,用于文件名不会变的情况,E-Tag属于协商缓存,优先级比 Cache-Control 低。nginx 默认是开启的,确保没有 etagoff 主动关掉就行。返回头里会有 ETag 一栏。

  2. 单页应用,像 vue、react 的官方项目都是单页应用 即打包后只有一个 index.html,此时路由有 hash 模式和 history 模式。如果使用 history 模式,配置不当刷新页面则会导致 404

原因是当你用 nginx 默认配置时,首页 localhost:8080/ 是可以正常访问的,但是当你跳转到别的页面例如 localhost:8080/goodsList ,前端其实掌控了路由没有重新请求,这时候你刷新页面,根据 nginx 的配置会去找 goodsList.html 或者 goodsList/index.html,于是就报 404 了

这个情形 Vue-Cli官网是有说明的,只需要把所有路径的请求,都指向 index.html ,前端应用会根据当前的 path 判断渲染的页面,具体配置为:

    location / {
      root   /app;
      index  index.html;
      # 加一行 所有路径的请求,都 try_files 指向 index.html
      try_files $uri $uri/ /index.html;
    }
  1. 多个单页应用,因为性能原因,Webpack 中将不相干的业务设置不同的 entry,打包出了多个 html,可以按下面配置部署,访问 /public/buyer 开头的路径,会指向 buyer.html
	location /public/buyer {
        root   html;
        index  buyer.html;
        try_files $uri /public/buyer.html;
    }

	location /public/seller {
        root   html;
        index  seller.html;
        try_files $uri /public/seller.html;
    }

  1. 前端应用和后端混合部署
    # 后端应用 /api/v1/ 开头的都会重定向到 http://xxx.xxx.xxx.xx:3030/
	location /api/v1/ {
        proxy_pass http://xxx.xxx.xxx.xx:3030/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    # 前端应用
    location / {
        root   /app;
        index  index.html;
        try_files $uri $uri/ /index.html;
    }
  1. 配置域名
    server {
        # 访问不带端口就是默认 80端口,HTTPS 默认 443端口
        listen       80;
        # listen       443 ssl;
        server_name  这里填域名 www.xxxx.com;
  1. 老是404?用 alias 替代 root 指定根目录,直接来看两者的区别
# root ,请求 http://xxx.com/css/style.css 时 会去找 /data/css/style.css
location /css/ {
  root /data;
}
# alias ,请求 http://xxx.com/css/style.css 时 会去找 /data/style.css
location /css/ {
  alias /data/;
}

区别在于,alias 配置必须 / 结尾,并且会截去 path 的部分

列了这么多场景,大家点赞收藏,遇到了就来看看能不能用上

什么是正向代理、反向代理?

正向代理可以理解为用户端的代理,在发起请求时交给代理发起请求,例如:游戏加速、科学上网工具;反向代理是服务器端的代理,收到请求后转发给其他的服务,例如 Apache、Nginx、Tomcat 等。

Docker

服务器资源利用 - 变革性的虚拟容器技术 docker!我们从 "它是什么、它在项目中做什么、前端可以用它做什么" 这三个方面说说

Docker 是什么

Docker 是一种操作系统层面的虚拟化技术,能为应用创建 文件系统、网络、进程等 与宿主机隔离的运行环境,比传统虚拟机技术更轻便快捷。

提到虚拟化技术,在虚拟化容器(container)之前,使用的是传统的虚拟机技术:直接虚拟一套硬件(割出一套CPU、内存、硬盘等等),在虚拟硬件上运行操作系统,再在系统内运行应用。而操作系统会占用很高的硬盘、内存等资源。但 Docker 可以使容器共享宿主机的操作系统内核,且在资源分配上隔离,因此更为轻便高效。

Docker 在项目中做什么

Docker 在团队中通常会用于线上或测试环境的项目部署,优点是应用环境稳定、迁移方便。线上可能会配合 K8S(或者只使用 K8S)进行容器编排,方便集群部署、按需分配资源、考虑服务器容灾等

前端可以用 Docker 做什么

对于开发人员来说,Docker 最方便的功能就是帮我们搭建开发环境,为项目中的 nginx、mysql、前端应用、后端应用编写好配置后,就可以一键安装环境并启动。在团队内可以大大提升安装开发环境的速度。实战教程:用 Docker 一键部署前后端项目

简单安装与使用

基本流程:安装 -> 编写配置文件 -> 启动

  1. 官网中下载操作系统对应的 Docker 桌面应用程序并启动

  2. 下载 实战代码,里面有5个编写好的项目镜像配置

  3. 编写/修改 Dockerfile 文件,配置镜像,参照实战代码webapp/Dockerfile-dev 配置;

  4. 编写/修改 compose 文件,按顺序将镜像启动为容器,参照实战代码docker-compose-dev.yml 配置,启动了5个容器;

  5. 命令行执行:docker-compose -f docker-compose-dev.yml up -f 指定配置文件直接启动!前后端应用 + mysql + nginx 就一键启动啦

  6. 启动成功,访问 http://localhost:3030/ 查看部署好的页面,指向前端项目 webapp;http://localhost:3030/api/ 指向后端项目 nest-server。

  7. 启动不成功可以尝试以下命令(谨慎在线上使用这些命令)

# 停止所有容器 
docker stop $(docker ps -aq)
# 删除所有停止的容器 
docker container prune
# docker-compose 重新拉取镜像
docker-compose up -d --build
# 再尝试启动
docker-compose -f docker-compose-dev.yml up

学习资源

Jenkins

项目写好了,就该部署到测试环境或者线上环境了。如果是一个静态构建的前端项目,我们得 npm run build 然后把打包出的文件,用 scp 命令 或者 ftp工具 复制到服务器的 nginx 目录下完成部署。不仅要等构建完成才能拷贝,拷贝还需要连上服务器,过程略显繁琐,此时我们可以考虑使用 jenkins 来自动化部署。

使用 jenkins 的好处有:

  1. 配置好部署任务后,点击执行即可完成 拉代码 -> 打包 -> 部署 一条龙
  2. 可以通过 git service、脚本 等方式,在代码提交时自动触发部署任务
  3. 可以配置邮箱或者通知机器人,获取部署成功的通知
  4. 部署失败可以通过查看任务执行详情,在控制台中查看失败输出和原因

安装

在服务器上安装运行 jenkins 的步骤可以参考文档:

配置部署任务

  1. 首页 -> 系统管理 -> 管理插件 -> 启用 NodeJS 插件
  2. 首页 -> 系统管理 -> 全局工具配置,配置node下载及安装
  3. 首页 -> 新建 -> 创建一个新任务,选择构建自由风格的软件项目
  4. 配置基本信息,配置仓库信息 -> 选择 git 仓库
  5. 增加构建步骤,通常是 npm install && npm run build
  6. 设置构建后操作,主要是把打包出的 dist 目录拷贝到 nginx 的静态服务目录下

通常我们开发人员提供 git 仓库和部署命令 即可,其他完整步骤可以协同运维或者后端同学一起配置。

上一篇:七、前端需要了解的后端常用工具