本地跑得好好的项目,怎么让外网用户也能访问?这篇文章用一个真实项目,带你走完从买服务器到上线的全流程。
前言
前端 npm run build 出了 dist,后端 npm run start 能跑接口,数据库也有数据了——然后呢?
然后你需要一台服务器,把它们部署上去。
这篇文章不聊项目代码,只聊一件事:怎么用宝塔面板,把一个前后端分离项目跑在线上。
技术栈:
- 前端:React + Vite → 打包成静态文件
- 后端:Node.js + Express + TypeScript → 编译成 JS 运行
- 数据库:MySQL
- 服务器:腾讯云轻量应用服务器 + 宝塔面板
一、整体架构:先搞清楚请求怎么走
部署之前,先理解用户访问你的网站时,请求是怎么流转的:
用户浏览器
↓
DNS 解析 → 服务器公网 IP
↓
安全组/防火墙 → 放行 80/443 端口
↓
Nginx(入口)
├─ / → 返回前端静态文件(React 打包产物)
└─ /api/* → 反向代理转发给 Node.js 后端
↓
Node.js → MySQL 读写数据
Nginx 是整个部署的核心枢纽,它做两件事:
- 直接返回前端的静态资源(HTML/CSS/JS)
- 把
/api开头的请求转发给 Node.js 后端
这就是所谓的反向代理——用户只跟 Nginx 打交道,不知道后面还有一台 Node.js 服务。
二、买服务器 + 安装宝塔
2.1 购买云服务器
推荐腾讯云轻量应用服务器,新用户最低 35 元/月起步就够用。
购买时注意:
- 操作系统选 CentOS 7.6 或 Ubuntu 20.04(宝塔兼容性好)
- 记住你的 公网 IP,后面全程要用
- 记住你设置的 root 密码
2.2 安装宝塔面板
SSH 连上服务器后,一行命令装宝塔:
# 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),然后设置为默认版本。
验证安装:
node -v
npm -v
如果你的项目用 pnpm,也需要全局安装:
npm install -g pnpm
3.2 创建数据库
宝塔面板 → 数据库 → 添加数据库
填写:
- 数据库名:
time_capsule_production - 用户名:
time_capsule_prod(或自定义) - 密码:生成一个强密码,记下来
- 访问权限:选择 本地服务器(不要选"所有人",不安全)
创建成功后,你就可以用这个账号连接 MySQL 了。
💡 建议同时创建一个
_dev库用于测试,开发和线上互不干扰。
四、上传项目代码
4.1 目录结构规划
在宝塔面板中,网站根目录是 /www/wwwroot/。建议这样组织:
/www/wwwroot/time-capsule/
├── client/ # 前端项目(打包后的 dist 内容直接放这里)
├── server/ # 后端项目
│ ├── dist/ # TypeScript 编译产物
│ ├── node_modules/
│ ├── .env
│ └── package.json
4.2 上传方式
方式一:宝塔文件管理器(简单粗暴)
直接在面板里上传 ZIP 压缩包,然后解压。
方式二:Git 拉取(推荐)
先把代码推到 GitHub/Gitee,然后在服务器上:
cd /www/wwwroot
git clone https://gitee.com/你的仓库名/time-capsule.git
cd time-capsule
后续更新代码只需 git pull,比每次上传文件方便太多。
五、部署后端(Node.js)
5.1 安装依赖 & 编译 TypeScript
cd /www/wwwroot/time-capsule/server
# 安装依赖
npm install
# TypeScript 编译成 JavaScript
npm run build
编译完成后会生成 dist/ 目录,里面的 .js 文件才是 Node.js 真正运行的代码。
5.2 配置环境变量
# 创建 .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 测试运行
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 验证后端接口
curl http://localhost:3001/health
# 应该返回: {"status":"ok"}
curl http://localhost:3001/api/capsules
# 应该返回 JSON 数据
六、部署前端(React)
6.1 打包前端项目
在本地执行(或者在服务器上装好 Node 依赖后打包):
cd client
# 如果需要连接线上 API,修改 .env
echo "VITE_API_URL=http://你的服务器IP" > .env
npm run build
打包完成后,dist/ 目录里就是纯静态的 HTML/CSS/JS 文件。
6.2 上传打包产物
把 dist/ 里的所有文件(不是 dist 文件夹本身)上传到:
/www/wwwroot/time-capsule/client/
最终结构:
/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 手动微调配置
点击站点 → 配置文件,确保关键部分如下:
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
nginx -t # 检查配置语法
nginx -s reload # 重载配置
或者直接在宝塔面板点「保存」自动重载。
八、验证部署
打开浏览器访问 http://你的IP(或域名),应该能看到:
- ✅ 页面正常渲染(前端静态文件由 Nginx 返回)
- ✅ 能看到数据列表(
/api/capsules被转发给 Node.js → MySQL) - ✅ 能创建新数据(POST 请求走反向代理到后端)
# 快速验证 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 后端没启动,或者端口不对。
解决:
# 检查 Node 进程是否在运行
pm2 list
# 查看日志
pm2 logs
Q3:数据库连接失败
原因:.env 里的数据库配置不对,或者 MySQL 没有授权。
解决:
# 在服务器上测试数据库连接
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:
- 宝塔面板 → 网站 → 点击站点 → SSL
- 选择「Let's Encrypt」免费申请证书
- 勾选「强制 HTTPS」
- 提交,自动配置完成
配置后,访问 https://你的域名 即可安全访问。
总结
整个部署流程,核心就五步:
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 数据库
🛠️ 部署工具:腾讯云轻量服务器 + 宝塔面板