node+nginx实现对react进行一键打包部署--windows版

文章目录

  • node+nginx实现对react进行一键打包部署--windows版
    • 1.功能展示及项目准备
      • 1.1功能展示
    • 1.2 项目准备
      • 1.2.1技术点
      • 1.2.2安装相关配置(windows)
    • 2.实现
      • 2.1 实现思路
      • 2.2 实现步骤
        • 2.1 项目准备
          • 2.1.1 创建env文件
          • 2.1.2 创建api/index.js文件
          • 2.1.3 添加解决跨域代码
      • 2.2 项目实现
        • 2.1 前端部分
          • 2.2.1 编写前端带代码
        • 2.2 后端部分
          • 2.2.1 实现node对项目打包
          • 2.2.2 对项目打包文件夹重命名
          • 2.2.3 对打包文件夹复制在nginx指定位置
          • 2.2.4 配置nginx管理项目代码
          • 2.2.5 重启nginx
          • 2.2.6 完整代码
    • 3.总结

node+nginx实现对react进行一键打包部署–windows版

1.功能展示及项目准备

1.1功能展示

功能展示

1.2 项目准备

1.2.1技术点

  • react
  • node
  • nginx
  • express
  • axios

1.2.2安装相关配置(windows)

  • 安装nginx
  • 使用vite安装react
  • 安装node
  • 使用node 安装express
  • 项目中安装axios (npm i axios --S)
    网上有多种安装方法,
    这里我就不做过多介绍了

2.实现

2.1 实现思路

实现思路

2.2 实现步骤

2.1 项目准备
2.1.1 创建env文件

在vite创建的项目文件根目录下新建一个.env文件

//你创建的项目的路径部分路径
VITE_API_URL=D:\OneDrive\桌面\练习项目\学生信息-react
//项目的名称
VITE_APP_NAME=create
2.1.2 创建api/index.js文件

项目的src下创建api文件夹,新建index.js文件,写入以下代码

import axios from 'axios'
axios.defaults.baseURL='http://localhost:3000'export const getStuList=()=>axios({url:'/student/list',method:'get'})export const addStu=(data)=>axios({url:'/student/add',method:'post',data})export const editStu=(data)=>axios({url:'/student/edit',method:'post',data})export const delStu=(data)=>axios({url:'/student/del',method:'post',data})export const buildApp=(data)=>axios({url:'/build/app',method:'post',data})
2.1.3 添加解决跨域代码

向express的项目中的app.js添加以下代码

//用于配置解决跨域问题
var allowCrosDown=function(req,res,next){res.header('Access-Control-Allow-Origin','*')res.header('Access-Control-Allow-Methods','*')res.header('Access-Control-Allow-Headers','*')next()
}
app.use(allowCrosDown)

2.2 项目实现

2.1 前端部分
2.2.1 编写前端带代码

主要是填写要部署后的项目监听端口与文件名称

