从零到上线:全栈项目部署全流程实战

代码写完了,浏览器里跑得飞快,可怎么把它变成别人也能访问的产品?这篇把部署的全流程捋一遍:部署到底在部署什么、方案怎么选、服务器域名备案、HTTPS、Nginx 反向代理、宝塔面板运维,一条龙讲清楚。


先想清楚:部署到底在部署什么?

一个前后端分离的项目,上线后其实跑着三样东西:

组成部分 内容 例子
前端 npm run build 产出的 dist/ 静态资源 HTML / CSS / JS / 图片
后端 提供 /api 接口的服务进程 NestJS / Express / Node 服务
数据库 存数据的地方 MySQL / PostgreSQL / Supabase

很多人以为"部署"就是把代码传上去,其实是要把这三样分别安排妥当,再用一层反向代理把它们串起来。

一句话理解前端产出:React / Vue 项目 npm run builddist/ 里的静态文件,交给任意静态服务器(Nginx / 对象存储 / Vercel)就能跑。


⭐ 重点:一次访问请求的完整旅程

部署前,先建立整篇文章最重要的一张图------用户输入网址到页面加载完成,请求到底经历了什么。之后每一步都是在给这张图"填空"。

bash 复制代码
用户在浏览器输入 www.yourdomain.com
        │
        ▼
① 浏览器(输入域名)
        │
        ▼
② DNS 解析:域名 → 服务器公网 IP(如 47.100.x.x)
        │
        ▼
③ 安全组 / 防火墙:放行 80 / 443 端口?
        │  没开放 → 连接直接失败(转圈 / 超时)
        ▼
④ Nginx 守门(SSL 证书 + 路由分发)
        │
        ├── 静态文件路径(/ .js .css 图片)
        │     → 直接读 dist/ 里的文件返回,浏览器渲染出页面
        │
        └── /api 开头
              → 反向代理转发给后端(127.0.0.1:3001)
              → 后端处理完,数据原路返回

① 浏览器:输入域名

用户只记域名,不记 IP。输入 www.yourdomain.com,浏览器发起 HTTPS 请求------但浏览器现在还不知道服务器在哪

② DNS 解析:域名 → 服务器公网 IP

DNS 就像全球电话簿 :把域名 www.yourdomain.com 翻译成服务器的公网 IP (如 47.100.x.x)。浏览器拿到 IP 后,向这个 IP 发起 TCP 连接。

③ 安全组 / 防火墙:放行 80/443 端口

这是云服务器上的两道"门卫":

  • 云厂商安全组:控制台里配置,放行入站规则。
  • 系统防火墙(ufw / firewalld):服务器内部再拦一道。

只放行 80(http)443(https) 两个端口,其他端口对公网全部关闭

⚠️ 端口没开放的表现是:连接超时、一直转圈,而不是"页面 404"。这也是排查"为什么访问不了"的第一步------先去安全组看端口放没放。

这也是后端安全的根基:后端监听 127.0.0.1:3001公网根本打不到它,只有 Nginx 能通过内网访问。

④ Nginx 守门:SSL 终结 + 路由分发

请求终于进入服务器,到达 Nginx(监听 80/443)。Nginx 做两件事:

  1. SSL 终结:先解密 HTTPS(如果有 SSL 证书),后面和后端通信都是明文内网,不影响。
  2. 路由分发 :看请求路径,分两路------
请求类型 Nginx 怎么处理
静态文件//app.js/style.css、图片) 自己直接处理 :从磁盘读 dist/ 打包好的静态资源返回,浏览器渲染出页面
/api 开头/api/todos 自己不处理 :把请求反向代理 转发给后端服务(127.0.0.1:3001),后端算完返回 JSON,Nginx 原路送回

理解 Nginx 的正确姿势

Nginx 是"分发器",不是"中转站"。

  • 静态资源它给得了:本地磁盘就有,直接读出来返回,快。
  • API 它给不了:业务逻辑在后端,它只负责"转手"给后端,再传回来。
  • 用户全程只接触 Nginx,看不到后端端口------这就是反向代理(服务藏在代理后面)。

大白话总结

浏览器输网址 → DNS 查到服务器 IP → 防火墙放行端口 → Nginx 守门

  • 页面资源:直接读 React 打包好的 dist 静态文件返回
  • 接口请求:反向代理转发给后端程序

这个流程图里第 ④ 步 Nginx 的分流,就是后面「第五步:Nginx 反向代理」要手把手搭建的核心,先记住整体,再看细节。


方案怎么选:Vercel 还是国内云?

国外路线:Vercel + Supabase(省事但"固定")

  • Vercel 是前端的"一键托管",git push 就自动部署,自带域名和 HTTPS。
  • Supabase 提供后端即服务(PostgreSQL + Auth + Storage)。
  • 适合 Next.js 全家桶项目,几乎不用配服务器。

