手把手系列之——前端工程化
前言: 在公司,每天的工作都离不开一个内部平台,它的名字叫做devops(就是这么直白哈哈哈),这个系统包含了公司从商机、需求、开发、测试到部署的全流程。那什么是devops呢,本文将由此引入CI/CD、前端自动化等一系列概念,并手把手带你进行实战!
什么是 DevOps?
![]()
DevOps 是 Development(开发)与 Operations(运维)的合成词(面试有被问到过,还好我会!),代表的是一套文化、实践与工具的集合,核心目标是打破开发与运维之间的壁垒,让软件从需求到上线的全流程更短、更稳、更可重复。
什么是 CI/CD?
CI/CD 是持续集成与持续交付/部署的缩写,是 DevOps 在「构建与发布」环节的具体实现方式。
-
CI(Continuous Integration,持续集成)
开发者频繁将代码合入主干(或主分支),每次合入后自动触发:拉取代码、安装依赖、执行 Lint、跑单测/集成测试、打包构建。目的是尽早发现集成错误,避免分支长期不合并带来的「大爆炸」式合并问题。 -
CD(Continuous Delivery / Deployment)
- 持续交付:CI 通过后,产物处于「随时可发布」的状态,发布到生产支持人工审批或手动触发。
- 持续部署:在持续交付的基础上再进一步,通过流水线自动将通过测试的版本部署到测试/预生产/生产环境。
简单来说就是:CI 负责「每次提交都能被自动验证」;CD 负责「通过验证的版本能快速、可控地发布出去」。二者通常由同一套流水线串联起来。
什么是前端自动化?
前端自动化 指的是在前端工程中,把原本依赖人工、重复性高的动作交给脚本或流水线自动完成,主要包括:
- 代码质量:提交前/合入后自动执行 ESLint、Prettier、类型检查(TypeScript)等。
- 测试:单元测试(Jest)、组件测试、E2E 测试在流水线中自动运行。
-
构建与产物:根据分支或标签自动执行
npm/pnpm build,生成dist等产物,并归档或打镜像。 - 部署:将构建产物自动同步到静态服务器、CDN,或构建成 Docker 镜像并推送到仓库、触发 K8s 等部署。
前端自动化的落地形式往往就是:在 CI/CD 流水线里为前端项目配置「安装依赖 → Lint → 测试 → 构建 → 部署」等步骤,从而减少人工操作、统一环境、提高发布频率与可靠性。
三者的联系
| 概念 | 定位 | 与另外两者的关系 |
|---|---|---|
| DevOps | 文化与流程层面的指导思想 | 强调「自动化、协作、快速反馈」;CI/CD 与前端自动化是其实践手段。 |
| CI/CD | 构建与发布环节的技术实践 | 在 DevOps 理念下,用流水线把「集成 → 测试 → 部署」自动化;前端项目参与其中即是在做「前端自动化」。 |
| 前端自动化 | 在前端域内的具体落地 | 通过接入 CI/CD(如 Jenkins、GitLab CI),把前端的检查、构建、部署纳入统一流水线,是 DevOps 在前端侧的体现。 |
总结:
DevOps 解决「为什么要这样做」和「怎样组织」,是一个指导思想;
CI/CD 解决「用流水线把构建和发布自动化」;
前端自动化则是在前端项目里,用 CI/CD 和脚本把检查、构建、部署都跑起来。
梳理完概念,可以回答这个问题了:为什么需要 DevOps 与 CI/CD呢?
传统研发的痛点
-
发布慢、手工多:打包、上传、部署全靠人工,易出错且耗时长。像我们前端团队没有工程化之前需要手动维护十几个省市的社保渠道验证环境,要和服务器打交道不说,每次改完bug都需要手动上传到验证环境上,难受的要死
-
环境不一致:本地、测试、生产环境差异大,开发动不动就说:在我本地好好的呀......
-
反馈滞后:代码合并后很久才部署,问题发现晚、修复成本高
DevOps 与 CI/CD 能带来什么?
- DevOps:开发与运维协作、流程自动化、基础设施即代码,缩短从需求到上线的周期。
- CI(持续集成):代码合入后自动构建、测试,尽早发现集成问题。
- CD(持续交付/部署):在 CI 通过后,自动或一键将产物部署到各类环境。
对前端而言,典型收益包括:提交即触发构建、自动跑 Lint/单测、自动打包并部署到测试/生产,减少重复劳动。
一、技术选型与整体架构
1.1 核心组件
| 角色 | 选型 | 说明 |
|---|---|---|
| CI/CD 引擎 | Jenkins | 成熟、插件丰富,适合自定义流水线 |
| 代码仓库 | GitLab | 自带 CI/CD(GitLab CI),与 Jenkins 也可配合 |
| 容器化 | Docker | 统一构建与运行环境,便于「一次构建,到处运行」 |
| 私有仓库 | Docker Registry / Harbor、Verdaccio(npm) | 镜像与前端包私有化 |
说明:Gogs 仅适合做轻量 Git,不支持 CI/CD;若要做自动化构建与部署,建议用 GitLab(企业一般都本地部署) + 第三方 CI。
1.2 前端在流水线中的流程
代码提交 → 拉取代码 → 安装依赖 → Lint/测试 → 构建(dist) → 产物归档/镜像构建 → 部署
二、Jenkins 安装与基础配置
2.1 两种安装方式
- 直装:在宿主机装 Java + Jenkins,与系统耦合,升级、迁移不便。
- Docker 安装(推荐):隔离环境、易迁移、易复现。
单容器快速启动示例:
docker run -u root -d -p 10050:8080 -p 50000:50000 \
-v /var/run/docker.sock:/var/run/docker.sock \
jenkins/jenkins:2.479
验证容器是否运行:
docker ps | grep jenkins
若希望 在 Jenkins 里执行 Docker 命令(例如在流水线中 docker build / docker push),有两种常见做法:
-
挂载宿主机 Docker Socket:Jenkins 容器通过
/var/run/docker.sock使用宿主机 Docker(上面命令已挂载)。 - Docker-in-Docker(DinD):在独立容器中跑 Docker 守护进程,Jenkins 通过 TCP 连接过去,与宿主机 Docker 隔离,避免版本冲突,更贴近「在 Jenkins 里跑 Docker」的直觉,有点那个俄罗斯套娃的感觉。
下面采用 DinD + 自定义 Jenkins 镜像 的方式,便于在流水线中稳定的使用 Docker。
2.2 自定义 Jenkins 镜像(内建 Docker CLI + 访问 Socket)
思路:基于官方 Jenkins 镜像,安装 Docker CLI,并让 Jenkins 用户能访问挂载的 docker.sock(或后续在 DinD 中通过 TCP 访问)。
示例 Dockerfile(使用腾讯/阿里镜像加速,便于国内环境):
ARG JENKINS_VERSION=2.479.1
FROM jenkins/jenkins:${JENKINS_VERSION}
USER root
# 使用国内镜像源
RUN apt-get install -y apt-transport-https \
&& if [ -f /etc/apt/sources.list ]; then sed -i "s@http://\\(deb\\|security\\).debian.org@https://mirrors.tencent.com@g" /etc/apt/sources.list; else echo "deb https://mirrors.tencent.com/debian $(. /etc/os-release && echo "$VERSION_CODENAME") main" > /etc/apt/sources.list && echo "deb https://mirrors.tencent.com/debian-security $(. /etc/os-release && echo "$VERSION_CODENAME")-security main" >> /etc/apt/sources.list; fi
RUN apt-get update
# 安装 Docker CLI(使用阿里云 Docker CE 源)
RUN apt-get install -y ca-certificates curl gnupg \
&& curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| tee /etc/apt/sources.list.d/docker.list > /dev/null \
&& apt-get update \
&& apt-get install -y --no-install-recommends docker-ce-cli
# 使 jenkins 用户能访问 docker.sock(宿主机 docker 组 GID 多为 999,按需调整)
RUN groupadd -g 999 docker 2>/dev/null || true && usermod -aG docker jenkins
USER jenkins
构建:
docker build -t jenkins:2.479.1-docker .
测试(宿主机 socket 模式):
docker run --rm --name=test -v /var/run/docker.sock:/var/run/docker.sock \
jenkins:2.479.1-docker docker -H unix:///var/run/docker.sock ps
通过 .sock 或 TCP 与 Docker 通信,可以避免在 Jenkins 容器内再装一套 Docker 引擎带来的版本与权限问题。
2.3 使用 Docker Compose 组网:Jenkins + DinD
下面用 Compose 把「Jenkins 容器」和「DinD 容器」组网,Jenkins 通过 TLS 的 TCP 连接 DinD,实现「在 Jenkins 里执行 Docker 命令」:
新建docker-compose.yml
services:
jenkins-docker:
image: arm64v8/docker:dind
container_name: jenkins-docker
privileged: true
networks:
jenkins:
aliases:
- docker
environment:
- DOCKER_TLS_CERTDIR=/certs
volumes:
- jenkins-docker-certs:/certs/client
- jenkins-data:/var/jenkins_home
jenkins-blueocean:
image: jenkins:2.479.1-docker
container_name: jenkins-blueocean
restart: on-failure
networks:
- jenkins
environment:
- DOCKER_HOST=tcp://docker:2376
- DOCKER_CERT_PATH=/certs/client
- DOCKER_TLS_VERIFY=1
volumes:
- jenkins-data:/var/jenkins_home
- jenkins-docker-certs:/certs/client:ro
- /tmp:/tmp
ports:
- "10050:8080"
- "50000:50000"
networks:
jenkins:
name: jenkins
driver: bridge
volumes:
jenkins-docker-certs:
jenkins-data:
driver: local
driver_opts:
type: none
device: /home/jenkins/data
说明:
-
jenkins-docker:DinD 服务,暴露 2376(TLS)。 -
jenkins-blueocean:Jenkins 容器,通过DOCKER_HOST=tcp://docker:2376使用 DinD。 - 证书与数据卷保证重启后 Jenkins 仍能连上 DinD,且数据持久化。
启动:
docker compose up -d
进入 Jenkins 容器排查时可用:
docker exec -it jenkins-blueocean /bin/sh
至此 Jenkins 安装与 Docker 环境就绪,可用于后续流水线中的镜像构建与推送。
2.4 基础配置(插件与镜像)
- 访问:
http://<宿主机IP>:10050(或你映射的端口)。
- 首次可先「选择插件来安装」,若部分插件安装失败可先跳过,稍后在「插件管理」中重试或更换更新中心。
-
更新中心:若默认源慢,可在「Manage Jenkins → Plugin Manager → Advanced」中把 Update Site 换成国内镜像(如华为云,如果ping不通可以再换其他源),再安装 Node.js、Pipeline、Git、SSH 等插件。