function App() {const apiUrl = import.meta.env.VITE_API_URL;const appName = import.meta.env.VITE_APP_NAME;const [port,setPort]=useState('')const [buildName,setBuildName]=useState('')const [msg,setMsg]=useState('')async function handelBuild(){let result=await buildApp({TotalPath:apiUrl+'\\'+appName,port:+port,buildName})setMsg(result.data.msg)}return (<><div className='tabelCon'><div className='options'><ul><li><label htmlFor="port">打包后端口号:</label><input type="text" name="port" value={port} onChange={e=>setPort(e.target.value)} placeholder='请输入9000以后的端口号'/></li><li><label htmlFor="buildName">打包后文件名:</label><input type="text" name="buildName" value={buildName} onChange={e=>setBuildName(e.target.value)} placeholder='请输入文件名称'/></li><li><button onClick={handelBuild} className='bulid'>打包文件</button></li><li style={{color:'red'}}>{msg}</li></ul></div>//实现添加信息删除信息部分的html代码//因为与本文章无关便不记录,与兴趣的//可以自己实现一下......</div></>)
}export default App
2.2 后端部分
2.2.1 实现node对项目打包

实现对react进行打包,实现起来就是,

  • node进入前端项目的根目录
  • 执行npm run build命令
	// 使用 child_process.exec 函数执行命令//执行下面代码,在项目中就会看到一个dist文件夹const { exec } = require('child_process');let {TotalPath,port,buildName}=req.bodyconst command = 'npm run build';exec(`cd ${TotalPath} && ${command}`, (error, stdout, stderr) => {if (error) {res.send({msg:error})return;}});
2.2.2 对项目打包文件夹重命名

对打包后的文件进行重命名

  • 使用fs.rename()对文件夹进行重命名
//buildName就是要重新命名的名称
let {TotalPath,port,buildName}=req.body
let buildPath=TotalPath+'\\'+'dist'
let newPath=TotalPath+`\\${buildName}`
fs.rename(buildPath, newPath, (err) => {if (err) res.send({msg:error});console.log('重命名成功')})
2.2.3 对打包文件夹复制在nginx指定位置

将打包的文件复制到nginx安装目录中的html文件目录下

  • 创建一个文件夹
  • 将打包后的内容复制过去
	let NginxPath='D:\\前端开发工具\\nginx-1.24.0'// d:\前端开发工具\nginx-1.24.0\conf\nginx.conflet NginxConf=NginxPath+'\\'+'conf'+'\\'+'nginx.conf'const directoryPath = NginxPath+`\\html\\${buildName}`;fs.mkdir(directoryPath, { recursive: true }, err => {if (err) {res.send({msg:error})console.error(`无法创建文件夹 ${directoryPath}: ${err}`);return;}console.log(`文件夹 ${directoryPath} 已成功创建`);copyFolderRecursiveSync(newPath, directoryPath );exec(`cd ${NginxPath} && ${reloadCommand}`, (error, stdout, stderr) => {if (error) {res.send({msg:error})return;}res.send({msg:'项目打包成功、修改名称成功、复制文件到nginx成功、配置成功、重启成功'})});});function copyFolderRecursiveSync(source, target) {// 判断源文件夹是否存在if (!fs.existsSync(source)) {console.log(`源文件夹 ${source} 不存在`);return;}// 创建目标文件夹(如果不存在)if (!fs.existsSync(target)) {fs.mkdirSync(target);}// 读取源文件夹中的内容const files = fs.readdirSync(source);files.forEach(file => {const srcFile = path.join(source, file);const tgtFile = path.join(target, file);// 判断文件是文件夹还是文件if (fs.lstatSync(srcFile).isDirectory()) {// 如果是文件夹,递归复制子文件夹copyFolderRecursiveSync(srcFile, tgtFile);} else {// 如果是文件,直接复制到目标文件夹fs.copyFileSync(srcFile, tgtFile);}});
}
2.2.4 配置nginx管理项目代码

配置nginx管理项目代码

  • 修改nginx安装目录下conf中nginx.conf文件内容
  • 编写命令,插入代码
//port监听的端口
const { exec } = require('child_process');
const path = require('path');
const fs = require('fs');
const readline = require('readline');
const serve=`   server {listen       ${port};server_name  localhost;location / {root   html/${buildName};index  index.html index.htm;}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}}`//这里的59指的是在nginx.conf中插入的位置,//可根据自己的配置文件进行相应的修改insertContentInLine(NginxConf, serve, 59);function insertContentInLine(filePath, content, lineIndex) {// 创建读取文件的流const readStream = fs.createReadStream(filePath);const rl = readline.createInterface({input: readStream,output: process.stdout,terminal: false});let lines = [];let currentLineIndex = 1;rl.on('line', line => {lines.push(line);if (currentLineIndex === lineIndex) {lines.push(content);}currentLineIndex++;});rl.on('close', () => {// 将修改后的内容写回文件fs.writeFileSync(filePath, lines.join('\n'));console.log(`内容已成功插入到第 ${lineIndex}`);});
}
2.2.5 重启nginx