但它的代价是"比较固定" :Vercel 主要是给 Next.js 这类框架用的,Node 自定义后端、非 Next.js 项目就不太好搬;而且服务器在海外,国内访问慢、有被墙风险

国内路线:腾讯云 / 阿里云(可控但流程多)

  • 买一台轻量应用服务器(Linux),自己装环境、自己配。
  • 需要走域名备案 (10~20 天)、配 HTTPS、用 Nginx / 宝塔 做部署和反向代理。
  • 可控性强、国内访问快,适合正式项目和要"运维能力"的面试加分。

怎么选(决策表)

场景 推荐
Next.js + Supabase、想快速上线、不在乎访问速度 Vercel + Supabase
前后端分离、要控制服务器、国内用户多 腾讯云/阿里云 + 宝塔
预算紧张、只练手 免费部署平台(Vercel / Render / 免费对象存储托管静态站)

第一步:买服务器

国内主流是腾讯云 / 阿里云的「轻量应用服务器」

  • 轻量应用服务器:开箱即用,套餐里自带带宽和固定流量,选好镜像(如 Ubuntu / CentOS)就能 SSH 登录,适合个人项目。
  • 全量 ECS / CVM:更灵活但更贵,配置需要自己动手,适合有运维经验的人。
bash 复制代码
# 登录服务器
ssh root@你的服务器公网IP

登录后先干两件事:更新系统、建一个非 root 用户(安全),然后装运行时。

💡 小建议:新手第一台服务器买轻量应用服务器就够,别一上来上 ECS 全量机,贵且配置繁琐。


第二步:域名 + ICP 备案

为什么必须备案?

国内服务器上绑定的域名必须 ICP 备案(工信部登记),这是硬性要求。流程:

  1. 买个域名(腾讯云 / 阿里云都能买,.com 一年几十块)。
  2. 在云厂商控制台提交备案,上传身份证等资料。
  3. 审核 10~20 天,期间域名不能用国内服务器访问。

⚠️ 大坑:先备案再买服务器 ?不对,是先买服务器再备案 (备案要填服务器信息)。但备案要等 10~20 天,所以买服务器 → 立刻提交备案,等备案期间先把代码和构建流程准备好,时间刚好不浪费。

不想等备案怎么办?

  • 香港 / 海外节点的服务器(不用备案,但国内访问慢、稳定性差)。
  • 纯练手就用 Vercel 这类免备案平台。

第三步:配置 HTTPS(SSL)

HTTP vs HTTPS

HTTPS = HTTP + SSL/TLS 层,主要解决两件事:

  1. 加密:数据在传输中加密,防窃听、防篡改。
  2. 身份验证:通过 SSL 证书验证服务器身份,防中间人攻击。

端口约定

  • 80:HTTP 默认端口
  • 443:HTTPS 默认端口

怎么配证书

最省事的是用免费证书

bash 复制代码
# Let's Encrypt + certbot,一条命令自动签证书并配置 Nginx
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d yourdomain.com

腾讯云 / 阿里云也有免费的 DV 证书,控制台申请后下载,放进 Nginx 配置即可。

nginx 复制代码
server {
    listen 443 ssl;
    server_name yourdomain.com;

    ssl_certificate     /etc/nginx/ssl/yourdomain.com.pem;
    ssl_certificate_key /etc/nginx/ssl/yourdomain.com.key;

    # 80 端口跳转 https
    # server { listen 80; return 301 https://$host$request_uri; }
}

第四步:部署后端(Node / NestJS)

把代码传到服务器,装依赖,用进程管理器跑起来:

bash 复制代码
git clone 你的仓库地址
cd 项目后端目录
npm install
npm run build        # TS 项目编译(如 NestJS)
# 用 pm2 常驻运行,崩溃自动重启
npm i -g pm2
pm2 start dist/main.js --name api
pm2 save             # 保存进程列表,开机自启

后端默认跑在 127.0.0.1:3001(注意:只绑内网地址,不直接暴露公网,由 Nginx 在前面转发)。


第五步:Nginx 反向代理(核心)

前端 /api 怎么访问后端?跨域吗?

这是前后端分离部署里最关键的一环

先记住一个概念------同源 = 协议 + 域名 + 端口都相同,浏览器只允许同源请求(否则跨域)。

  • 开发时 :前端跑在 5173,后端在 3001,端口不同 → 跨域,要配 CORS 或 vite proxy。
  • 生产时 :前端页面和 /api 接口都在同一个域名 下(https://yourdomain.comhttps://yourdomain.com/api/...),同协议同域名同端口 → 不存在跨域,不用配 CORS。

所以生产的正确姿势是:Nginx 托管前端静态文件,并把 /api 反向代理到后端的 3001 端口

具体配置

nginx 复制代码
server {
    listen 80;
    server_name yourdomain.com;

    # 1. 前端静态资源(npm run build 出来的 dist/)
    root /var/www/myapp/dist;
    index index.html;

    # 2. /api 反向代理到后端
    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;
    }
}
  • 用户访问 https://yourdomain.com/ → Nginx 返回 dist/ 里的前端页面。
  • 前端请求 https://yourdomain.com/api/todos → Nginx 转发给 127.0.0.1:3001/api/todos → 后端返回 JSON。

