1. 项目缘起:为什么我们需要一个“猴子代码”?
在团队里待久了,你肯定遇到过这种场景:新项目启动,大家摩拳擦掌准备大干一场,结果光是搭建开发环境、配置构建工具、搞CI/CD流水线就花了两三天。每个人电脑上的Node版本、包管理器、IDE插件都不一样,张三能跑起来的项目,李四一拉下来就报错。好不容易本地跑通了,要部署上线又是一堆麻烦:手动构建、手动上传、手动重启服务,一个不小心就出线上事故。
这就是典型的前端工程化问题。它不是一个技术难题,而是一个效率和组织难题。我们需要的不是某个高深莫测的框架,而是一套能快速复制、稳定运行、并且团队里每个人都能无脑上手的“标准答案”。
这就是我折腾“MonkeyCode”的初衷。你可以把它理解为一个高度定制化的前端项目脚手架,但它又不止于脚手架。它更像一个“工程化解决方案包”,里面打包了从项目初始化、开发规范、构建优化,到自动化测试、容器化部署、CI/CD流水线的一整套东西。目标很简单: 用一套命令,生成一个“开箱即用”的现代化Vue 3项目,并且连上云端的生产线,实现代码提交即部署。
为什么叫“MonkeyCode”?一方面,它想做到像猴子一样“简单复制”就能用,降低心智负担;另一方面,也是提醒自己,工具是为人服务的,别把工程化搞成束缚创造力的枷锁。接下来,我就把这套从零到一的完整过程拆开给你看。
2. 核心蓝图:MonkeyCode工程化体系包含什么?
在动手写第一行代码之前,我们必须想清楚这个“解决方案包”到底要解决哪些具体问题。一个完整的前端工程化体系,远不止
vue create
那么简单。我把它分成了四个层次,像搭积木一样层层递进。
2.1 第一层:项目脚手架与开发规范
这是地基。我们需要一个能快速生成项目骨架的命令行工具。这个骨架必须包含:
- 技术栈锁定 :Vue 3 + TypeScript + Vite 作为基础。这是当前性能和开发体验的黄金组合。Vite的闪电般的热更新和构建速度,是开发效率的保障。
-
目录结构规范
:不是随意的
src下面放所有东西。我会预设好components,views,utils,apis,stores,types等目录,并且约定它们的职责。比如,components下再分common(全局通用)和business(业务相关),避免后期组件混乱。 -
代码规范与质量门禁
:集成ESLint(语法检查)、Prettier(代码格式化)、Stylelint(样式检查)。关键一步是在
package.json的scripts里加入"lint": "eslint . --ext .vue,.js,.ts,.jsx,.tsx --fix"和"format": "prettier --write ."。更狠的是配置Git Hooks(通过husky和lint-staged),在git commit时自动检查暂存区的文件,不合格的代码根本提交不上去。 -
基础工具封装
:封装好常用的工具函数(如请求拦截、日期格式化)、Vue组合式函数(如
usePagination分页逻辑)和全局组件(如Loading、Message)。这些是避免重复造轮子的关键。
2.2 第二层:构建优化与产物管理
本地开发爽了,还得保证线上用户访问也快。这里涉及构建过程的深度定制。
-
环境变量管理
:区分
development、test、production等多环境。使用dotenv和Vite的环境变量模式(.env.development,.env.production),将API地址、密钥等敏感信息与代码分离。 -
构建策略优化
:
-
依赖分包(ManualChunks)
:将
vue、vue-router、pinia、element-plus等几乎不变的第三方库单独打包成一个vendor块,利用浏览器缓存。 -
按需引入
:对于
Element Plus这类大型UI库,必须配置自动按需引入,避免全量导入导致包体积膨胀。 -
资源压缩与Hash
:配置
vite的build选项,启用terser代码压缩,为静态资源(JS、CSS、图片)添加内容Hash,便于长期缓存和增量更新。
-
依赖分包(ManualChunks)
:将
-
产物分析
:集成
rollup-plugin-visualizer,构建后会生成一个可视化的依赖分析图(一个HTML文件),让你一眼看出是哪个依赖让你的包变“胖”了,从而有针对性地优化。
2.3 第三层:自动化测试与质量保障
没有测试的代码就像没有刹车的汽车。对于MonkeyCode,我要求生成的模板必须内置测试能力。
-
单元测试(Unit Test)
:使用
Vitest(与Vite生态完美契合,速度快)替代Jest。为工具函数、组合式函数、纯逻辑组件编写单元测试。配置好测试覆盖率报告(--coverage)。 -
组件测试(Component Test)
:使用
@vue/test-utils来测试Vue组件。模拟用户交互,断言组件渲染输出和状态变化。 -
端到端测试(E2E Test)
:使用
Cypress或Playwright。虽然重,但对于核心用户流程(如登录、下单)是必要的保障。在CI/CD流水线中,可以在部署前自动运行E2E测试。 -
测试脚本集成
:在
package.json中配置"test:unit","test:e2e"等脚本,并确保它们能在CI环境中无头(headless)运行。
2.4 第四层:CI/CD与自动化部署
这是将代码变动自动、安全、可靠地交付到用户手中的最后一步,也是工程化的终极体现。我选择的是 GitLab CI/CD + Docker + 云服务器 的组合,这也是目前中小团队最实用、成本可控的方案。
-
GitLab CI/CD
:利用GitLab自带的CI/CD功能,通过在项目根目录创建
.gitlab-ci.yml文件来定义流水线。它比Jenkins更轻量,与代码仓库集成度更高。 - Docker容器化 :将应用和其运行环境(Node版本、Nginx配置等)一起打包成Docker镜像。这解决了“在我机器上能跑”的经典问题,保证了环境一致性。
-
部署流程
:代码推送到特定分支(如
main) -> 触发CI流水线 -> 运行测试 -> 构建Docker镜像 -> 将镜像推送到私有仓库(如阿里云容器镜像服务) -> 在服务器上拉取新镜像并重启容器。
这四层构成了MonkeyCode的完整闭环。下面,我们就从第一层开始,一步步实现它。
3. 从零手搓MonkeyCode CLI与Vue3项目模板
我们不依赖
vue-cli
,而是自己创建一个更灵活的CLI工具来生成项目。这能让我们对模板有百分百的控制权。
3.1 创建MonkeyCode CLI工具
首先,我们新建一个目录
monkeycode-cli
。
mkdir monkeycode-cli && cd monkeycode-cli
npm init -y
编辑
package.json
,设置入口文件并添加必要的依赖。我们不需要复杂的命令行框架,用Node.js原生
fs
、
path
模块和
inquirer
(用于交互式提问)就够了。
{
"name": "monkeycode-cli",
"version": "1.0.0",
"description": "A CLI to generate Vue3 project with full engineering stack.",
"main": "index.js",
"bin": {
"monkeycode": "./bin/monkeycode.js"
},
"scripts": {},
"dependencies": {
"inquirer": "^9.0.0",
"chalk": "^4.1.2", // 用于终端彩色输出
"fs-extra": "^11.1.0" // 增强的文件操作,比原生fs更好用
}
}
创建
bin/monkeycode.js
文件,并在开头加上Shebang,让它成为可执行脚本。
#!/usr/bin/env node
console.log('Welcome to MonkeyCode!');
// ... 后续逻辑
通过
npm link
命令,将这个包链接到全局,这样我们就可以在任意地方使用
monkeycode
命令了。
npm link
3.2 设计交互式模板生成逻辑
CLI的核心逻辑是:询问用户几个关键选项 -> 根据选项选择模板 -> 将模板文件复制到目标目录 -> 动态替换模板中的变量(如项目名)。
我们在
index.js
中实现:
const inquirer = require('inquirer');
const fs = require('fs-extra');
const path = require('path');
const chalk = require('chalk');
const templates = {
'vue3-standard': {
url: 'https://github.com/your-org/vue3-standard-template.git', // 你的模板仓库地址
description: 'Vue 3 + TypeScript + Vite + Pinia + Element Plus'
},
// 未来可以扩展更多模板,如 'vue3-mobile', 'react-standard'
};
async function createProject() {
const answers = await inquirer.prompt([
{
type: 'input',
name: 'projectName',
message: '请输入项目名称:',
default: 'my-vue3-app'
},
{
type: 'list',
name: 'template',
message: '请选择项目模板:',
choices: Object.keys(templates).map(key => ({
name: `${key} (${templates[key].description})`,
value: key
}))
},
{
type: 'confirm',
name: 'useE2E',
message: '是否需要集成E2E测试 (Cypress)?',
default: false
}
]);
const targetDir = path.join(process.cwd(), answers.projectName);
if (fs.existsSync(targetDir)) {
console.log(chalk.red(`目录 ${targetDir} 已存在!`));
process.exit(1);
}
console.log(chalk.blue(`正在创建项目 ${answers.projectName}...`));
// 这里简化处理,实际应该去拉取远程模板或复制本地模板
// 我们假设有一个本地的模板目录 `templates/vue3-standard`
const templateDir = path.join(__dirname, 'templates', answers.template);
await fs.copy(templateDir, targetDir);
// 动态更新 package.json 中的项目名
const pkgPath = path.join(targetDir, 'package.json');
const pkg = require(pkgPath);
pkg.name = answers.projectName;
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
console.log(chalk.green(`项目创建成功!`));
console.log(chalk.yellow(`cd ${answers.projectName}`));
console.log(chalk.yellow(`npm install`));
console.log(chalk.yellow(`npm run dev`));
}
createProject().catch(console.error);
这个CLI工具虽然简单,但已经具备了核心的交互和模板复制功能。真正的精髓在于我们准备好的那个
templates/vue3-standard
模板。
3.3 构建“开箱即用”的Vue3项目模板
现在,我们来精心打造这个模板。在
monkeycode-cli/templates/vue3-standard
目录下,创建一个标准的Vue3项目。
# 在模板目录下
npm create vue@latest . -- --typescript --router --pinia --eslint --prettier
根据提示选择Yes或No,我们这里已经预设了要TS、Router、Pinia、ESLint和Prettier。
接下来是深度定制:
1. 规范目录结构:
src/
├── apis/ # 所有API请求封装,按模块划分
├── assets/ # 静态资源
├── components/ # 组件
│ ├── common/ # 全局通用组件 (如Button, Modal)
│ └── business/ # 业务相关组件
├── composables/ # Vue组合式函数
├── layouts/ # 布局组件
├── router/ # 路由配置
├── stores/ # Pinia状态管理,按模块划分
├── styles/ # 全局样式、变量
├── types/ # TypeScript类型定义
├── utils/ # 工具函数
├── views/ # 页面视图组件
├── App.vue
└── main.ts
2. 配置ESLint + Prettier + Husky:
在生成的
.eslintrc.cjs
和
.prettierrc
基础上,我们可以根据团队习惯调整规则。比如,强制使用
===
,变量命名必须使用
camelCase
等。
安装
husky
和
lint-staged
:
npm install husky lint-staged -D
npx husky init
编辑
package.json
,添加
lint-staged
配置:
"lint-staged": {
"*.{js,ts,vue}": [
"eslint --fix",
"prettier --write"
]
}
在
.husky/pre-commit
钩子文件中写入:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged
这样,每次提交前都会自动检查和修复代码格式问题。
3. 集成Element Plus并配置按需导入:
npm install element-plus @element-plus/icons-vue
npm install -D unplugin-vue-components unplugin-auto-import
修改
vite.config.ts
:
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
plugins: [
// ...
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
})
现在,你可以在组件中直接使用
ElButton
,而无需手动
import
,插件会自动处理。
4. 封装Axios请求实例:
在
src/utils/request.ts
中,创建一个配置了拦截器、基础URL、超时时间的Axios实例,并导出。在
src/apis/user.ts
等文件中引入这个实例,定义具体的API函数。这样做的好处是统一错误处理、请求/响应拦截(如添加token、处理通用错误码)。
至此,一个具备基础工程化能力的Vue3项目模板就准备好了。CLI工具会将它复制到用户指定的目录。接下来,我们要为这个项目注入灵魂——自动化部署流水线。
4. 构建CI/CD流水线:GitLab CI + Docker实战
本地开发环境再完美,代码上不了线也是白搭。我们采用GitLab CI/CD,因为它与Git仓库无缝集成,配置简单直观。
4.1 编写
.gitlab-ci.yml
文件
在项目模板的根目录,我们预先创建好
.gitlab-ci.yml
文件。这个文件定义了整个CI/CD的流程(Pipeline),它由多个按顺序或并行执行的“作业(Job)”组成。
# .gitlab-ci.yml
stages:
- test # 测试阶段
- build # 构建阶段
- deploy # 部署阶段
variables:
DOCKER_IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA # 定义镜像标签,使用提交哈希
# 缓存 node_modules,加速后续作业
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
# 1. 单元测试作业
unit-test:
stage: test
image: node:18-alpine # 使用Node官方镜像作为运行环境
script:
- npm ci --cache .npm --prefer-offline # 使用ci命令,它比install更严格,适合CI环境
- npm run test:unit -- --coverage # 运行单元测试并生成覆盖率报告
artifacts:
when: always
paths:
- coverage/ # 将测试覆盖率报告保存为产物,可在GitLab界面查看
reports:
junit:
- junit.xml # 如果有JUnit格式的测试报告,可以在这里配置
only:
- merge_requests # 仅在合并请求时运行,加快主分支推送速度
- main
# 2. 构建作业
build:
stage: build
image: node:18-alpine
script:
- npm ci --cache .npm --prefer-offline
- npm run build # 执行Vite构建,生成dist目录
artifacts:
paths:
- dist/ # 将构建产物保存,后续部署作业可以使用
only:
- main # 仅当代码推送到main分支时触发构建
# 3. 构建并推送Docker镜像
docker-build-push:
stage: build
image: docker:20.10.16 # 使用Docker in Docker (dind)环境
services:
- docker:20.10.16-dind # 启动一个Docker守护进程服务
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
script:
- echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY # 登录到容器镜像仓库
- docker build -t $DOCKER_IMAGE_TAG . # 根据项目根目录的Dockerfile构建镜像
- docker push $DOCKER_IMAGE_TAG # 推送镜像到仓库
dependencies:
- build # 声明依赖build作业,确保先有构建产物
only:
- main
# 4. 部署到服务器
deploy-to-server:
stage: deploy
image: alpine:latest
before_script:
- apk add --no-cache openssh-client # 安装ssh客户端
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | ssh-add - # 添加存储在GitLab CI变量中的SSH私钥
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
script:
# 通过SSH连接到部署服务器,执行部署脚本
- ssh -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "cd /path/to/deploy/script && ./deploy.sh $DOCKER_IMAGE_TAG"
only:
- main
when: manual # 设置为手动触发,点击按钮才部署,增加安全性
这个配置文件定义了一个清晰的流水线:代码推送到
main
分支后,先运行单元测试(如果是合并请求也会触发),然后并行进行项目构建和Docker镜像的构建与推送,最后等待手动点击触发部署到服务器。
注意 :这里有几个关键的安全和配置点:
$CI_REGISTRY_USER,$CI_REGISTRY_PASSWORD,$CI_REGISTRY,$SSH_PRIVATE_KEY,$SERVER_USER,$SERVER_IP这些都是 GitLab CI/CD Variables 。你需要在GitLab项目的 Settings -> CI/CD -> Variables 中设置。 绝对不要 将这些敏感信息硬编码在YAML文件或代码里。docker-build-push作业使用了services: - dind,这需要在GitLab Runner的配置中启用Docker in Docker特权模式。对于共享Runner,GitLab.com通常已配置好;对于自托管Runner,需要在config.toml中配置privileged = true。deploy-to-server设置为when: manual(手动触发),这是一个重要的安全实践,防止每一次提交都自动上线。你可以在GitLab Pipeline界面看到一个“播放”按钮,点击它才会执行部署。
4.2 编写项目Dockerfile
要让Docker镜像构建成功,我们需要在项目根目录提供一个
Dockerfile
。这里采用
多阶段构建
,以减小最终镜像体积。
# Dockerfile
# 第一阶段:构建阶段
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production --cache .npm --prefer-offline
COPY . .
RUN npm run build
# 第二阶段:运行阶段
FROM nginx:alpine
# 将构建产物从builder阶段复制到Nginx的默认静态文件目录
COPY --from=builder /app/dist /usr/share/nginx/html
# 如果需要自定义Nginx配置,可以复制进去
# COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
这个Dockerfile非常高效。第一阶段用Node环境安装依赖并构建,生成
dist
目录。第二阶段使用轻量级的
nginx:alpine
镜像,只把第一阶段的构建产物复制过来,抛弃了Node环境的所有中间文件和源码,使得最终镜像非常小巧(通常只有几十MB)。
4.3 编写服务器端部署脚本
最后,我们需要在部署服务器上准备一个简单的Shell脚本
deploy.sh
,GitLab CI会通过SSH远程执行它。
#!/bin/bash
# deploy.sh
set -e # 遇到错误立即退出
IMAGE_TAG=$1 # 从CI传入的镜像标签,如 registry.example.com/group/project:abc1234
echo "开始部署,镜像标签: $IMAGE_TAG"
# 1. 拉取最新的镜像
docker pull $IMAGE_TAG
# 2. 停止并删除旧容器(如果存在)
CONTAINER_NAME="my-vue3-app"
if [ "$(docker ps -aq -f name=$CONTAINER_NAME)" ]; then
echo "停止并移除旧容器..."
docker stop $CONTAINER_NAME
docker rm $CONTAINER_NAME
fi
# 3. 运行新容器
echo "启动新容器..."
docker run -d \
--name $CONTAINER_NAME \
--restart always \ # 设置容器总是重启,应对服务器重启等情况
-p 8080:80 \ # 将宿主机的8080端口映射到容器的80端口
$IMAGE_TAG
# 4. 清理旧的、无用的Docker镜像,释放磁盘空间
echo "清理无用镜像..."
docker image prune -f
echo "部署完成!"
将这个脚本放在服务器的某个路径下(如
/path/to/deploy/script/
),并赋予执行权限
chmod +x deploy.sh
。当GitLab CI的
deploy-to-server
作业触发时,就会通过SSH执行这个脚本,完成服务的更新。
5. 避坑实录:那些我踩过的“猴子坑”
工程化的道路从来不是一帆风顺的。下面分享几个我在搭建这套体系时遇到的典型问题和解决方案,希望能帮你省下几个小时甚至几天的调试时间。
5.1 GitLab Runner 注册与配置的“网络迷踪”
问题:在自托管服务器上安装GitLab Runner后,执行作业总是卡在
Preparing environment
或直接失败。
排查过程:
-
检查Runner状态
:
sudo gitlab-runner status,确保服务是running的。 -
查看Runner日志
:
sudo gitlab-runner run在前台运行,观察实时日志。发现错误信息是dial tcp x.x.x.x:443: i/o timeout。 -
网络分析
:Runner需要连接GitLab服务器(通常是
gitlab.com或你的私有地址)来获取作业。服务器可能因为防火墙或网络策略无法访问外网。 -
解决方案
:
-
方案A(如果有网络权限)
:为服务器配置正确的HTTP/HTTPS代理。在Runner的配置文件(通常是
/etc/gitlab-runner/config.toml)中,找到对应的Runner,添加environment = ["http_proxy=http://your-proxy:port", "https_proxy=http://your-proxy:port"]。 - 方案B(内网环境) :搭建一个内网GitLab实例,并将Runner注册到内网地址。这是最稳定可靠的方案。
-
方案C(使用Shell Executor)
:如果只是简单项目,可以将Runner的执行器(executor)从
docker改为shell。这样作业会在Runner机器本身的Shell中运行,避免了Docker网络问题,但牺牲了环境隔离性。
-
方案A(如果有网络权限)
:为服务器配置正确的HTTP/HTTPS代理。在Runner的配置文件(通常是
心得 :CI/CD工具链的网络连通性是第一步,也是最容易出问题的一步。务必先确保Runner能稳定“回连”到GitLab。
5.2 Docker镜像构建缓慢与体积膨胀
问题:每次构建Docker镜像都要好几分钟,而且镜像越来越大。 根因分析:
-
没有合理利用Docker缓存
:Dockerfile的每一条指令都会生成一个镜像层。如果
COPY . .放在了npm install之前,那么任何源码文件的改动都会导致缓存失效,需要重新安装所有node_modules。 -
构建上下文(Build Context)过大
:
docker build .命令中的.会把当前目录所有文件(包括node_modules,.git, 日志文件等)发送给Docker守护进程,如果文件很多很大,传输和准备就会很慢。 -
最终镜像包含了构建工具
:如果你用
FROM node:18作为最终运行镜像,它会包含完整的Node和npm,而运行一个Vue编译后的静态站点根本不需要这些。
优化方案(即我们上面采用的方案):
-
调整Dockerfile指令顺序
:把变化频率低的指令放前面(如
COPY package*.json ./和RUN npm ci),变化频率高的指令放后面(如COPY . .)。 -
使用
.dockerignore文件 :在项目根目录创建.dockerignore,忽略不需要的文件。node_modules .git .DS_Store *.log .env.local dist - 采用多阶段构建 :正如我们之前的Dockerfile所示,第一阶段用完整Node环境构建,第二阶段只复制构建产物到轻量级Nginx镜像中,最终镜像体积可能只有原来的1/10。
5.3 CI/CD流水线中的环境变量“捉迷藏”
问题:在GitLab CI作业中,
npm run build
能成功,但构建出的页面访问API时却指向了
localhost
。
排查过程:
-
检查代码,发现API地址是通过
import.meta.env.VITE_API_BASE_URL获取的。 -
在本地
.env.production文件中明明配置了VITE_API_BASE_URL=https://api.myapp.com。 -
查看GitLab CI构建日志,发现构建命令是直接
npm run build,没有指定模式。 -
根本原因
:Vite(或类似的构建工具)在构建时,会从
当前Shell进程的环境变量
和
.env文件中读取VITE_开头的变量。在CI环境中,.env.production文件可能不存在,或者Shell中没有设置这些变量。
解决方案:
在
.gitlab-ci.yml
的
build
作业中,通过
variables
关键字注入环境变量。
build:
stage: build
variables:
VITE_API_BASE_URL: "https://api.myapp.com" # 在这里定义
# 或者更安全地从GitLab CI变量中读取:
# VITE_API_BASE_URL: $PRODUCTION_API_URL
script:
- npm run build
这样,在CI执行
npm run build
时,
VITE_API_BASE_URL
就被正确设置了。
重要提醒 :永远不要在代码仓库中提交包含真实密码、密钥的
.env文件。.env.example可以提交,用于说明需要哪些变量。真实的生产环境变量只应通过CI/CD平台的安全变量功能或服务器环境来设置。
6. 进阶与扩展:让猴子代码更“智能”
基础流程跑通后,我们可以考虑一些进阶优化,让整个体系更健壮、更高效。
6.1 基于Git Tag或分支的差异化部署
目前的流水线只监听
main
分支。在实际开发中,我们可能有
develop
(开发环境)、
staging
(预发布环境)、
main
(生产环境)等多个分支。
可以在
.gitlab-ci.yml
中利用
rules
关键字进行更精细的控制:
docker-build-push:
# ... 其他配置
rules:
- if: $CI_COMMIT_BRANCH == "main"
variables:
ENVIRONMENT: "production"
DOCKER_IMAGE_TAG: $CI_REGISTRY_IMAGE:prod-$CI_COMMIT_SHORT_SHA
- if: $CI_COMMIT_BRANCH == "staging"
variables:
ENVIRONMENT: "staging"
DOCKER_IMAGE_TAG: $CI_REGISTRY_IMAGE:staging-$CI_COMMIT_SHORT_SHA
when: manual # 预发布环境可以手动触发构建
然后在构建脚本或Dockerfile中,根据
ENVIRONMENT
变量使用不同的环境配置文件(如
.env.staging
)。
6.2 集成代码扫描与安全检测
除了单元测试,可以在CI中集成静态代码安全扫描(SAST)和依赖漏洞扫描。
-
使用
npm audit:在package.json的脚本中添加"audit": "npm audit --audit-level=high",并在CI的test阶段执行它。如果发现高危漏洞,可以让流水线失败。 -
集成SonarQube
:对于更全面的代码质量分析,可以配置一个
sonar作业,在构建后运行SonarScanner,将分析结果上传到SonarQube服务器,从复杂度、重复率、代码坏味道、安全漏洞等多个维度评估代码质量。
6.3 部署回滚与监控
自动化部署了,也要能快速回滚。一个简单的回滚策略是:
-
在服务器上,每次部署新镜像前,给当前正在运行的容器打一个标签,例如
my-app:previous。 -
如果新版本出现问题,只需执行一个回滚脚本,将服务重新指向
my-app:previous镜像即可。 - 更成熟的做法是使用Kubernetes的滚动更新和版本管理功能,可以做到无缝升级和秒级回滚。
监控方面,可以在Docker容器中集成应用性能监控(APM)工具的Agent,或者在服务器层面使用Prometheus+Grafana来监控容器资源使用情况、应用接口健康状态等。
折腾完这一整套,从输入
monkeycode create my-project
到代码提交后自动部署上线,整个过程已经高度自动化。它可能不是最完美的方案,但绝对是一个能立刻用起来、并且能随着团队成长而不断演进的坚实起点。工程化的最终目的不是炫技,而是让开发者能更专注于创造业务价值,而不是在环境配置和部署琐事上浪费时间。希望这套“猴子代码”的思路,能给你带来一些切实的启发。




被折叠的 条评论
为什么被折叠?



