一文搞懂宝塔面板部署前后端分离项目(React + Node.js + MySQL)

本地跑得好好的项目,怎么让外网用户也能访问?这篇文章用一个真实项目,带你走完从买服务器到上线的全流程。

前言

前端 npm run build 出了 dist,后端 npm run start 能跑接口,数据库也有数据了------然后呢?

然后你需要一台服务器,把它们部署上去。

这篇文章不聊项目代码,只聊一件事:怎么用宝塔面板,把一个前后端分离项目跑在线上。

技术栈:

  • 前端:React + Vite → 打包成静态文件
  • 后端:Node.js + Express + TypeScript → 编译成 JS 运行
  • 数据库:MySQL
  • 服务器:腾讯云轻量应用服务器 + 宝塔面板

一、整体架构:先搞清楚请求怎么走

部署之前,先理解用户访问你的网站时,请求是怎么流转的:

bash 复制代码
用户浏览器
    ↓
DNS 解析 → 服务器公网 IP
    ↓
安全组/防火墙 → 放行 80/443 端口
    ↓
Nginx(入口)
    ├─ /            → 返回前端静态文件(React 打包产物)
    └─ /api/*       → 反向代理转发给 Node.js 后端
                            ↓
                        Node.js → MySQL 读写数据

Nginx 是整个部署的核心枢纽,它做两件事:

  1. 直接返回前端的静态资源(HTML/CSS/JS)
  2. /api 开头的请求转发给 Node.js 后端

这就是所谓的反向代理------用户只跟 Nginx 打交道,不知道后面还有一台 Node.js 服务。


二、买服务器 + 安装宝塔

2.1 购买云服务器

推荐腾讯云轻量应用服务器,新用户最低 35 元/月起步就够用。

购买时注意:

  • 操作系统选 CentOS 7.6Ubuntu 20.04(宝塔兼容性好)
  • 记住你的 公网 IP,后面全程要用
  • 记住你设置的 root 密码

2.2 安装宝塔面板

SSH 连上服务器后,一行命令装宝塔:

bash 复制代码
# CentOS
yum install -y wget && wget -O install.sh https://download.bt.cn/install/install_6.0.sh && sh install.sh

# Ubuntu
wget -O install.sh https://download.bt.cn/install/install-ubuntu_6.0.sh && sudo bash install.sh

安装完成后会给你:

  • 面板地址http://你的IP:8888/随机路径
  • 用户名 + 密码

⚠️ 记得去云厂商控制台的安全组放行 8888 端口,否则打不开面板。

2.3 登录后第一件事

宝塔面板首次登录会提示安装套件,选择:

  • Nginx(必装)
  • MySQL 5.7 或 8.0(必装)
  • Node.js 版本管理器(在「软件商店」搜索安装)

一键等待安装完成。


三、服务器环境配置

3.1 安装 Node.js

宝塔面板 → 软件商店 → 搜索 Node.js 版本管理器 → 安装

打开 Node.js 版本管理器,安装你需要的版本(比如 v18 或 v20),然后设置为默认版本

验证安装:

bash 复制代码
node -v
npm -v

如果你的项目用 pnpm,也需要全局安装:npm install -g pnpm

3.2 创建数据库

宝塔面板 → 数据库添加数据库

填写:

  • 数据库名:time_capsule_production
  • 用户名:time_capsule_prod(或自定义)
  • 密码:生成一个强密码,记下来
  • 访问权限:选择 本地服务器(不要选"所有人",不安全)

创建成功后,你就可以用这个账号连接 MySQL 了。

💡 建议同时创建一个 _dev 库用于测试,开发和线上互不干扰。


四、上传项目代码

4.1 目录结构规划

在宝塔面板中,网站根目录是 /www/wwwroot/。建议这样组织:

bash 复制代码
/www/wwwroot/time-capsule/
├── client/          # 前端项目(打包后的 dist 内容直接放这里)
├── server/          # 后端项目
│   ├── dist/        # TypeScript 编译产物
│   ├── node_modules/
│   ├── .env
│   └── package.json

4.2 上传方式

方式一:宝塔文件管理器(简单粗暴)

直接在面板里上传 ZIP 压缩包,然后解压。

方式二:Git 拉取(推荐)

先把代码推到 GitHub/Gitee,然后在服务器上:

bash 复制代码
cd /www/wwwroot
git clone https://gitee.com/你的仓库名/time-capsule.git
cd time-capsule

后续更新代码只需 git pull,比每次上传文件方便太多。


五、部署后端(Node.js)

5.1 安装依赖 & 编译 TypeScript

bash 复制代码
cd /www/wwwroot/time-capsule/server

# 安装依赖
npm install

# TypeScript 编译成 JavaScript
npm run build

编译完成后会生成 dist/ 目录,里面的 .js 文件才是 Node.js 真正运行的代码。

5.2 配置环境变量

bash 复制代码
# 创建 .env 文件
cat > .env << 'EOF'
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=time_capsule_prod
DB_PASSWORD=你刚才记下的密码
DB_NAME=time_capsule_production
PORT=3001
EOF

5.3 测试运行

bash 复制代码
node dist/app.js

看到 Server running on http://localhost:3001 说明后端启动成功。

Ctrl + C 停掉,接下来我们用宝塔让它持久运行

5.4 用宝塔的 Node 项目管理器持久运行

宝塔面板 → 网站Node项目添加Node项目

填写:

  • 项目目录:/www/wwwroot/time-capsule/server
  • 启动选项:dist/app.js
  • Node版本:选择你安装的版本
  • 项目端口:3001
  • 包管理器:npm(或 pnpm

点击提交,宝塔会自动帮你:

  • PM2 守护进程(进程挂了自动重启)
  • 开机自启动
  • 日志管理

这比你手动 node dist/app.js 然后用 nohup 挂后台优雅得多。

5.5 验证后端接口

bash 复制代码
curl http://localhost:3001/health
# 应该返回: {"status":"ok"}

curl http://localhost:3001/api/capsules
# 应该返回 JSON 数据

六、部署前端(React)

6.1 打包前端项目

在本地执行(或者在服务器上装好 Node 依赖后打包):

bash 复制代码
cd client

# 如果需要连接线上 API,修改 .env
echo "VITE_API_URL=http://你的服务器IP" > .env

npm run build

打包完成后,dist/ 目录里就是纯静态的 HTML/CSS/JS 文件。

6.2 上传打包产物

dist/ 里的所有文件(不是 dist 文件夹本身)上传到:

bash 复制代码
/www/wwwroot/time-capsule/client/

最终结构:

perl 复制代码
/www/wwwroot/time-capsule/client/
├── index.html
├── assets/
│   ├── index-xxxxx.js
│   └── index-xxxxx.css
└── vite.svg

七、配置 Nginx 反向代理(核心)

这是整个部署最关键的一步。

7.1 添加站点

宝塔面板 → 网站添加站点

  • 域名:填你的域名(如 capsule.example.com),如果没有域名就填服务器 IP
  • 根目录:/www/wwwroot/time-capsule/client
  • PHP版本:选「纯静态」

7.2 配置反向代理

点击站点名 → 反向代理添加反向代理

  • 代理名称:api
  • 目标URL:http://127.0.0.1:3001
  • 发送域名:$host

提交后,宝塔会自动生成 Nginx 配置。

7.3 手动微调配置

点击站点 → 配置文件,确保关键部分如下:

nginx 复制代码
server {
    listen 80;
    server_name capsule.example.com;  # 或你的 IP

    # 前端静态资源
    root /www/wwwroot/time-capsule/client;
    index index.html;

    # API 请求 → 反向代理到 Node.js
    location /api/ {
        proxy_pass http://127.0.0.1:3001;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    # 健康检查接口
    location /health {
        proxy_pass http://127.0.0.1:3001;
    }

    # SPA 路由兜底(React Router 的 history 模式必须有这个)
    location / {
        try_files $uri $uri/ /index.html;
    }
}

几个关键点:

配置项 作用
location /api/ 把所有 /api 开头的请求转发给 Node.js
proxy_pass 转发目标,必须是 127.0.0.1:3001(本机)
try_files $uri $uri/ /index.html SPA 路由兜底,刷新页面不会 404

7.4 重载 Nginx

bash 复制代码
nginx -t        # 检查配置语法
nginx -s reload # 重载配置

或者直接在宝塔面板点「保存」自动重载。


八、验证部署

打开浏览器访问 http://你的IP(或域名),应该能看到:

  1. ✅ 页面正常渲染(前端静态文件由 Nginx 返回)
  2. ✅ 能看到数据列表(/api/capsules 被转发给 Node.js → MySQL)
  3. ✅ 能创建新数据(POST 请求走反向代理到后端)
bash 复制代码
# 快速验证 API 是否通了
curl http://你的IP/api/capsules
curl http://你的IP/health

九、常见问题排查

Q1:页面白屏 / 404

原因:SPA 路由没配置兜底。

解决:确保 Nginx 配置了 try_files $uri $uri/ /index.html;

Q2:API 请求 502 Bad Gateway

原因:Node.js 后端没启动,或者端口不对。

解决:

bash 复制代码
# 检查 Node 进程是否在运行
pm2 list

# 查看日志
pm2 logs

Q3:数据库连接失败

原因:.env 里的数据库配置不对,或者 MySQL 没有授权。

解决:

bash 复制代码
# 在服务器上测试数据库连接
mysql -u time_capsule_prod -p -h 127.0.0.1 time_capsule_production

Q4:安全组 / 防火墙端口没开

宝塔面板 → 安全 → 放行以下端口:

端口 用途
80 HTTP
443 HTTPS
8888 宝塔面板
22 SSH

3306(MySQL)不要对外开放,只允许本机访问。


十、HTTPS 配置(可选但推荐)

有域名的话,强烈建议配置 HTTPS:

  1. 宝塔面板 → 网站 → 点击站点 → SSL
  2. 选择「Let's Encrypt」免费申请证书
  3. 勾选「强制 HTTPS」
  4. 提交,自动配置完成

配置后,访问 https://你的域名 即可安全访问。


总结

整个部署流程,核心就五步:

markdown 复制代码
1. 买服务器 + 装宝塔
2. 装 Node.js / MySQL / Nginx
3. 上传代码 → npm install → npm run build
4. 宝塔 Node 项目管理器启动后端
5. 配置 Nginx 反向代理(/api → Node.js)

宝塔的价值在于:你不需要手动写 Nginx 配置文件、不用手动配 PM2、不用折腾 systemd 服务------它帮你把这些运维操作变成了可视化点击。

但理解背后的原理(Nginx 反向代理、进程守护、静态资源托管)才是真正重要的。宝塔只是工具,原理才是你的核心竞争力。


📁 本文配套项目:React + Vite 前端 + Node.js + Express + TypeScript 后端 + MySQL 数据库

🛠️ 部署工具:腾讯云轻量服务器 + 宝塔面板

相关推荐
Interview Aid1121 小时前
TikTok OA 四题分享|半小时内 AC,题目基本都是实现题
java·开发语言·算法·面试·职场和发展
怕浪猫10 小时前
FDE 最大的浪费不是写出有 bug 的代码,而是漂亮地解决了一个错误的问题
面试·架构·github
黄敬峰12 小时前
Next.js 全栈实战:数据清洗、ORM 设计与 AI Prompt 工程最佳实践
面试·github
雨夜之寂16 小时前
雨夜-现在有办法识别是不是ai文章么
后端·面试
不正经学生18 小时前
C语言动态内存管理(上):堆上的自由与责任
c语言·开发语言·c++·算法·面试
ssshooter18 小时前
AI 时代你不能不知道的 git worktree
前端·后端·面试
CoderYanger19 小时前
A.每日一题:输入单词需要的最少按键次数 Ⅰ+Ⅱ
java·数据结构·算法·leetcode·面试
艾莉丝努力练剑1 天前
【AI大模型接入SDK】SSE协议
c++·学习·面试·大模型·sdk
Rain的Java大神之路1 天前
如何保证接口幂等
java·经验分享·后端·面试·架构