当前位置: 首页 > news >正文

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 向文件中插入内容

相关文章:

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

文章目录 nodenginx实现对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 项目实…...

【机器学习】基于Gumbel-Sinkhorn网络的“潜在排列问题”求解

1. 引言 1.1.“潜在排列”问题 本文将深入探索一种特殊的神经网络方法,该方法在处理离散对象时展现出卓越的能力,尤其是针对潜在排列问题的解决方案。在现代机器学习和深度学习的领域中,处理离散数据一直是一个挑战,因为传统的神经网络架构通常是为连续数据设计的。然而,…...

create-react-app创建的项目中设置webpack配置

create-react-app 创建的项目默认使用的是 react-scripts&#xff08;存在于node_modules文件夹中&#xff09;来处理开发服务器和构建&#xff0c;它内置了一些webpack相关配置。一般不会暴露出来给开发者&#xff0c;但是在有些情况下我们需要修改下webpack默认配置&#xff…...

【ai】tx2 nx :安装torch、torchvision for yolov5

torchvision 是自己本地构建的验证torchvision nvidia@tx2-nx:~/twork/03_yolov5/torchvision$ nvidia@tx2-nx:~/twork/03_yolov5/torchvision$ python3 Python 3.6.9 (default, Mar 10 2023, 16:46:00) [GCC 8.4.0] on linux Type "help", "copyright",…...

【报错】在终端中输入repo命令后系统未能识别这个命令

1 报错 已经使用curl命令来下载repo工具,但是在终端中输入repo命令后系统未能识别这个命令。 2 分析 通常是因为repo...

【机器学习】K-Means算法详解:从原理到实践

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 K-Means算法详解&#xff1a;从原理到实践引言1. 基本原理1.1 簇与距离度量1.2 …...

解决qiankun项目与子应用样式混乱问题

背景 qiankun项目用的是Vue2Antdesign2&#xff0c;但其中一个子应用用的是Vue3Antdesign4。集成之后发现子应用的样式混乱&#xff0c;渲染的是Antdesign2的样式。 解决 以下步骤在子应用里操作 1. 在main.js引入ConfigProvider &#xff0c;在app全局注册ConfigProvider …...

黑产当前,如何识别异常图片?

在这个人人都是创作者的年代&#xff0c; UGC 已成为诸多平台的重要组成。 有利益的地方就会有黑产存在&#xff0c; 不少 UGC 平台都被黑产「薅羊毛」搞的心烦意乱&#xff0c; 用户传的图片&#xff0c;怎么就变成视频链接了&#xff1f; 正常运营的平台&#xff0c;为何流量…...

数据模型(models)

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 &#xff08;1&#xff09;在App中添加数据模型 在app1的models.py中添加如下代码&#xff1a; from django.db import models # 引入django.…...

【CS.AL】算法核心之贪心算法 —— 力扣(LeetCode)743. 网络延迟时间 - Dijkstra算法题解

文章目录 题目描述References 题目描述 743. 网络延迟时间 - 力扣&#xff08;LeetCode&#xff09; 有 N 个网络节点&#xff0c;标记为 1 到 N。 给定一个列表 times&#xff0c;其中 times[i] (u, v, w) 表示有一条从节点 u 到节点 v 的时延为 w 的有向边。 现在&#xf…...

25、架构-微服务的驱动力

微服务架构的驱动力可以从多方面探讨&#xff0c;包括灵活性、独立部署、技术异构性、团队效率和系统弹性等。 灵活性和可维护性 灵活性是微服务架构的一个主要优势。通过将单体应用拆分成多个独立的微服务&#xff0c;开发团队可以更容易地管理、维护和更新各个服务。每个微…...

JeecgFlow事件网关概念及案例

事件网关 通常网关基于连线条件决定后续路径&#xff0c;但事件网关有所不同&#xff0c;其基于事件决定后续路径。事件网关的每条外出顺序流都需要连接一个捕获中间事件。 事件网关只有分支行为&#xff0c;流程的走向完全由中间事件决定。可以从多条候选分支中选择事件最先达…...

