Skip to content

本文由 简悦 SimpRead 转码, 原文地址 mp.weixin.qq.com

聊到运维,很长一段时间我觉得跟前端就是毫无关联的玩意,应该说半毛钱关系都木。但随着前端工程化的发展,前端基本运维部署相关知识甚至也逐步被重视,如果你公司的运维部门很强大,那么你也可以完全忽略运维相关的。只是树酱觉得,如果你想更多了解前端架构,还是需要具备一定的运维相关知识储备。当然,现在云厂商都想应推出自己的 Serverless 服务 (下一篇会讲~),号称让前端更专注业务的开发,而不用担心底层应用的部署和维护,对开发者而言可以更多聚焦到业务领域的开发,有兴趣的童鞋可以去玩玩

1.npm

npm 是 Node.js 官方提供的包管理工具,主要用来管理项目依赖,发布等等,下面介绍几个比较常见的部署应用场景,常用的 npm 命令这里不作介绍了

1.1 nrm

nrm(npm registry manager) 是 npm 的镜像源管理工具,因为 npm 默认建立的链接访问的是国外的资源,访问速度较慢,使用这个就可以快速地在 npm 源间切

  • 如何安装
npm install -g nrm
  • 查看可选的资源
nrm ls   *npm ---- https://registry.npmjs.org/cnpm --- http://r.cnpmjs.org/taobao - http://registry.npm.taobao.org/eu ----- http://registry.npmjs.eu/...
  • 添加私有仓库链接
nrm add name http://registry.npm.tree.com/  # 私有仓库链接nrm use name # 使用本址的镜像地址

nrm 更多用于如果公司内网部署了私有仓库,也就是方便用 nrm 作来源切换,也有益于依赖的版本管理,如果你想搭建自己的私有仓库,可以使用 verdaccio,可以看这个具体的教程 点我👇

1.2 发布 npm 包

当我们想发布一个 npm 包,需要完成什么样的流程呢?

  • 先注册 npm 账号 🔗

  • 配置 package.json