对nginx进行重启

  • 进入nginx安装目录
  • 执行nginx -s reload重启
 const reloadCommand='nginx -s reload'let NginxPath='D:\\前端开发工具\\nginx-1.24.0'exec(`cd ${NginxPath} && ${reloadCommand}`, (error, stdout, stderr) => {if (error) {res.send({msg:error})return;}res.send({msg:'项目打包成功、修改名称成功、复制文件到nginx成功、配置成功、重启成功'})});

现在你就实现了点击一键部署项目在本机中了

2.2.6 完整代码

完整代码如下

const { exec } = require('child_process');
const path = require('path');
const fs = require('fs');
const readline = require('readline');
function copyFolderRecursiveSync(source, target) {// 判断源文件夹是否存在if (!fs.existsSync(source)) {console.log(`源文件夹 ${source} 不存在`);return;}// 创建目标文件夹(如果不存在)if (!fs.existsSync(target)) {fs.mkdirSync(target);}// 读取源文件夹中的内容const files = fs.readdirSync(source);files.forEach(file => {const srcFile = path.join(source, file);const tgtFile = path.join(target, file);// 判断文件是文件夹还是文件if (fs.lstatSync(srcFile).isDirectory()) {// 如果是文件夹,递归复制子文件夹copyFolderRecursiveSync(srcFile, tgtFile);} else {// 如果是文件,直接复制到目标文件夹fs.copyFileSync(srcFile, tgtFile);}});
}function insertContentInLine(filePath, content, lineIndex) {// 创建读取文件的流const readStream = fs.createReadStream(filePath);const rl = readline.createInterface({input: readStream,output: process.stdout,terminal: false});let lines = [];let currentLineIndex = 1;rl.on('line', line => {lines.push(line);if (currentLineIndex === lineIndex) {lines.push(content);}currentLineIndex++;});rl.on('close', () => {// 将修改后的内容写回文件fs.writeFileSync(filePath, lines.join('\n'));console.log(`内容已成功插入到第 ${lineIndex}`);});
}//暴露接口
router.post('/build/app',(req,res)=>{let {TotalPath,port,buildName}=req.body// let appPath='D:\OneDrive\桌面\练习项目\学生信息-react\create'const command = 'npm run build';const reloadCommand='nginx -s reload'const serve=`   server {listen       ${port};server_name  localhost;location / {root   html/${buildName};index  index.html index.htm;}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}}`// 使用 child_process.exec 函数执行命令let NginxPath='D:\\前端开发工具\\nginx-1.24.0'// d:\前端开发工具\nginx-1.24.0\conf\nginx.conflet NginxConf=NginxPath+'\\'+'conf'+'\\'+'nginx.conf'let buildPath=TotalPath+'\\'+'dist'let newPath=TotalPath+`\\${buildName}`const directoryPath = NginxPath+`\\html\\${buildName}`;exec(`cd ${TotalPath} && ${command}`, (error, stdout, stderr) => {if (error) {res.send({msg:error})return;}fs.rename(buildPath, newPath, (err) => {if (err) res.send({msg:error});fs.mkdir(directoryPath, { recursive: true }, err => {if (err) {res.send({msg:error})console.error(`无法创建文件夹 ${directoryPath}: ${err}`);return;}console.log(`文件夹 ${directoryPath} 已成功创建`);copyFolderRecursiveSync(newPath, directoryPath );insertContentInLine(NginxConf, serve, 59);exec(`cd ${NginxPath} && ${reloadCommand}`, (error, stdout, stderr) => {if (error) {res.send({msg:error})return;}res.send({msg:'项目打包成功、修改名称成功、复制文件到nginx成功、配置成功、重启成功'})});});});});
})

3.总结

在这个项目中我们学会了以下知识

  • node执行命令
    • exec()执行
  • node修改文件夹名称
    • fs.rename()
  • node 复制文件到指定目录下
    • fs.copyFileSync
  • node 向文件中插入内容

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/34891.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android Studio中HAXM安装失败的解决方案(HAXM installation failed)