使用鸿蒙HarmonyOs NEXT 开发 快速开发 简单的购物车页面

目录 资源准备&#xff1a;需要准备三张照片&#xff1a;商品图、向下图标、金钱图标 1.显示效果&#xff1a; 2.源码&#xff1a; 资源准备&#xff1a;需要准备三张照片&#xff1a;商品图、向下图标、金钱图标 1.显示效果&#xff1a; 定义了一个购物车页面的布局&#x…...

iOS 中 attribute((constructor)) 修饰的函数

开发环境声明&#xff1a;此文描述的 attribute((constructor)) 特指使用 Objective-C 开发 iOS、MacOS&#xff0c;Swift 语言不支持这种属性修饰符。 初识 attribute((constructor)) 在 Objective-C 开发中&#xff0c;attribute((constructor)) 是一个 GCC 和 Clang 编译器…...

原生js实现图片预览控件,支持丝滑拖拽,滚轮放缩,放缩聚焦

手撸源代码如下&#xff1a;注释应该很详细了&#xff0c;拿去直用 可以放到在线编辑器测试&#xff0c;记得修改图片路径 菜鸟教程在线编辑器 <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" conten…...

C语言入门课程学习笔记9:指针

C语言入门课程学习笔记9 第41课 - 指针&#xff1a;一种特殊的变量实验-指针的使用小结 第42课 - 深入理解指针与地址实验-指针的类型实验实验小结 第43课 - 指针与数组&#xff08;上&#xff09;实验小结 第44课 - 指针与数组&#xff08;下&#xff09;实验实验小结 第45课 …...

借助 Cloudflare D1 和 Drizzle 在 Astro 上实现全栈

使用 Cloudflare D1 和 Drizzle ORM 将后端添加到 Astro 项目的分步指南 文章目录 安装 Astro添加 Cloudflare 适配器部署到 Pages安装 wrangler 并登录创建 D1 数据库创建 wrangler.toml 文件将 .wrangler 添加到 .gitignore更新 astro.config.ts安装 Drizzle 依赖项创建 driz…...

SUSE linux 15的网络管理

1 手工配置网络 wicked提供了一种新的网络配置框架。自SUSE 12起&#xff0c;SUSE使用了新的网络管理工具wicked&#xff0c;这个是区别与其他常见发行版的。常见的发行版目前大多使用的是NetworkManager服务进行网络管理。 1.1 wicked网络配置 传统网络接口管理面临的挑战之…...

海康威视-下载的录像视频浏览器播放问题

目录 1、播放异常比对 2、视频编码检查 2.1、正常视频解析 2.2、海康视频解析 2.3、比对工具 3、转码 3.1、maven依赖 3.2、实现代码 4、验证 在前面的文章&#xff08;海康威视-按时间下载录像文件_海康威视 sdk 下载录像 大小0-CSDN博客&#xff09;中&#xff0c;通…...

养殖自动化管理系统:开启智慧养殖新篇章

在现代农业的快速演进中&#xff0c;养殖业正经历一场前所未有的技术革命。养殖自动化管理系统&#xff0c;作为这场变革的前沿科技&#xff0c;正逐步成为推动行业高效、环保、可持续发展的关键力量。本文将深入探讨自动化养殖系统如何通过精准管理、智能监控、数据驱动决策&a…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

群晖NAS如何在虚拟机创建飞牛NAS

套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...

MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释

以Module Federation 插件详为例&#xff0c;Webpack.config.js它可能的配置和含义如下&#xff1a; 前言 Module Federation 的Webpack.config.js核心配置包括&#xff1a; name filename&#xff08;定义应用标识&#xff09; remotes&#xff08;引用远程模块&#xff0…...

如何配置一个sql server使得其它用户可以通过excel odbc获取数据

要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据&#xff0c;你需要完成以下配置步骤&#xff1a; ✅ 一、在 SQL Server 端配置&#xff08;服务器设置&#xff09; 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到&#xff1a;SQL Server 网络配…...