各位观众老爷,晚上好!我是今晚的讲师,准备好迎接一场 Vue 项目 CI/CD 的饕餮盛宴了吗?今天咱们不搞虚的,直接上干货,手把手教你打造一条龙的自动化流水线,让你的 Vue 项目从此告别手动部署的苦逼日子,拥抱丝滑流畅的 CI/CD 体验!
第一部分:工欲善其事,必先利其器——工具链选择
要搭建 CI/CD 流水线,首先得选好趁手的兵器。别跟我说你还打算用记事本写代码然后手动 FTP 上传,那是远古时代的故事了!
- 版本控制系统:Git (这是必须的,没得选)
-
CI/CD 平台:
- GitHub Actions: 如果你的代码托管在 GitHub 上,强烈推荐,免费额度够用,而且集成方便。
- GitLab CI/CD: GitLab 自带 CI/CD,功能强大,可以自建,也可以用 SaaS 版本。
- Jenkins: 老牌 CI/CD 工具,灵活可定制,但配置相对复杂。
- CircleCI: 云原生 CI/CD,上手简单,但收费较高。
咱们今天主要讲 GitHub Actions,因为它用的人多,免费,而且足够满足大部分 Vue 项目的需求。
- 包管理器:npm/yarn/pnpm (根据你的项目选择,推荐 pnpm,速度快,节省空间)
- 测试框架:Jest/Mocha/Vitest (根据你的喜好和项目需求选择,推荐 Jest,生态完善)
- 代码质量检查工具:ESLint/Prettier/Stylelint (保证代码风格一致,减少 bug)
-
部署工具:
- 服务器: 各种云服务器 (AWS, Azure, Google Cloud, 阿里云, 腾讯云),或者自己的服务器。
- 对象存储: 如果是静态网站,可以部署到对象存储 (AWS S3, 阿里云 OSS, 腾讯云 COS)。
- Vercel/Netlify: 专门为前端项目打造的部署平台,免费额度较高,上手简单。
咱们今天以部署到服务器为例,演示整个流程。
第二部分:GitHub Actions 入门——YAML 语法和基本概念
GitHub Actions 的核心就是 YAML 文件,它定义了你的 CI/CD 流水线。咱们先来了解一下 YAML 的基本语法和 GitHub Actions 的基本概念。
-
YAML 语法: YAML 是一种人类可读的数据序列化格式。它使用缩进表示层级关系,使用
-
表示列表项。name: My Workflow # 工作流的名称 on: # 触发工作流的事件 push: branches: [main] jobs: # 定义任务 build: # 任务名称 runs-on: ubuntu-latest # 运行环境 steps: # 定义步骤 - name: Checkout code # 步骤名称 uses: actions/checkout@v3 # 使用的 Action - name: Set up Node.js uses: actions/setup-node@v3 with: node-version: 16 - name: Install dependencies run: npm install - name: Build project run: npm run build
-
GitHub Actions 基本概念:
- Workflow (工作流): 一个自动化的流程,由一个或多个 jobs 组成。
- Job (任务): 一个包含多个 steps 的执行单元。
- Step (步骤): 一个具体的执行动作,可以是运行命令,也可以是使用 Action。
- Action (动作): 可重用的代码块,封装了常用的操作,比如 checkout 代码,安装依赖等。
- Runner (运行器): 运行 workflow 的服务器,可以是 GitHub 提供的,也可以是自己搭建的。
第三部分:配置 Vue 项目的 CI/CD 流水线
咱们现在开始配置 Vue 项目的 CI/CD 流水线。假设你的项目已经托管在 GitHub 上,并且使用了 npm 作为包管理器。
-
创建
.github/workflows
目录: 在你的项目根目录下创建.github
目录,然后在.github
目录下创建workflows
目录。 -
创建
main.yml
文件: 在.github/workflows
目录下创建一个main.yml
文件,这个文件就是你的 CI/CD 流程的定义。 -
编写
main.yml
文件:name: Vue CI/CD # 工作流的名称 on: # 触发工作流的事件 push: branches: [main] # 当 push 到 main 分支时触发 pull_request: branches: [main] # 当有 pull request 到 main 分支时触发 jobs: # 定义任务 build: # 任务名称 runs-on: ubuntu-latest # 运行环境 steps: # 定义步骤 - name: Checkout code # 步骤名称 uses: actions/checkout@v3 # 使用的 Action - name: Set up Node.js uses: actions/setup-node@v3 with: node-version: 16 # 使用 Node.js 16 - name: Install dependencies run: npm install # 安装依赖 - name: Run tests run: npm run test:unit # 运行单元测试 (根据你的项目配置修改) - name: Run lint run: npm run lint # 运行 ESLint (根据你的项目配置修改) - name: Build project run: npm run build # 构建项目 - name: Upload artifacts # 上传构建产物 uses: actions/upload-artifact@v3 with: name: dist # 产物名称 path: dist # 产物路径 deploy: # 部署任务 needs: build # 依赖 build 任务 runs-on: ubuntu-latest # 运行环境 if: github.ref == 'refs/heads/main' # 只在 main 分支上部署 steps: - name: Download artifacts # 下载构建产物 uses: actions/download-artifact@v3 with: name: dist # 产物名称 - name: Deploy to server # 部署到服务器 uses: appleboy/[email protected] # 使用 SSH Action with: host: ${{ secrets.SERVER_HOST }} # 服务器地址 (从 secrets 中获取) username: ${{ secrets.SERVER_USER }} # 服务器用户名 (从 secrets 中获取) key: ${{ secrets.SERVER_PRIVATE_KEY }} # 服务器私钥 (从 secrets 中获取) port: 22 # SSH 端口 script: | cd /var/www/your-project # 进入项目目录 rm -rf * # 删除所有文件 cp -r dist/* . # 复制构建产物到项目目录 # 如果你的项目需要重启服务,可以在这里添加重启命令 # 例如:sudo systemctl restart your-service
-
配置 Secrets: 在 GitHub 仓库的 Settings -> Secrets -> Actions 中添加以下 Secrets:
SERVER_HOST
: 你的服务器地址。SERVER_USER
: 你的服务器用户名。SERVER_PRIVATE_KEY
: 你的服务器私钥。 注意:一定不要把私钥直接写在 YAML 文件中,否则会被泄露!
-
提交代码: 将
.github/workflows/main.yml
文件提交到 GitHub 仓库。 -
观察流水线运行: push 代码到 main 分支,或者创建一个 pull request 到 main 分支,GitHub Actions 就会自动运行你的 CI/CD 流水线。你可以在 GitHub 仓库的 Actions 选项卡中查看流水线的运行状态。
代码解释:
name: Vue CI/CD
: 定义工作流的名称。on:
: 定义触发工作流的事件。这里配置了当 push 到 main 分支或者有 pull request 到 main 分支时触发。jobs:
: 定义任务。这里定义了两个任务:build
和deploy
。build:
: 构建任务,负责 checkout 代码,安装依赖,运行测试和构建项目。deploy:
: 部署任务,负责下载构建产物,然后通过 SSH 连接到服务器,将构建产物复制到服务器上。needs: build
: 表示 deploy 任务依赖 build 任务,只有 build 任务成功完成后,deploy 任务才会执行。if: github.ref == 'refs/heads/main'
: 表示只有当分支是 main 分支时,deploy 任务才会执行。uses: actions/checkout@v3
: 使用actions/checkout@v3
这个 Action 来 checkout 代码。uses: actions/setup-node@v3
: 使用actions/setup-node@v3
这个 Action 来设置 Node.js 环境。uses: actions/upload-artifact@v3
: 使用actions/upload-artifact@v3
这个 Action 来上传构建产物。uses: actions/download-artifact@v3
: 使用actions/download-artifact@v3
这个 Action 来下载构建产物。uses: appleboy/[email protected]
: 使用appleboy/[email protected]
这个 Action 来通过 SSH 连接到服务器。secrets.SERVER_HOST
: 从 GitHub 仓库的 Secrets 中获取服务器地址。
第四部分:代码质量检查——ESLint、Prettier 和 Stylelint
代码质量是保证项目稳定性和可维护性的重要因素。咱们可以使用 ESLint、Prettier 和 Stylelint 来进行代码质量检查。
- ESLint: 用于检查 JavaScript 代码的语法和风格。
- Prettier: 用于格式化代码,使其符合统一的风格。
- Stylelint: 用于检查 CSS 代码的语法和风格。
-
安装依赖:
npm install eslint prettier eslint-plugin-vue eslint-config-prettier stylelint stylelint-config-standard stylelint-config-prettier stylelint-order -D
-
配置 ESLint: 创建
.eslintrc.js
文件:module.exports = { root: true, env: { node: true, }, extends: [ 'plugin:vue/vue3-essential', 'eslint:recommended', '@vue/eslint-config-prettier', ], parserOptions: { ecmaVersion: 2020, }, rules: { 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 'vue/multi-word-component-names': 'off', // 关闭多单词组件名校验,根据你的需要调整 }, };
-
配置 Prettier: 创建
.prettierrc.js
文件:module.exports = { semi: false, singleQuote: true, trailingComma: 'all', printWidth: 100, tabWidth: 2, };
-
配置 Stylelint: 创建
.stylelintrc.js
文件:module.exports = { extends: [ 'stylelint-config-standard', 'stylelint-config-prettier', 'stylelint-order', ], rules: { 'order/properties-alphabetical-order': null, // 关闭属性字母顺序校验,根据你的需要调整 }, };
-
配置 npm scripts: 在
package.json
文件中添加以下 scripts:"scripts": { "lint": "eslint --ext .vue,.js,.jsx,.ts,.tsx src/", "lint:fix": "eslint --fix --ext .vue,.js,.jsx,.ts,.tsx src/", "format": "prettier --write src/", "stylelint": "stylelint src/**/*.{vue,css,scss}", "stylelint:fix": "stylelint --fix src/**/*.{vue,css,scss}" }
-
修改
main.yml
文件: 将Run lint
步骤修改为:- name: Run lint run: npm run lint
现在,每次提交代码,GitHub Actions 都会自动运行 ESLint、Prettier 和 Stylelint,检查代码质量。如果代码质量检查失败,流水线就会停止,防止不符合规范的代码被部署到服务器上。
第五部分:多环境部署——区分开发、测试和生产环境
在实际项目中,通常需要区分开发、测试和生产环境。咱们可以使用不同的分支和不同的配置来支持多环境部署。
-
创建不同的分支: 创建
develop
(开发) 和staging
(测试) 分支。 -
配置不同的 Secrets: 为不同的环境配置不同的 Secrets。例如:
-
SERVER_HOST_DEV
: 开发环境服务器地址。 -
SERVER_USER_DEV
: 开发环境服务器用户名。 -
SERVER_PRIVATE_KEY_DEV
: 开发环境服务器私钥。 -
SERVER_HOST_STAGING
: 测试环境服务器地址。 -
SERVER_USER_STAGING
: 测试环境服务器用户名。 -
SERVER_PRIVATE_KEY_STAGING
: 测试环境服务器私钥。 -
SERVER_HOST_PROD
: 生产环境服务器地址。 -
SERVER_USER_PROD
: 生产环境服务器用户名。 -
SERVER_PRIVATE_KEY_PROD
: 生产环境服务器私钥。
-
-
修改
main.yml
文件:name: Vue CI/CD on: push: branches: - main - develop - staging pull_request: branches: - main - develop - staging jobs: build: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v3 - name: Set up Node.js uses: actions/setup-node@v3 with: node-version: 16 - name: Install dependencies run: npm install - name: Run tests run: npm run test:unit - name: Run lint run: npm run lint - name: Build project run: npm run build - name: Upload artifacts uses: actions/upload-artifact@v3 with: name: dist path: dist deploy: needs: build runs-on: ubuntu-latest strategy: matrix: environment: [dev, staging, prod] # 区分不同的环境 include: - environment: dev branch: develop SERVER_HOST: ${{ secrets.SERVER_HOST_DEV }} SERVER_USER: ${{ secrets.SERVER_USER_DEV }} SERVER_PRIVATE_KEY: ${{ secrets.SERVER_PRIVATE_KEY_DEV }} - environment: staging branch: staging SERVER_HOST: ${{ secrets.SERVER_HOST_STAGING }} SERVER_USER: ${{ secrets.SERVER_USER_STAGING }} SERVER_PRIVATE_KEY: ${{ secrets.SERVER_PRIVATE_KEY_STAGING }} - environment: prod branch: main SERVER_HOST: ${{ secrets.SERVER_HOST_PROD }} SERVER_USER: ${{ secrets.SERVER_USER_PROD }} SERVER_PRIVATE_KEY: ${{ secrets.SERVER_PRIVATE_KEY_PROD }} if: github.ref == format('refs/heads/{0}', matrix.branch) steps: - name: Download artifacts uses: actions/download-artifact@v3 with: name: dist - name: Deploy to server uses: appleboy/[email protected] with: host: ${{ matrix.SERVER_HOST }} username: ${{ matrix.SERVER_USER }} key: ${{ matrix.SERVER_PRIVATE_KEY }} port: 22 script: | echo "Deploying to ${{ matrix.environment }}" cd /var/www/your-project-${{ matrix.environment }} # 区分不同环境的项目目录 rm -rf * cp -r dist/* . # 根据环境执行不同的重启命令 # 例如: # if [ "${{ matrix.environment }}" == "prod" ]; then # sudo systemctl restart your-service # fi
代码解释:
strategy: matrix:
使用矩阵策略来并行执行多个部署任务,每个任务对应一个环境。include:
定义了不同环境的配置,包括分支名称、服务器地址、用户名和私钥。if: github.ref == format('refs/heads/{0}', matrix.branch)
: 只有当分支名称与当前环境配置的分支名称匹配时,才执行部署任务。matrix.environment
: 当前环境的名称。matrix.SERVER_HOST
: 当前环境的服务器地址。
现在,当你 push 代码到 develop
分支时,GitHub Actions 会自动将代码部署到开发环境服务器上。当你 push 代码到 staging
分支时,GitHub Actions 会自动将代码部署到测试环境服务器上。当你 push 代码到 main
分支时,GitHub Actions 会自动将代码部署到生产环境服务器上。
第六部分:自动化测试——单元测试、集成测试和 E2E 测试
自动化测试是保证项目质量的关键。咱们可以使用 Jest 进行单元测试, Cypress 进行 E2E 测试。
-
安装 Jest:
npm install jest @vue/test-utils -D
-
配置 Jest: 创建
jest.config.js
文件:module.exports = { preset: '@vue/cli-plugin-unit-jest', };
-
编写单元测试: 在
src/components
目录下创建一个HelloWorld.spec.js
文件:import { shallowMount } from '@vue/test-utils' import HelloWorld from '@/components/HelloWorld.vue' describe('HelloWorld.vue', () => { it('renders props.msg when passed', () => { const msg = 'new message' const wrapper = shallowMount(HelloWorld, { props: { msg } }) expect(wrapper.text()).toMatch(msg) }) })
-
安装 Cypress:
npm install cypress -D
-
编写 E2E 测试: 在
cypress/integration
目录下创建一个example.spec.js
文件:describe('My First Test', () => { it('Visits the app root url', () => { cy.visit('/') cy.contains('h1', 'You did it!') }) })
-
配置 npm scripts: 在
package.json
文件中添加以下 scripts:"scripts": { "test:unit": "vue-cli-service test:unit", "test:e2e": "cypress run" }
-
修改
main.yml
文件:name: Vue CI/CD on: push: branches: - main - develop - staging pull_request: branches: - main - develop - staging jobs: build: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v3 - name: Set up Node.js uses: actions/setup-node@v3 with: node-version: 16 - name: Install dependencies run: npm install - name: Run tests (unit) run: npm run test:unit - name: Run tests (e2e) run: npm run test:e2e # 添加 E2E 测试 - name: Run lint run: npm run lint - name: Build project run: npm run build - name: Upload artifacts uses: actions/upload-artifact@v3 with: name: dist path: dist deploy: needs: build runs-on: ubuntu-latest strategy: matrix: environment: [dev, staging, prod] include: - environment: dev branch: develop SERVER_HOST: ${{ secrets.SERVER_HOST_DEV }} SERVER_USER: ${{ secrets.SERVER_USER_DEV }} SERVER_PRIVATE_KEY: ${{ secrets.SERVER_PRIVATE_KEY_DEV }} - environment: staging branch: staging SERVER_HOST: ${{ secrets.SERVER_HOST_STAGING }} SERVER_USER: ${{ secrets.SERVER_USER_STAGING }} SERVER_PRIVATE_KEY: ${{ secrets.SERVER_PRIVATE_KEY_STAGING }} - environment: prod branch: main SERVER_HOST: ${{ secrets.SERVER_HOST_PROD }} SERVER_USER: ${{ secrets.SERVER_USER_PROD }} SERVER_PRIVATE_KEY: ${{ secrets.SERVER_PRIVATE_KEY_PROD }} if: github.ref == format('refs/heads/{0}', matrix.branch) steps: - name: Download artifacts uses: actions/download-artifact@v3 with: name: dist - name: Deploy to server uses: appleboy/[email protected] with: host: ${{ matrix.SERVER_HOST }} username: ${{ matrix.SERVER_USER }} key: ${{ matrix.SERVER_PRIVATE_KEY }} port: 22 script: | echo "Deploying to ${{ matrix.environment }}" cd /var/www/your-project-${{ matrix.environment }} rm -rf * cp -r dist/* .
现在,每次提交代码,GitHub Actions 都会自动运行单元测试和 E2E 测试,确保代码质量。
第七部分:总结与展望
今天咱们一起打造了一条 Vue 项目的 CI/CD 流水线,包括自动化测试、代码质量检查和多环境部署。虽然配置过程有点繁琐,但是一旦配置完成,就可以大大提高开发效率,保证项目质量。
当然,CI/CD 还有很多高级用法,比如:
- 代码覆盖率: 使用 Istanbul 或 NYC 来生成代码覆盖率报告。
- 性能测试: 使用 Lighthouse 或 WebPageTest 来进行性能测试。
- 安全扫描: 使用 Snyk 或 SonarQube 来进行安全扫描。
- 自动回滚: 当部署失败时,自动回滚到上一个版本。
希望今天的讲座能对你有所帮助。记住,CI/CD 不是一蹴而就的,需要不断学习和实践,才能打造出最适合你的流水线!下次再见!