文章目录 错误示例Hyper-VWindows SandboxWindows Hypervisor Platform&#xff08;Windows 虚拟化监控程序平台&#xff09; 出现原因解决方法虚拟机平台方案一方案二方案三 错误示例 表明HAXM (Hardware Accelerated Execution Manager)安装失败了。HAXM是一个硬件辅助虚拟化…

FPGA SATA高速存储设计

今天来讲一篇如何在fpga上实现sata ip&#xff0c;然后利用sata ip实现读写sata 盘的目的&#xff0c;如果需要再速度和容量上增加&#xff0c;那么仅仅需要增加sata ip个数就能够实现增加sata盘&#xff0c;如果仅仅实现data的读写整体来说sata ip设计比较简单&#xff0c;下面…

车载系统类 UI 风格品质非凡

车载系统类 UI 风格品质非凡

数据资产与云计算深度融合:借助云计算技术,优化数据存储、高效处理并创新应用,驱动企业数字化转型

目录 一、引言 二、数据资产与云计算深度融合的必要性 1、数据资产的重要性 2、云计算技术的优势 三、云计算技术在数据资产管理中的应用 1、数据存储的优化 2、数据处理的高效性 3、数据应用的创新 四、云计算驱动企业数字化转型的实践案例 案例一&#xff1a;金融行…

【SpringBoot Web框架实战教程(开源)】01 使用 pom 方式创建 SpringBoot 第一个项目

导读 这是一系列关于 SpringBoot Web框架实战 的教程&#xff0c;从项目的创建&#xff0c;到一个完整的 web 框架&#xff08;包括异常处理、拦截器、context 上下文等&#xff09;&#xff1b;从0开始&#xff0c;到一个可以直接运用在生产环境中的web框架。而且所有源码均开…

MySQL进阶-索引-使用规则-最左前缀法则和范围查询

文章目录 1、最左前缀法则2、启动mysql3、查询tb_user4、查看tb_user的索引5、执行计划 profession 软件工程 and age31 and status 06、执行计划 profession 软件工程 and age317、执行计划 profession 软件工程8、执行计划 age31 and status 09、执行计划 status 010、执行…

方法的其他形式——方法使用时常见的问题

示例&#xff1a; public class MethodDemo02 {public static void main(String[] args) {//目标&#xff1a;掌握按照方法的实际业务需求不同&#xff0c;设计出合理的方法形式来解决问题//需求&#xff1a;打印三行Hello World.printfHelloWorld();System.out.println("…

K210视觉识别模块学习笔记6: 识别苹果_图形化操作函数_

今日开始学习K210视觉识别模块: 图形化操作函数 亚博智能 K210视觉识别模块...... 固件库: canmv_yahboom_v2.1.1.bin 训练网站: 嘉楠开发者社区 今日学习如何在识别到目标的时候添加图形化操作:(获取坐标、框出目标等) 在识别苹果的基础上 学习与添加 这些操…

C# 入门—实现 Hello, World!

目录 一、.net 平台 二、.net 都能干什么&#xff1f; 三、.net 两种交互模式 四、使用 VS Code 开发 C# 程序 五、实现 Hello, World! 一、.net 平台 下载 .NET(Linux、macOS 和 Windows) (microsoft.com) .NET 简介 - .NET | Microsoft Learn C# :一种编程语言,可以开…

未来出行新选择——加油宝APP,让您的每一次加油都充满智慧与便捷!

一、前言 随着科技的飞速发展&#xff0c;智能手机已经成为我们生活中不可或缺的一部分。为了满足广大车主对便捷、高效加油服务的需求&#xff0c;我们倾力打造了全新的加油宝APP。这款APP不仅为您提供一站式的加油服务&#xff0c;还融合了多项创新功能&#xff0c;让您的出…

C语言入门系列:特殊的main函数和exit函数

