1 引言
在之前的文章《Ubuntu云服務器上部署發布Vite項目》中筆者使用了Vite提供的預覽服務(npm run preview
)來在云服務器上發布Web應用。這樣做輕量應用是沒問題的,不過遇到一些專業的問題就不行了,最好還是使用專業的HTTP服務器。除此之外,筆者還有一些其他的需求:
- 前后端分離的項目,需要將后端的服務轉發到前端服務IP相同的端口(443端口)。
- 子域名的項目,需要將服務轉發到主域名服務IP相同的端口(443端口)。
這個時候就需要使用nginx,畢竟nginx不僅是一款輕量、高性能的HTTP服務器,還支持轉發和代理服務功能。不過上述兩個問題后面在討論,本篇就詳細記錄一下部署發布單個Vite項目的問題。
2 詳述
2.1 操作
首先,還是需要先安裝nginx:
sudo apt install nginx
然后,準備Vite項目,需要確保項目已經通過npm run build
構建好,并且生成了靜態文件目錄(通常是dist目錄下)。
接下來,在/etc/nginx/sites-available/
目錄下創建一個新的配置文件,例如筆者這里創建一個charlee44文件。在這個文件中填入如下內容:
server { # 定義服務器listen 80; # 監聽80端口server_name charlee44.com; # 服務器域名root /path/to/your/project/dist; # 項目build后的實際路徑index index.html; # 主頁location / { #位置塊,定義路由try_files $uri $uri/ /index.html;}
}
sites-available
目錄下創建的配置是可用的配置,要真正啟用這個配置需要在sites-enabled
目錄中,因此創建軟鏈接:
sudo ln -s /etc/nginx/sites-available/charlee44 /etc/nginx/sites-enabled/
最后就是測試Nginx配置并重啟服務,在終端輸入以下命令:
sudo nginx -t
sudo systemctl restart nginx
2.2 配置
上面的配置很好理解,基本已經注釋清楚了,就是位置塊部分有點難理解,具體意思是:
- $uri:先看看有沒有和請求路徑完全一致的文件存在,比如 /about.html
- $uri/:如果沒有,再看看是否是一個目錄,比如 /about/
- 如果都沒有,就返回 /index.html
不太理解也沒關系,等以后有需求了再來了解清楚。如果這個配置測試沒有問題,在訪問主頁時頁面提示:
500 Internal Server Error
nginx/1.18.0 (Ubuntu)
那么有可能是權限不夠,可以檢查一下文件/var/log/nginx/error.log
是否有類似“Permission denied”的提示。Ubuntu中有些目錄是受保護的目錄(例如/root
目錄),可以將build項目移動到nginx可以正常訪問的目錄,例如/var
下目錄。
如果想配置HTTPS服務,那么就可以使用如下配置:
# HTTP 跳轉 HTTPS
server {listen 80;server_name charlee44.com;return 301 https://$host$request_uri; # 返回301永久重定向,將請求跳轉到HTTPS版本
}# HTTPS 服務
server {listen 443 ssl;server_name charlee44.com;# SSL證書ssl_certificate /etc/nginx/ssl/charlee44.com/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/charlee44.com/charlee44.com.key;ssl_protocols TLSv1.2 TLSv1.3; # 啟用安全的加密協議版本ssl_ciphers HIGH:!aNULL:!MD5; # 設置加密套件,禁用不安全的算法root /var/www/charlee44.com;index index.html;location / {try_files $uri $uri/ =404; # 嘗試查找對應文件或目錄,否則返回404頁面}
}
這段配置的意思是如果用戶通過HTTP訪問網站,那么就將請求轉發到HTTPS的443端口上。另外,HTTPS最重要的一點還有需要申請SSL證書(可以參考筆者之前的文章《在Ubuntu上使用Certbot申請Let’s Encrypt SSL證書》來進行申請)。
2.3 優化
上述HTTPS服務的配置,經過筆者的實際測試,性能比不上Vite提供的預覽服務(npm run preview
)。原因是因為nginx是高度可配,還有很多優化選項可以配置,具體配置如下:
# HTTP 跳轉 HTTPS
server {listen 80;server_name charlee44.com;return 301 https://$host$request_uri;
}# HTTPS 服務
server {listen 443 ssl http2; # ? 啟用 HTTP/2server_name charlee44.com;ssl_certificate /etc/letsencrypt/live/charlee44.com/fullchain.pem;ssl_certificate_key /etc/letsencrypt/live/charlee44.com/privkey.pem;ssl_protocols TLSv1.2 TLSv1.3;ssl_ciphers HIGH:!aNULL:!MD5;root /var/www/charlee44.com;index index.html;# ? 靜態資源緩存 + Cache-Controllocation ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {expires max;add_header Cache-Control "public, immutable";log_not_found off;}# ? HTML 文件緩存短一些(可選)location ~ \.html$ {expires 1h;}# ? 默認處理入口location / {try_files $uri $uri/ =404;}# ? 啟用 Gzip 壓縮gzip on;gzip_types application/javascript text/css;gzip_comp_level 6;# ? 提升文件傳輸效率sendfile on;tcp_nopush on;tcp_nodelay on;
}
相比之前的配置,在性能上主要優化了以下幾點:
2.3.1 啟用HTTP/2
使用HTTP/2協議可以實現多路復用、頭部壓縮等特性,顯著提升加載速度:
listen 443 ssl http2; # ? 啟用 HTTP/2
2.3.2 靜態資源緩存控制
設置瀏覽器緩存策略,減少重復請求,加快頁面加載速度:
# ? 靜態資源緩存 + Cache-Control
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {expires max; # 設置些資源永不過期add_header Cache-Control "public, immutable"; # 設置緩存策略:公開可緩存,內容不變log_not_found off; # 不記錄不存在的文件的404日志
}# ? HTML 文件緩存短一些(可選)
location ~ \.html$ {expires 1h; # HTML文件可能經常更新,設置較短緩存時間
}
2.3.3 Gzip壓縮
啟用Gzip并指定壓縮類型,以減少傳輸體積,加快網頁加載速度(尤其對 JS/CSS):
# ? 啟用 Gzip 壓縮
gzip on;
gzip_types application/javascript text/css;
gzip_comp_level 6; # 啟用 Gzip 壓縮時,使用壓縮級別 6(共 1 到 9 級)
2.3.4 文件傳輸優化
提升網絡傳輸效率,降低延遲,提高吞吐量:
# ? 提升文件傳輸效率
sendfile on;
tcp_nopush on; # 合并頭部+正文,減少小包數量
tcp_nodelay on; # 對動態請求或 WebSocket 立即發送數據
3 結語
其實HTTP服務器的性能優化遠不止這點內容,針對本篇內容的性能優化配置,筆者就可以想到兩點:
- 靜態資源緩存控制的性能優化是通知客戶端緩存文件資源,那么是否可以在服務器上緩存文件資源到內存呢?這樣當客戶端請求過來,就可以不經過硬盤直接傳輸內存中的數據,這樣可以節省一次磁盤IO。
- 啟用Gzip壓縮,壓縮文件也是算在客戶端請求響應時間的,那么是否可以預先將文件按照最高級別進行壓縮,然后需要的時候再直接傳輸出去呢?這樣可以節省臨時文件的時間,同時也最大程度的減少的文件傳輸體積。
其實這兩個問題,甚至更多的性能優化思路,nginx都有一定程度的解決方案,就留待以后再研究吧。