前端部署到服务器上运行,通常不是把整个前端工程放到服务器上跑起来,而是本地构建出静态文件,把产物目录交给服务器上已有的 web 服务器托管。先确认三件事:构建产物目录在哪、服务器上放到哪个路径、谁在监听 80/443。这三件事都有明确输出可以核对,不需要凭感觉。
判断方向:前端上线只做静态托管,不在服务器上执行开发服务器。先看构建日志打印的产物目录,再看 nginx 的 root 是否指向该目录,最后用 curl 比对页面引用的 assets 文件名与服务器上实际文件是否一致。对不上,问题多半在上传环节或 root 配置,不在业务代码。项目若要求服务端渲染,托管方式不同,需要按框架自身的运行要求另行确认。
怎么把前端部署到服务器上:先把能核对的事实摆清楚
对象和前提:前端项目能在本地跑通构建命令;服务器能用 SSH 登录,并且有 sudo 权限或已经装了 web 服务器;域名和证书属于另一环节,先让 IP 能访问通再说。
需要先拿到的是三类能核对的信息:构建日志最后打印的输出目录、服务器上的目标目录内容、web 服务器版本和配置目录位置。这几个命令执行完就有结果,不依赖判断。
# 1. 本地:确认构建产物目录(Vite 默认 dist,CRA 默认 build,以日志输出为准)
cd /path/to/project
npm run build
ls -l dist
# 正常应看到 index.html 和 assets/ 目录
# 2. 服务器:确认已有 web 服务器和站点目录
ssh user@your-server
nginx -v # 有版本输出说明已安装
ls /usr/share/nginx/html # 默认站点目录,看里面有没有 index.html
ls /etc/nginx/conf.d/ # 站点配置常见位置,其他发行版可能在 sites-enabled
可以核对的现象:构建日志最后几行会列出输出文件;ls dist 里有没有 index.html;nginx -v 有没有版本号;配置目录里有没有能被主配置 include 的 .conf 文件。这些都是命令跑完就写在屏幕上的东西。
怎么把前端部署到服务器上最容易搞错的一点
最常见的误解是“部署就是把项目传到服务器上,执行 npm install 再 npm run dev”。前端代码最终在浏览器里执行,服务器只需要把静态文件发出去;开发服务器带热更新、代理等能力,通常不适合作为对外入口。
能把两种情况区分开的检查动作:在服务器上执行下面这条命令,再到本地列出构建产物的文件名,两边带 hash 的文件名应当对得上。
curl -s http://127.0.0.1/ | grep -o 'assets/[^"]*' | head
# 本地对照
ls dist/assets | head
对得上,说明走的是静态托管;对不上,或者 curl 返回 404、默认欢迎页,说明 nginx 的 root 没指到产物目录,或者产物根本没上传。另一个分界点是看响应头 curl -I http://127.0.0.1/ 里的 Server 字段,如果返回的明显是开发服务器特征,那就是把开发服务器暴露出去了。

怎么把前端部署到服务器上:一个照着就能做完的做法
下面按“本地构建 + rsync 上传 + nginx 托管”走一遍,路径、用户名、域名都按实际替换。
# 1. 本地项目根目录构建
npm ci
npm run build
# 2. 上传产物(--delete 会清理目标目录里的旧文件,先确认它是专用目录)
rsync -avz --delete dist/ user@your-server:/var/www/site/
# 3. 服务器上确认文件和权限
ssh user@your-server
ls /var/www/site # 应看到 index.html、assets/
sudo chown -R www-data:www-data /var/www/site # 用户以 nginx.conf 里 user 指令为准
sudo chmod -R 755 /var/www/site
然后写站点配置。不要把 index.html 设成长缓存,否则发版后用户可能拿到旧入口。
# /etc/nginx/conf.d/site.conf
server {
listen 80;
server_name example.com; # 没有域名时先写服务器 IP
root /var/www/site;
index index.html;
location / {
try_files $uri $uri/ /index.html; # 单页应用路由回退
}
location /assets/ {
expires 7d;
add_header Cache-Control "public";
}
location = /index.html {
add_header Cache-Control "no-cache";
}
}
sudo nginx -t # 期望看到 syntax is ok / test is successful
sudo systemctl reload nginx # 无输出通常即成功
curl -I http://127.0.0.1/ # 期望 HTTP/1.1 200 OK,Content-Type: text/html
每一步该看到什么:构建结束打印产物清单;rsync 结束打印传输的文件数量;nginx -t 打印 syntax is ok 和 test is successful;reload 后 curl 返回 200。如果项目要挂在子路径(例如 /app/),构建时先设置 base: '/app/'(Vite)或 homepage(CRA),nginx 的 location 也要同步,两边不一致会表现为静态资源 404。
怎么把前端部署到服务器上:怎么验证结果对不对
验证不要只看首页能不能打开,按下面几条依次走一遍,每条都有明确的正常结果。
curl -I http://127.0.0.1/返回 200,Content-Type 为 text/html。- 把前面 grep 到的文件名拼进去:
curl -I http://127.0.0.1/assets/<构建产物文件名>返回 200,Content-Type 对应 JS 或 CSS;返回 404 说明上传路径或 root 不一致。 - 前端路由刷新:
curl -I http://127.0.0.1/某个前端路由应返回 200 而不是 404,说明 try_files 回退生效。 - 浏览器打开页面,开发者工具 Network 里 JS、CSS 全为 200,Console 无 404;再用无痕窗口开一次,排除本地缓存干扰。
- 日志位置:
/var/log/nginx/access.log能看到对应请求,/var/log/nginx/error.log没有 permission denied 或 open() 失败。
正常结果的样子是:状态码 200、响应体就是 index.html 的内容、静态资源按带 hash 的文件名取到、刷新子路由不出 404。哪一条不满足就回到对应环节查:root 指错、文件没上传、目录权限不可读、或者 base 与访问路径不一致。