文章目录 一&#xff0c;main函数二&#xff0c;exit函数1&#xff0c;exit函数2&#xff0c;atexit()函数2.1 atexit函数的简介2.2 atexit注册的函数一定会被调用吗2.2.1 正常退出测试2.2.2 异常退出测试 一&#xff0c;main函数 一个C程序至少包含一个函数&#xff0c;这个函…

机器学习Python代码实战(二)分类算法:k-最近邻

一.k-最近邻算法步骤 1.选择适当的k值。它表示在预测新的数据点时要考虑的邻居数量。 2.计算距离。计算未知点与其他所有点之间的距离。常用的距离计算方法主要有欧氏距离&#xff0c;曼哈顿距离等。 3.选择邻居。在训练集中选择与要预测的数据点距离最近的k个邻居。 4.预测…

随机步问题

随机步问题 1.题目简介2.题目分析3.创建变量4.主程序5.程序效果6.程序可以改进的点 1.题目简介 2.题目分析 数组初始化 生成随机方向 判断程序结束的标志 当前元素为Z&#xff0c;或者四个方向都堵住了 3.创建变量 arry[ROW][COL]创建二维数组 _Bool a,b,c,d判断是否会出现四…

thinksboard新建菜单

1.打开目录\thingsboard\ui-ngx\src\app\modules\home\pages新增npages文件夹 2.新增npages.module.ts以及npages-routing.module.ts控制文件&#xff0c;以及页面展示文件npages.component.html,npages.component.scss,npages.component.ts 3.打开npages.component.ts文件&…

最新AI智能聊天对话问答系统源码(详细图文搭建部署教程)+AI绘画系统,DALL-E3文生图, Whisper TTS 语音识别,文档分析

一、人工智能 随着人工智能技术的持续进步&#xff0c;AI绘画已经发展成为一个日益成熟的领域。越来越多的人开始尝试使用AI绘画软件来创作艺术作品。尽管这些AI绘画软件对绘画领域产生了显著影响&#xff0c;但它们并不会完全取代画师。与传统手绘不同&#xff0c;AI绘画可以…

【第2章】MyBatis-Plus代码生成器

文章目录 前言一、安装二、生成方式1.DefaultQuery (元数据查询)2.存在问题 三、快速生成1. 生成代码2. 目录结构 四、交互式总结 前言 全新的 MyBatis-Plus 代码生成器&#xff0c;通过 builder 模式可以快速生成你想要的代码&#xff0c;快速且优雅&#xff0c;跟随下面的代…

Pikachu 靶场 SSRF 通关解析

前言 Pikachu靶场是一种常见的网络安全训练平台&#xff0c;用于模拟真实世界中的网络攻击和防御场景。它提供了一系列的实验室环境&#xff0c;供安全专业人士、学生和爱好者练习和测试他们的技能。 Pikachu靶场的目的是帮助用户了解和掌握网络攻击的原理和技术&#xff0c;…

揭秘软文发稿秘诀:打造高效推广营销

你是否有在看一篇文章时&#xff0c;可能明知道它是一则广告但仍心甘情愿的继续了解下去&#xff0c;这样的文章大概率就是一篇软文&#xff0c;在当今信息爆炸的时代&#xff0c;软文作为一种有效的推广营销手段&#xff0c;已经成为各大企业、品牌争相使用的利器。然而&#…

关于VMware遇到的一些问题

问题一&#xff1a;打不开磁盘…或它所依赖的某个快照磁盘&#xff0c;开启模块DiskEarly的操作失败&#xff0c;未能启动虚拟机 解决方法&#xff1a; 首先将centos 7关机&#xff0c;然后把快照1删掉 然后打开虚拟机所在目录&#xff0c;把提示的000001.vmdk全部删除&…

Linux:系统引导过程与服务控制

目录 一、linux 系统引导过程 1.1、引导过程总览 1.2、系统初始化进程 &#xff08;centos 6和7 的区别&#xff09; 1.2.1、centos 6 的引导过程 init 进程 1.2.2、centos 7(systemd进程) 二、MBR、GRUB菜单、忘记密码故障修复 2.1、修复MBR扇区故障 模拟故障 重启…