一、工具準備
openSSL:需要針對https請求頭 生成對應的 自簽名證書。
Nginx:服務器搭建工具
nodeJS: Express API運行環境
PM2: node進程管理器。用于替代npm命令管理 啟動命令。
二、openSSL 本地自簽名證書生成。
創建服務器空文件夾(這里可以和Nginx程序包位置在一起,也可以單獨放置)例如:D:demo
在D:demo 文件夾 下創建 文件?generate_cert.sh
內容:
#!/bin/bash
mkdir -p cert && cd cert
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \-keyout server.key -out server.crt \-subj "/C=CN/ST=Beijing/L=Beijing/O=LocalDev/CN=localhost"
執行這個sh,?
或者創建 cert文件夾,cmd命令執行命令
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \-keyout server.key -out server.crt \-subj "/C=CN/ST=Beijing/L=Beijing/O=LocalDev/CN=localhost"
win系統文件權限問題可能導致 sh執行生成文件夾和文件失敗。
這樣就生成了這兩個自簽名文件,可以支持本地的https請求頭使用。(瀏覽器訪問會出現不安全提示,需要保存到本地系統可信任證書列表中)
三、Express API 相關配置、程序啟動和PM2管理
? ? ?拷貝Express API 程序到?D:demo 文件夾 下。
? ? ?相關配置修改(例如環境變量中 環境參數改為生產環境對應值)
? ? ?ssl相關內容也要配置修改
? ? ?Express API 程序中 拷貝一份cert 文件夾到程序根目錄
? ? ?app.js入口文件中配置
? ? ?
...
const keyPath = path.join(__dirname, '../cert/localhost+3-key.pem');
const certPath = path.join(__dirname, '../cert/localhost+3.pem');const options = {key: fs.readFileSync(keyPath),cert: fs.readFileSync(certPath)
};
...// 創建HTTPS服務器https.createServer(options, app).listen(process.env.API_PORT, () => {...console.log(`Server running on https://localhost:${process.env.API_PORT}`);});
? ? ?項目根目錄下添加ecosystem.config.cjs 文件用于PM2 啟動參數配置
? ??
module.exports = {apps: [{name: 'PM2啟動進程別名',script: './dist/app.js',type: 'module', // 啟用ES模塊支持watch: false,env: {//PM2啟動默認設置環境變量}}]
}
cd 到 API程序根目錄下 cmd? npm run build (package.json 配置的編譯命令 其實就是?tsc 命令)
D:demo/API/項目根目錄下 會生成一個dist編譯后的包。
然后執行 pm2 start "D:\demo\API\ecosystem.config.cjs" 命令(win 需要使用絕對路徑)
啟動程序
pm2 ls 可以看到 全部的 已管理的 node服務進程,
常用命令? pm2 logs <PM2服務名>、pm2 stop?<PM2服務名>、 pm2 save?<PM2服務名>
到這一步 Express API 本地 服務就搭建好了可通過https://localhost:端口號/路由地址
的方式訪問API接口。
四、React 前端?Nginx?服務發布
https://localhost:端口號/路由地址react 前端程序 通過本地 環境 修改配置 適配 生產環境(例如:代理的API鏈接直接連接剛剛發布的API連接。還有一些 生產環境變量變動)
運行 npm run build (真實命令tsc -b && vite build),生產dist包。
拷貝本地生產 dist包 到D:demo文件夾下改名為 前端包對應的名稱例如:demo-app.
?新建?nginx.conf文件
配置如下
worker_processes 1;
events {worker_connections 1024;
}http {include ...mime.types;//nginx程序目錄下的mime.types文件導入(win下用絕對路徑)default_type application/octet-stream;sendfile on;keepalive_timeout 65;server {listen 443 ssl;server_name localhost;//自簽名文件對應的配置(win下配置絕對路徑)ssl_certificate ../cert/server.crt;ssl_certificate_key ../cert/server.key;# 前端服務location / {root ./demo/demo-app; // win下配置絕對路徑try_files $uri $uri/ /index.html;index index.html;autoindex off; server_tokens on;add_header X-Content-Type-Options "nosniff";add_header Content-Type "text/html; charset=utf-8";# 允許所有來源訪問add_header 'Access-Control-Allow-Origin' '*';# 允許的請求方法add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';# 允許的請求頭add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With';# 允許帶憑證的跨域請求add_header 'Access-Control-Allow-Credentials' 'true';# 預檢請求處理if ($request_method = 'OPTIONS') {add_header 'Access-Control-Max-Age' 1728000;add_header 'Content-Type' 'text/plain; charset=utf-8';add_header 'Content-Length' 0;return 204;}}# API代理location /api/ {proxy_pass https://localhost:[端口號]/api/;proxy_ssl_verify off; proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection 'upgrade';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_cache_bypass $http_upgrade;# 跨域傳遞add_header 'Access-Control-Allow-Origin' '$http_origin';add_header 'Access-Control-Allow-Credentials' 'true';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';}# 靜態文件代理location /static/ {proxy_pass https://localhost:[端口號]/static/;proxy_ssl_verify off; proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection 'upgrade';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_cache_bypass $http_upgrade;# 跨域傳遞add_header 'Access-Control-Allow-Origin' '$http_origin';add_header 'Access-Control-Allow-Credentials' 'true';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';}}
}
具體配置結合業務需求修改。
這塊就把 Express API 代理 和 前端的頁面配到了一個服務。
之后就cd 到?nginx 程序目錄下 cmd? nginx -c ../nginx.conf (win用絕對路徑)
沒有報錯,在 瀏覽器中使用 https://localhost 測試?nginx 服務是否發布成功。
成功會跳轉到發布的本地測試服務 首頁
也可以用https://[局域網本機IP]? 訪問測試服務。(局域網內測試使用)
擴展:如果追求安全性可以使用?Docker容器中的?nginx鏡像 發布應用。