- 权限:安装 Role-based Authorization Strategy,便于按项目/角色做细粒度控制。
三、GitLab 安装
若尚未安装 GitLab,可用 Docker 快速起一个(注意资源:建议 4 核 8GB 以上,避免 OOM):
-
新建目录,例如
gitlab。 -
新建
.env:GITLAB_HOME=/home/gitlab -
新建
docker-compose.yml(示例为 ARM64,x86 可去掉platform):services: web: image: 'gitlab/gitlab-ce:18.2.0-ce.0' platform: linux/arm64 restart: always hostname: '10.211.55.4' environment: GITLAB_OMNIBUS_CONFIG: | external_url 'http://10.211.55.4:10082' gitlab_rails['gitlab_shell_ssh_port'] = 10083 env_file: - .env ports: - '10082:10082' - '10083:22' volumes: - '$GITLAB_HOME/config:/etc/gitlab' - '$GITLAB_HOME/logs:/var/log/gitlab' - '$GITLAB_HOME/data:/var/opt/gitlab' shm_size: '512m' -
执行
docker compose up -d启动后,访问http://<host>:10082/users/sign_in,即表示安装成功。
四、Jenkins 与 GitLab 打通(SSH + Webhook)
4.1 在 Jenkins 中配置 Git 凭据
![]()
-
在 Jenkins「源码管理」中需要拉取 GitLab 仓库时,添加 Credentials。
-
类型选择 SSH Username with private key。
-
在宿主机或某台机器上生成密钥(若未使用默认路径,需在 Jenkins 中指定私钥路径):
ssh-keygen -t ed25519 -C YourEmail cat <私钥路径> # 将内容粘贴到 Jenkins 的 Key 中 -
Username 可填
git或 GitLab 上对应用户名。
4.2 在 GitLab 中配置 Deploy Key
- 进入项目:Settings → Repository → Deploy Keys。
- 新建部署密钥,把上面生成的 公钥 粘贴进去,勾选「公开访问」等按需勾选。
- 这样 Jenkins 即可用该私钥拉取代码,无需个人账号密码。
4.3 Webhook(代码推送触发构建)
- 在 Jenkins 任务中启用「构建触发器」:Build when a change is pushed to GitLab(需安装 GitLab 插件)。
- 在 GitLab 项目:Settings → Webhooks,URL 填 Jenkins 的 GitLab webhook 地址,并设置与 Jenkins 中一致的 Secret 令牌。
- 保存后可发送 Test 请求验证,确保 Jenkins 能收到推送事件并触发任务。
这样可实现:git push → GitLab → Webhook → Jenkins 自动构建,符合 CI 的「提交即构建」理念。
五、前端流水线
5.1 手动构建与部署
在 Jenkins 任务中增加「执行 shell」步骤,例如:
pnpm i
pnpm build
建议:在 Jenkins 中配置 Node.js 环境(Node 插件)并指定版本;设置 淘宝源 或项目级 .npmrc 加速依赖安装。构建完成后,前端产物一般在 dist,可在 Workspace 中查看。
部署方式二选一或组合使用:
-
Publish over SSH:在 Manage Jenkins → System 中配置 SSH 服务器,在任务的 Build Steps 中增加「Send files or execute commands over SSH」,指定源为
dist/**、远程目录(如/var/www/my-app),并可增加「在远程执行命令」(如重载 Nginx),完成「构建 → 上传到目标机」的简单 CD。 -
Docker 镜像:在仓库中准备 Dockerfile(多阶段构建:先
pnpm build,再只保留dist+ Nginx),在任务中执行docker build -t my-app:${BUILD_NUMBER} .与docker push <私有仓库>/my-app:${BUILD_NUMBER}。 - 私有仓库可选阿里云、自建 Registry、Harbor(详见第六节「前端私有化」),从而在 Jenkins 内完成「构建 → 打镜像 → 推仓库 → 在 K8s 或 Docker 主机上拉取并部署」的完整 CD。
5.2 Jenkins Pipeline
把「拉代码 → 装依赖 → 构建 → 测试 → 归档/镜像 → 部署」写成 Pipeline 脚本(Declarative 或 Scripted),可以实现版本化管理、复用、审查。
- 在任务类型中选择 Pipeline。
- 从 SCM 读取
Jenkinsfile,或直接在任务里写 Pipeline 脚本。 - 使用
node { ... }、stage、sh、archiveArtifacts、docker.build等步骤编排前端流水线。
流水线即代码,便于版本管理与审查,也可与 GitLab 分支策略配合(例如仅对 main 分支执行生产部署)。
5.3 GitLab CI/CD
![]()
若希望「流水线跟着仓库走」,也可采用 GitLab CI:
- 在仓库根目录添加 .gitlab-ci.yml。
- 定义
stages(如build、test、deploy)和jobs。 - 每个 job 指定
image(如node:20)、script(如pnpm i && pnpm build)、artifacts(保存dist)。 - 通过 GitLab Runner 在 Docker 或宿主机上执行,无需单独维护 Jenkins。
Jenkins 与 GitLab CI 也可并存:例如用 GitLab CI 做 MR 内的构建与测试,用 Jenkins 做发布与对接内部部署系统。
六、前端私有化
前端链路中常涉及两类私有仓库:Docker 镜像(用于部署)与 npm 包(组件库、工具包)。私有化后可实现内网构建、权限管控与版本的统一。
6.1 Docker 镜像私有化
构建好的前端镜像需要推送到私有仓库,供内网或 K8s 拉取部署,常见方案如下:
- 阿里云容器镜像服务:托管在云上,开箱即用,免费额度有限(如 300 个命名空间后要收费),适合小团队或试用。
-
自建 Docker Registry:官方
registry镜像即可搭建,无图形界面,适合仅需「能推能拉」的场景。
使用前需在 Jenkins 或本机docker run -d -p 5000:5000 --restart=always -v /opt/registry:/var/lib/registry registry:2docker login < registry 地址>配置账号。 - Harbor:企业级镜像仓库,提供 Web 管理、权限、镜像扫描、多仓库复制等功能,适合规范化和多环境同步,需单独部署与维护。
在流水线中于 docker build 之后执行 docker push <私有仓库地址>/<镜像名>:<标签>,即可将前端镜像推送到上述任一类仓库。
6.2 npm 包私有化(Verdaccio)
团队内部组件库、工具包希望私有发布时,可用 Verdaccio 搭建 npm 私有源:
npm install --global verdaccio
npm i -g nrm
verdaccio
nrm add private http://localhost:4873/
nrm use private
npm adduser
npm login
发布:
npm init -y
npm publish
![]()
若流水线需从私有源安装依赖,在 Jenkins 中配置 .npmrc 或相应环境变量即可。
七、小结
| 环节 | 建议 |
|---|---|
| 代码仓库 | GitLab(或 GitHub),支持 Webhook、Deploy Key。 |
| CI | Jenkins 或 GitLab CI,提交/合并后自动安装依赖、Lint、测试、构建。 |
| 构建环境 | Node 版本固定,依赖缓存(如 pnpm store)、国内镜像加速。 |
| 产物 | 归档 dist 或构建镜像,便于追溯与回滚。 |
| 部署 | 通过 SSH 传文件或推送 Docker 镜像至服务器/K8s 供拉取部署。 |
| 私有化 | Docker 用 Registry/Harbor,npm 用 Verdaccio。 |
| 流水线形态 | Pipeline as Code(Jenkinsfile / .gitlab-ci.yml),可版本化、可复用。 |
按上述步骤一步步走下来,即可实现「手工打包上传」升级为「提交即构建、构建即可部署」的前端 DevOps 闭环;再结合分支策略、环境隔离与权限控制,就可以在保证质量的前提下提升发布效率与可重复性。
说回我们公司的devops,开发部分支持新建流水线,实现了新建分支 => 分支合并 => 打包部署(docker) => 成果上传的开发闭环,大大节省了运维时间和重复劳动,也推荐大家搞台服务器或者本地搞个虚拟机试试看!