项目部署
我的提示
📌 本章内容适用于对产品操作手册在服务器上进行前后端分离部署,采用的是前后端分离架构,主要使用了Vue3前端 + Node.js后端 + Nginx反向代理,适用的场景包括新服务器部署、服务器迁移、新人上手、项目上线、版本更新等,下面将对项目如何在服务器上部署进行详细解答!
# 一、部署前置准备
1.1 所需资源清单
- 服务器一台(Windows Server)
- 公网IP、域名(可选)
- 完整前端源码、后端源码
- 后端 .env 环境配置文件
- 数据库、账号密码
- SSL证书(HTTPS部署可选)
1.2 服务器端口放行要求
安全组/防火墙必须放行:
- 80 端口(HTTP)
- 443 端口(HTTPS) 后端端口(如3000)无需对外开放,仅本机Nginx代理访问,更安全。
1.3 服务器统一目录规范
D:\server ├─nginx-1.30.4 # Nginx主程序 ├─conf # 配置文件目录 ├─ssl # 证书目录 └─nginx.conf # 配置文件
D:\product
├─admin # 服务器后端程序目录
├─client # 前端项目目录
└─dist # 前端打包dist静态文件
# 二、服务器基础环境安装
2.1 安装 Node.js
- 官网下载 LTS 长期版 Windows(.msi) 安装包 Node (opens new window)
- 默认下一步安装即可
- 安装完成打开 CMD 验证:
node -v
npm -v
2
3
4
2.2 安装 PM2(后端常驻进程工具)
npm install pm2-windows-startup -g # 在Windows上安装PM2程序
pm2 start dist/index.js --name backend # Windows 正确 pm2 启动命令
pm2 status # 查看状态
pm2 restart backend # 修改.env 文件之后重启命令
pm2 stop backend
pm2 save # 保存进程,开机自启
pm2-startup install # 执行开机注册
pm2 delete backend # 删除进程
npm install better-sqlite3
npm install -D @types/better-sqlite3 安装数据库命令(原生 sqlite 驱动,磁盘直接读写,不用全量加载内存)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- 如果后端程序全面更新了,进入admin目录,通过cmd命令进入,重新运行
npm install,然后再运行pm2 restart backend重启
2.3 安装 Nginx(Windows版)
- 下载 Windows 稳定版 Nginx Nginx (opens new window)
- 解压至 D:\nginx
- 禁止放在 C盘、带中文、带空格路径
# 三、后端项目完整部署流程
3.1 上传代码
将后端完整源码上传至:D:\product\admin
3.2 关键配置
编辑 .env 文件
- HOST=0.0.0.0(不能为127.0.0.1,否则Nginx无法代理)
- PORT=3000(与Nginx代理端口一致)
- 数据库账号密码、文件路径、密钥配置正确
3.3 安装依赖
进入D:\product\admin服务器目录,安装依赖,安装命令是npm install
3.4 测试启动
运行命令npm run start
访问接口确认正常后,Ctrl+C 关闭测试进程。
# 四、前端项目打包与部署
4.1 本地打包
本地前端项目执行:npm run build,生成 dist文件夹,然后上传服务器,将 dist 全部上传覆盖至:D:\product\client
4.2 前端生产环境关键配置
必须使用相对路径,由Nginx代理转发,禁止写死IP端口
# 五、Nginx 完整生产配置
5.1 HTTP 标准配置
worker_processes auto;
# worker_rlimit_nofile 20960; Windows不支持,已注释
error_log logs/error.log error;
events {
worker_connections 1024;
multi_accept on;
accept_mutex on;
accept_mutex_delay 500ms;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
server_tokens off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
access_log logs/access.log main;
include mime.types;
default_type application/octet-stream;
keepalive_timeout 120;
client_max_body_size 10240m;
proxy_max_temp_file_size 1024m;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_comp_level 5;
gzip_types
text/xml
text/plain
text/css
text/javascript
application/json
application/x-javascript
application/javascript
application/xml
application/xml+rss
application/xhtml+xml
application/atom+xml
application/rss+xml
image/svg+xml
application/manifest+json;
gzip_proxied any;
gzip_disable "MSIE [1-6]\.";
upstream seeyon_v5_cluster{
server 127.0.0.1:8080 max_fails=50 fail_timeout=15s;
}
# ========== 统一80端口跳转 ==========
server {
listen 80;
server_name oa.puancn.top nas.puankj.top oa.puankj.top code.puancn.top;
return 301 https://$host$request_uri;
}
# ========== code.puancn.top HTTPS==========
server {
listen 443 ssl;
server_name code.puancn.top;
ssl_certificate ssl/code.puancn.top.pem;
ssl_certificate_key ssl/code.puancn.top.key;
root D:/product/client/dist;
index index.html;
# 前端SPA单页应用
location / {
try_files $uri $uri/ /index.html;
}
# 所有接口转发后端
location /api/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 60s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;
}
#上传文件代理
location /uploads {
proxy_pass http://127.0.0.1:3000/uploads;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_cache off;
add_header Cache-Control "no-store, no-cache, must-revalidate" always;
}
location ~ /\. {
deny all;
}
}
# ========== NAS 反向代理站点 ==========
server {
listen 443 ssl;
server_name nas.puankj.top;
charset utf-8;
ssl_certificate ssl/nas.puankj.top.pem;
ssl_certificate_key ssl/nas.puankj.top.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / {
proxy_pass http://192.168.110.90:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
}
# ========== oa.puankj.top 外网OA ==========
server {
listen 443 ssl;
server_name oa.puankj.top;
charset utf-8;
ssl_certificate ssl/oa.puankj.top.pem;
ssl_certificate_key ssl/oa.puankj.top.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / {
proxy_pass http://seeyon_v5_cluster;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_connect_timeout 600;
proxy_read_timeout 600;
proxy_send_timeout 600;
}
}
# ========== oa.puancn.top 内网OA ==========
server {
listen 443 ssl;
server_name oa.puancn.top;
charset utf-8;
ssl_certificate ssl/oa.puancn.top.pem;
ssl_certificate_key ssl/oa.puancn.top.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / {
proxy_pass http://seeyon_v5_cluster;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_connect_timeout 600;
proxy_read_timeout 600;
proxy_send_timeout 600;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
5.2 Nginx 启停、重载命令
cd D:\server\nginx
nginx -t # 检查配置是否报错(必执行)
start nginx # 启动
nginx -s reload # 平滑重启(更新代码只用这个)
nginx -s stop # 停止
2
3
4
5
6
7
8
# 六、日常运维规范
- 前端更新只替换dist+重载Nginx
- 后端更新只重启PM2
- 任何Nginx修改必须先 nginx -t 校验
- 服务器重启后自动恢复所有服务(已配置开机自启)
-END-