{  "name": "kutil",  "version": "1.0.0", #版本名称  "scripts":[], # 可执行的脚本命令  "repository": "https://github.com/xxx/xxx.git", #github仓库地址  "author": "tree <shuxin_liu@kingdee.com>", #作者  "description": "工具包“, #包的说明  "keywords": [    "utils",  ]}
  • 配置打包机制

如果是工具类打包,推荐使用 rollup,webpack 比较适合打包一些应用,例如 SPA 或者同构项目

  • 添加单元测试

优质的开源包,都有单元测试模块,来保证包的稳定性和代码质量,常见会有 build-passing 的标记,有兴趣的童鞋可以阅读树酱之前写的前端单元测试那些事

  • 开发文档 readme.me

readme 方便开发者快速熟悉,包括具体的 Api 介绍、使用例子、项目介绍等等,还可以加入包括单元测试覆盖率、下载量、证书等等

最后完成上面一系列操作之后,到了最终的发布环节

npm login # 登录你上面注册的npm账号npm publish # 登录成功后,执行发布命令+ kutil@1.0.0 # 发布成功显示npm报名及包的版本号

2. jenkins

jenkins 作为一个可扩展的自动化服务器,可以用作简单的 CI 服务器,具有自动化构建、测试和部署等功能,简而言之,jenkins 可以方便我们日常的前端项目版本更新迭代(开发、测试、生产环境等),也可以通过它自动化完成一系列的操作包括:编译打包元测试、代码扫描等,官方文档

2.1 如何安装

  • 下载 Jenkins.

  • 打开终端进入到下载目录.

  • 运行命令 java -jar jenkins.war --httpPort=8080.

  • 打开浏览器进入链接 http://localhost:8080.

  • 按照说明完成安装.

详细流程图可参考 Jenkins+github 前端自动化部署

2.2 配合前端项目自动化部署

这里主要介绍 jenkins 流水线配置的使用,流水线的代码定义了整个的构建过程, 他通常包括构建, 测试和交付应用程序的阶段,下面是路径和仓库的配置

图片相关配置如下:

  • SCM: 选择 git 或者 svn 作为代码触发器

  • 脚本路径:在项目根目录创建 jenkinsfile 来编写流水线

下面介绍一个简单版的 jenkinsfile 的流水线任务写法,完成整个前端工程化部署涉及的编译打包、静态扫描、单元测试等环节

def gitUrl = "http://gitlab.****.com/shc/****.git"//GIT入口(随不同工程改变)def gitCred = "***-***-4f00-a926-1848b670d97b"    //GIT 身份凭据if ("DEV" == buildType) {    buildScript = "build_development"    try {        node('k8s') {            stage('下拉源码') {                   checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: "${gitCred}", url: "${gitUrl}"]]])                 #可由片段生成器生成,选择示例步骤 “checkout:Check out from version control”,生成流水线脚本获取            }            checkStatus('下拉源码')            stage('代码构建编译') {                sh "yarn run ${buildScript}"            }            checkStatus('代码构建编译')            stage('代码静态扫描') {                sh 'yarn run lint'            }            checkStatus('代码静态扫描')            stage('单元测试') {                 sh 'yarn run unit'            }            checkStatus('单元测试')        }    } catch(Exception e) {           }}

完成后,即可构建项目,分阶段完成,首先是下拉源码、代码构建编译、代码扫描等等,所有环节成功才算自动化部署成功,如下所示

3.Docker

Docker 是一个虚拟环境容器, 可以将开发环境、代码、配置文件等一并打包到这个容器中, 最后发布应用

3.1 如何使用

通过将部署的操作集中成一个部署脚本完成传统的部署流程,通过在服务器上运行 docker 容器来运行前端应用

如何安装

yum install docker-ce

项目目录,部署项目需要准备 Dockerfile 和 nginx.conf(如果 nginx 不作定制化,可以直接用官方镜像)

3.2 Dockerfile 配置

dockerfile 是一个配置文件, 用来让 docker build 命令清楚运行那些操作,创建 dockerfile 并编写相关配置

FROM node:latest as builder WORKDIR /appCOPY package.json RUN npm install   COPY . .RUN npm run buildFROM nginx:latestCOPY nginx.conf /etc/nginxCOPY --from=builder /app/dist  /usr/share/nginx/html//ps: 每一个指令的前缀都必须是大写的。
  • ADD 和 COPY:  将文件或目录复制到 Dockerfile 构建的镜像中

  • EXPOSE: 指定运行该镜像的容器使用的端口,可以是多个。

  • RUN :指令告诉 docker 在镜像内执行命令

  • FROM :通过 FROM 指定的镜像名称,这个镜像称之为基础镜像,必须位于第一条非注释指令

  • WORKDIR: 在容器内部设置工作目录

Nginx.conf 配置如下

events {    worker_connections  1024;}http{    server {        listen       80;        server_name  localhost;        location / {            root   /usr/share/nginx/html;            index  index.html index.htm;        }       }}

创建文件并编写后,用 docker 创建镜像

3.3 如何创建镜像

使用当前目录的 Dockerfile 创建镜像,标签为 frontend

docker build -t frontend .
  • -t :指定要创建的目标镜像

  • . :Dockerfile 文件所在目录,可以指定 Dockerfile 的绝对路径

镜像成功生成

3.4 查看镜像

docker image ls | grep frontend

出现结果则应用镜像 frontend 成功创建, 然后我们基于该镜像启动一个 Docker 容器

4.5 如何启动

使用 docker 镜像 frontend:latest 以指定 80 端口映射模式启动容器, 并将容器命名为 frontend

docker run --name frontend -p 80:80 frontend:latest
  • -p: 指定端口映射,格式为:主机 (宿主) 端口: 容器端口 将宿主的 80 端口映射到容器的 80 端口

  • -name: 为容器指定一个名称;

完成 docker 部署

docker 也可以集成到上一节讲的 jenkins 自动化部署流水线中去

stage('部署到开发联调环境') {                echo "auto deploy to test environment"                sh "docker build -t frontend ."                sh "docker run --name frontend -p 80:80 frontend:latest"  }

4.PM2

PM2 是 node 进程管理工具,可以利用它来简化很多 node 应用管中繁琐任务,是 Nodejs 应用程序守护进程必不可少的选择,方便管理基于 nodejs 平台下能够有独立运行访问的 web 服务,如 nextjs、express、koa 等前端应用

4.1 常见的应用场景

  • 部署 node koa2 或 express 项目应用

  • 部署 前端 SSR(后端渲染)应用,如 nuxt.js(Vue)和 next.js(React) 等构建服务端渲染应用框架

4.2 如何使用

  • 安装 :npm install -g pm2

  • 启动 node 项目 : pm2 start app.js 或者 pm2 start bin/www

  • 停止 pm2 服务:pm2 stop bin/www

  • 停止所有 pm2 服务: stop all

  • 重启 pm2 服务: pm2 restart bin/www

  • pm2 所有进程信息:pm2 list

启动后如下所示

4.3 高阶应用

在项目根目录中添加一个 processes.json

{ #apps是一个数组,每一个数组成员就是对应一个pm2中运行的应用  "apps": [{    "name": "app",  #名称    "script": "./", #程序入口    "cwd": "./",           #应用程序所在的目录    "error_file": "./logs/err.log",#错误输出日志    "log_date_format": "YYYY-MM-DD HH:mm Z" #日期格式  }]}

结合 packjson 脚本命令,可以用 processes 来管理多应用

"script":{    "pm2":"pm2 start processes.json"}

更多命令和配置信息查看 pm2 文档

5.Nginx

Nginx 它既可以作为 Web 服务器,也可以作为负载均衡服务器,具备高性能、高并发连接等

5.1 前端 Nginx 那些事

详细信息请看之前梳理的前端 Nginx 那些事

5.2 补充

  • 灰度发布

灰度发布即是让一部分人继续用旧版本的产品 A,然后一部分用户开始用新版本特征的产品 B,如果用户对 B 没有什么问题反馈,则逐步扩大范围。一方面可以保证整体系统的稳定,而且在初始灰度的时候就可以发现、调整问题,以保证其影响度

传统的灰度是通过 Nginx 分发流量到服务器,这里介绍一下简单的灰度规则配置,通过在 nginx 里面配置路由规则就好,如果是规则复杂的话, 可以结合 nginx+lua 做一些些灰度的业务逻辑

  1. 根据 Cookie 实现灰度发布

通过获取 cookie 设置的版本号来区分

upstream test1 {    server 192.168.0.1:8080 max_fails=1 fail_timeout=60;}upstream default {    server 192.168.0.0:8080 max_fails=1 fail_timeout=60;}server {  listen 80;  server_name  www.****.com;  set $group "default";    if ($http_cookie ~* "version=V1"){        set $group test1;    }  location / {                           proxy_pass http://$group;    proxy_set_header   Host             $host;    proxy_set_header   X-Real-IP        $remote_addr;    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;    index  index.html index.htm;  } }
  1. 根据 IP 实现灰度发布

通过内外网 IP 来区分

upstream test1 {    server 192.168.0.1:8080 max_fails=1 fail_timeout=60;}upstream default {    server 192.168.0.0:8080 max_fails=1 fail_timeout=60;}server {  listen 80;  server_name  www.xxx.com;  set $group default;  if ($remote_addr ~ "10.0.0.110") {      set $group test1;  }location / {                           proxy_pass http://$group;    proxy_set_header   Host             $host;    proxy_set_header   X-Real-IP        $remote_addr;    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;    index  index.html index.htm;  }}

请你喝杯🍵 记得三连哦~

  1. 阅读完记得给🌲 酱点个赞哦,有👍 有动力

  2. 关注公众号前端那些趣事,陪你聊聊前端的趣事

  3. 文章收录在 Github frontendThings 感谢 Star✨