⚠️ 注意 location /apilocation /优先级 :带 /api 前缀的请求一定要先匹配到反向代理,别被静态文件规则吃掉。

部署流程串起来

bash 复制代码
# 前端:构建出静态文件
cd 前端目录 && npm run build   # 产出 dist/

# 后端:构建并启动
cd 后端目录 && npm run build && pm2 start dist/main.js --name api

# Nginx:把 dist/ 指向配置里的 root,reload 生效
sudo nginx -t && sudo systemctl reload nginx

第六步:宝塔面板(可视化运维)

如果你不想全程敲命令,**宝塔面板(BT Panel)**是把服务器变成"图形化操作系统后台"的工具。

  • 一键安装 Nginx / MySQL / Node 等环境。
  • 网页上可视化操作:建站点、配伪静态、申请 SSL 证书、看日志、定时任务。
  • 适合快速上手 + 日常运维。
bash 复制代码
# 官方一条命令安装(装完会给你面板地址和账号密码)
wget -O install.sh https://download.bt.cn/install/install_6.0.sh && bash install.sh

⚠️ 安全提醒:宝塔面板一定要改默认端口和密码,并只对可信 IP 开放,否则容易被扫描爆破。面板本身也能配 HTTPS。


安全清单(上线前必查)

  1. 关闭 root 直接 SSH 登录,用密钥登录 + 普通用户。
  2. 后端不要直接暴露公网,一律 Nginx 转发。
  3. 宝塔面板换端口、改密码、绑 IP
  4. 给服务器做基础防护:改 SSH 端口、装防火墙只放行 80/443/22
  5. 数据库(MySQL 等)只监听内网,不对外开端口。
  6. 敏感配置(数据库密码、API Key)用环境变量或 .env别提交进 git

避坑清单(建议收藏)

  1. 备案要 10~20 天 → 先买服务器、立刻提交备案,期间准备构建和部署脚本。
  2. 国内服务器不备案上不了线 → 赶时间就用香港/海外节点或 Vercel。
  3. 开发能跑、生产 404 → 检查 Nginx root 是否指向 dist/location /api 优先级是否正确。
  4. 页面能开、接口跨域 → 生产下前后端同域就不该跨域,多半是没走 Nginx 代理,直接请求了 3001 端口。
  5. 服务器重启后服务没了 → 用 pm2 save + pm2 startup 或 systemd 让进程开机自启。
  6. HTTPS 浏览器报不安全 → 证书没配对或证书过期,用 certbot renew 自动续期。

小结

部署一个前后端分离项目,本质就四步:

前端 dist/ 交给 Nginx 托管 → 后端进程用 pm2 常驻 → Nginx 把 /api 反向代理到后端 → 外面套一层 HTTPS。

方案上,省事选 Vercel + Supabase(Next.js 全家桶) ,可控选国内云 + 宝塔面板 。真正花时间的不是"传文件",而是备案、反向代理、安全和 HTTPS 这几件别人看不见的事------把它们都搞定,项目才算真的"上线"了。


技术栈:Linux · Nginx · 宝塔面板 · pm2 · Let's Encrypt · Vercel · Supabase · 腾讯云/阿里云

相关推荐
honkun622 分钟前
vue 表格组件 vxe-table 实实现专业记账凭证编辑表格与自动汇总
前端·javascript·vue.js
蛋先生DX39 分钟前
明明都是源码到CPU,各语言中间原理咋不是一个套路?
java·javascript·go
zzzzzz3103 小时前
react-bits:酷炫动效之外,React 组件库还能提供什么
javascript·react.js·动效
web打印社区10 小时前
网页静默打印热敏小票:从 HTML 到出纸的完整指南
前端·javascript·vue.js·electron·pdf·html
专业抄代码选手17 小时前
08|Fiber 上的 `useState`:状态终于属于具体组件
前端·javascript·react.js
默_笙17 小时前
😭 Vibe Coding 翻车实录:AI 编程为什么必须先写"剧本"
前端·javascript
lerhxx17 小时前
我用 R3F 手搓了一个能走进去的 3D 迷宫简历(上):从选型架构到迷宫生成算法
前端·javascript·three.js
鹏多多1 天前
PC 网站接入微信登录,这 10 个坑我替你踩完了!
前端·javascript·vue.js