CI_CD
什么是CI/CD
在前端开发中,CI/CD 是 Continuous Integration(持续集成)和 Continuous Deployment/Continuous Delivery(持续部署/持续交付)的简称。它是一种软件开发实践,自动化了应用的构建、测试和发布过程。
CI/CD的作用
- 持续集成(CI):当开发者将代码推送到版本控制系统(如 GitHub、GitLab)时,CI 工具会自动构建和测试应用代码,以确保代码没有引入新的问题。前端代码在此过程中会进行:
- 自动化单元测试和集成测试
- 代码质量检查(如 ESLint)
- 编译和构建打包(例如 Webpack 或 Vite)
- 持续部署/持续交付(CD):
- 持续交付:构建和测试通过后,代码自动发布到一个准备好的环境中(如 staging 环境)进行手动审核,之后再发布到生产环境。
- 持续部署:代码通过测试后,自动部署到生产环境,使更新可以快速上线。对于前端,这通常会将最新的代码发布到 Web 服务器或 CDN。
实现CI/CD
1.1 编写配置文件
// 配置
const config = [{name: '项目1',value: '项目1',ssh: {host: 'xxxx',port: 'xxxx',username: 'xxxx',password: 'xxxx',passphrase: 'xxxx'},targetDir: 'G:/桌面/code/xmzs/cicd-project/dist',targetFile: 'dist.zip',deployDir: '/www/wwwroot/',releaseDir: 'web',buildCommand: 'pnpm build'}
]export default config
配置文件为什么是一个数组呢?
因为可以支持多个项目上传不同的服务器
1.2 编写程序入口
function main() {}main()
1.3 读取配置文件的内容
有了入口之后,我们只需要使用node启动就可以完成程序的运行。有了配置文件之后,我们需要读取其中的配置完成后续的动作,那么,我们要怎么读取配置文件的内容呢?。我们可以采用命令行的方式来读取。因此,我们需要安装inquirer
这个库。
// 命令行交互工具
import inquirer from "inquirer";
import config from "../config.js";async function commanderLine () {const res = await inquirer.prompt([{type: 'list',message: '请选择项目',name: 'project',choices: config}])return config.find(item => item.value === res.project)
}export default commanderLine
通过以上函数,可以实现一下效果:
1.4 压缩
那么,我们可以根据命令行获取的路径参数对需要上传到服务器的文件夹进行压缩,需要用到archiver
这个库来对目录进行压缩。
// 编写压缩文件的代码
import archiver from 'archiver'
import fs from 'fs'
/*** * @param {*} targetDir 压缩的目录的位置* @param {*} localFile 压缩之后压缩包存放的位置*/
function compressFile (targetDir, localFile) {return new Promise(resolve => {// 创建可写流const output = fs.createWriteStream(localFile)const archive = archiver('zip', {zlib: { level: 9 }})archive.pipe(output)archive.directory(targetDir, 'dist')archive.finalize()archive.on('close', () => {console.log((archive.pointer() / 1024 / 1024).toFixed(2), 'MB')resolve()})})
}export default compressFile
1.5 使用ssh连接远程服务器
为了连接远程服务器,我们可以使用node-ssh这个库来完成
// 连接ssh服务
import * as ssh from 'node-ssh'const sshClient = new ssh.NodeSSH()function sshConnect (sshConfig) {return new Promise(resolve => {sshClient.connect(sshConfig).then(res => {console.log('connect success')resolve(res)})})
}export default {sshConnect,ssh: sshClient
}
import service from './src/ssh.js'
async main() {...await service.sshConnect(options.ssh)
}
1.6 上传文件
// 上传远端服务器的代码
// local表示需要上传的目录
// config.deployDir + config.releaseDir表示上传到服务器的目录的路径
function uploadFile (ssh, config, local) {return new Promise(resolve => {ssh.putFile(local, config.deployDir + config.releaseDir).then(() => {console.log('upload success')resolve()}).catch(err => {console.log(err)})})
}export default uploadFile
通过以上步骤,已经基本实现文件的上传,但是目前我们上传的是一个压缩包,因此需要对他进行解压,还有就是现在只能上传一次,因为服务器不允许同名文件出现,因此我们第二次上传时需要将上一次上传的给删掉。但是我们要怎么删除呢?
- 可以使用linux命令
- node-ssh提供了执行linux命令的方法
// 操作ssh命令的文件
function runCommander (ssh, command, path) {return new Promise(resolve => {ssh.execCommand(command, { cwd: path }).then((result) => {resolve()})})
}export default runCommander
通过以上方法,我们可以完成对linux命令的执行
- rm -rf 完成对原先文件的删除
- unzip 完成对压缩包的解压
- mv 完成对文件的重命名
1.7 执行对于需要上传的文件的打包
当我们对项目进行修改时,服务器上的内容并没有更新,因为我们并没有对其进行重新打包,因此我们还需要在上传文件到服务器之前对项目进行重新打包。那么,要如何在执行main脚本的同时执行项目的打包脚本呢?我们可以使用node的原生模块child_process子进程。
import { execSync } from 'child_process'
function runBuild (path, command) {return new Promise(resolve => {execSync(command, {cwd: path,stdio: 'inherit'})resolve()})
}export default runBuild
通过以上函数,我们可以完成对项目的打包。
1.8 最终的启动文件
import commanderLine from './src/helper.js'
import compressFile from './src/compressFile.js'
import service from './src/ssh.js'
import uploadFile from './src/uploadFile.js'
import runCommander from './src/handleCommand.js'
import path from 'path'
import runBuild from './src/build.js'
async function main () {const options = await commanderLine()const local = path.join(process.cwd(), options.targetFile)await runBuild(options.targetDir, options.buildCommand)await compressFile(options.targetDir, local)await service.sshConnect(options.ssh)await runCommander(service.ssh, `rm -rf ${options.releaseDir}`, options.deployDir)await uploadFile(service.ssh, options, local)await runCommander(service.ssh, `unzip ${options.releaseDir}`, options.deployDir)await runCommander(service.ssh, `rm -rf ${options.releaseDir}`, options.deployDir)await runCommander(service.ssh, `mv dist ${options.releaseDir}`, options.deployDir)service.ssh.dispose() // 断开ssh
}
main()
最终,我们只需要执行node app.js
就能完成对项目的打包以及部署到服务器了。
相关文章:

CI_CD
什么是CI/CD 在前端开发中,CI/CD 是 Continuous Integration(持续集成)和 Continuous Deployment/Continuous Delivery(持续部署/持续交付)的简称。它是一种软件开发实践,自动化了应用的构建、测试和发布过…...

Linux -- 初识线程
目录 线程的初步认识 为什么需要线程 怎么让代码分成多个执行流并发执行呢? 管理线程 线程的初步认识 线程是进程内部的一个执行分支,线程是CPU调度的基本单位。 在Linux操作系统中,线程是程序执行流的最小单位。一个进程可以包含多个线…...

Uniapp底部导航栏设置(附带PS填充图标教程)
首先需要注册和登录ifconfont官网,然后创建项目添加需要的图标 创建和添加图标库请参考:Uniapp在Vue环境中引入iconfont图标库(详细教程) 打开iconfont官网,找到之前添加的图标库,下载png图片 如果需要的…...

单智能体carla强化学习实战工程介绍
有三个工程: Ray_Carla: 因为有的论文用多进程训练强化学习,包括ray分布式框架等,这里直接放了一个ray框架的示例代码,是用sac搭建的,obs没用图像,是数值状态向量值(速度那些)。 …...

潮玩宇宙方块兽系统开发:可定制UI与多种游戏内嵌助力个性化体验
潮玩宇宙方块兽系统开发正在推动潮玩与游戏的融合,通过个性化的UI设计和多游戏内嵌模式,为用户带来了独一无二的体验。本文将从可定制UI、多游戏内嵌功能以及系统实现等方面入手,探讨如何构建一个极具吸引力的潮玩宇宙方块兽系统。 一、可定制…...

什么是低代码?3000字低代码超全解读!
现在这个时代企业面对的挑战越来越复杂,尤其在软件开发和应用交付方面,因为传统开发过程复杂且费时,企业很难从传统的软件开发方式中迅速响应市场变化从而获利。 而低代码(Low-Code)平台的出现为企业提供了一种更加快…...

雷池社区版7.1新版本自定义NGINX配置分析
简单介绍雷池,是一款简单好用, 效果突出的 Web 应用防火墙(WAF),可以保护 Web 服务不受黑客攻击。 雷池通过阻断流向 Web 服务的恶意 HTTP 流量来保护 Web 服务。雷池作为反向代理接入网络,通过在 Web 服务前部署雷池,可在 Web 服…...

[SAP ABAP] 面向对象程序设计-类和对象
面向对象开发的特点:封装、继承和多态 什么是类和对象? 类(CLASS)是创建对象的模板,对象(OBJECT)是类的实例 一个类可以创建多个对象 类 > 类型 对象 > 个体 在ABAP语言中,定义一个类,需要包含定义(defin…...

『大模型笔记』IBM技术团队:什么是智能体型RAG!
『大模型笔记』IBM技术团队:什么是智能体型RAG! 文章目录 一. 『大模型笔记』IBM技术团队:什么是智能体型RAG!二. 参考文献一. 『大模型笔记』IBM技术团队:什么是智能体型RAG! ✅检索增强生成(RAG)是一种结合检索和生成能力的技术,通过从向量数据库检索相关信息作为上…...
WPF 中 NavigationWindow 与 Page 的继承关系解析
官网解析: NavigationWindow 类 | Page 类 public class BaseWindow: NavigationWindow{} public partial class CountPage : Page{} 都是创建的WPF界面有什么区别? 在 WPF(Windows Presentation Foundation)开发中&#…...

WebRTC基础理论和通话原理
WebRTC理论知识 1.什么是WebRTC? WebRTC(Web RealTime Communication)是 Google于2010以6829万美元从 Global IP Solutions 公司购买,并 于2011年将其开源,旨在建立一个互联网浏览器间的实时通信的平台,让 WebRTC技术…...

NPU 可不可以代替 GPU
结论 先说结论,GPU分为可以做图形处理的传统意义上的真GPU,做HPC计算的GPGPU和做AI加速计算的GPGPU,所以下面分别说: 对于做图形处理的GPU,这个就和NPU 一样,属于DSA,没有替代性。当然…...

Vue3版本的uniapp项目运行至鸿蒙系统
新建Vue3版本的uniapp项目 注意,先将HbuilderX升级至最新版本,这样才支持鸿蒙系统的调试与运行; 按照如下图片点击,快速升级皆可。 通过HbuilderX创建 官方文档指导链接 点击HbuilderX中左上角文件->新建->项目 创建vue3…...

部署stable-diffusion3.5 大模型,文生图
UI 使用推荐的ComfyUI,GitHub 地址,huggingface 需要注册登录,需要下载的文件下面有说明 Dockerfile 文件如下: FROM nvidia/cuda:12.4.0-base-ubuntu22.04 RUN apt-get update && apt-get install python3 pip git --n…...
数据采集之selenium模拟登录
使用Cookijar完成模拟登录 本博文爬取实例为内部网站,请sduter使用本人账号替换*********(学号),***(姓名)进行登录 from selenium import webdriver from selenium.webdriver.common.by import By from…...

机器学习中的两种主要思路:数据驱动与模型驱动
在机器学习的研究和应用中,如何从数据中提取有价值的信息并做出准确预测,是推动该领域发展的核心问题之一。在这个过程中,机器学习方法主要依赖于两种主要的思路:数据驱动与模型驱动。这两种思路在不同的应用场景中发挥着至关重要…...
【计算机网络】TCP协议面试常考(一)
三次握手和四次挥手是TCP协议中非常重要的机制,它们在多种情况下确保了网络通信的可靠性和安全性。以下是这些机制发挥作用的一些关键场景: 三次握手的必要性: 同步序列号: 三次握手确保了双方的初始序列号(ISN&#…...

C#/.NET/.NET Core学习路线集合,学习不迷路!
前言 C#、.NET、.NET Core、WPF、WinForm、Unity等相关技术的学习、工作路线集合(持续更新)!!! 全面的C#/.NET/.NET Core学习、工作、面试指南:https://github.com/YSGStudyHards/DotNetGuide C#/.NET/.N…...
使用哈希表做计数排序js
function hashSort(arr) {// 创建一个哈希表(对象),统计每个数字出现的次数let hashMap {};arr.forEach(num > {if (hashMap[num]) {hashMap[num] 1;} else {hashMap[num] 1;}});// 根据哈希表的键值对构建排序后的数组let sortedArr …...

京津冀自动驾驶技术行业盛会|2025北京自动驾驶技术展会
“自动驾驶技术”已经成为全球汽车产业的焦点之一。在这个充满创新与变革的时代,“2025北京国际自动驾驶技术展览会”拟定于6月份在北京亦创国际会展中心盛大开幕,为全球自动驾驶技术领域的专业人士、企业以及爱好者们提供了一个交流与展示的平台。作为一…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...

面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...

Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...
日常一水C
多态 言简意赅:就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过,当子类和父类的函数名相同时,会隐藏父类的同名函数转而调用子类的同名函数,如果要调用父类的同名函数,那么就需要对父类进行引用&#…...

《信号与系统》第 6 章 信号与系统的时域和频域特性
目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...