Vue3前端項(xiàng)目部署到Linux服務(wù)器的實(shí)戰(zhàn)指南
前言
在現(xiàn)代 Web 開發(fā)流程中,前端項(xiàng)目的部署是連接開發(fā)與生產(chǎn)環(huán)境的關(guān)鍵環(huán)節(jié)。一個(gè)規(guī)范、高效的部署方案不僅能保證項(xiàng)目穩(wěn)定運(yùn)行,還能提升用戶訪問體驗(yàn)、降低運(yùn)維成本。Vue3 作為當(dāng)前最主流的前端框架之一,其部署方式相較于傳統(tǒng)頁(yè)面有著顯著差異 —— 特別是單頁(yè)應(yīng)用(SPA)的路由機(jī)制、靜態(tài)資源管理等方面,對(duì)運(yùn)維配置提出了特殊要求。
本文將以專業(yè)運(yùn)維工程師的視角,從環(huán)境準(zhǔn)備、本地構(gòu)建、服務(wù)器配置、容器化部署到自動(dòng)化運(yùn)維,全方位講解 Vue3 項(xiàng)目在 Linux 服務(wù)器上的部署實(shí)戰(zhàn)。無論你是前端開發(fā)者希望掌握部署技能,還是運(yùn)維工程師需要標(biāo)準(zhǔn)化前端項(xiàng)目部署流程,本文都將為你提供可直接落地的完整方案。
本文適用人群:
- 前端開發(fā)者需要掌握項(xiàng)目部署技能
- 運(yùn)維工程師負(fù)責(zé)前端項(xiàng)目的生產(chǎn)環(huán)境部署
- 全棧開發(fā)者需要獨(dú)立完成項(xiàng)目上線
- DevOps 工程師搭建自動(dòng)化部署流水線
環(huán)境準(zhǔn)備
本地開發(fā)環(huán)境
必備軟件:
軟件 | 版本要求 | 說明 |
Node.js | ≥ 16.0.0 | Vue3 官方推薦最低版本,建議使用 LTS 版本 |
包管理器 | npm ≥ 8.x / yarn ≥ 1.22 / pnpm ≥ 7.x | 推薦使用 pnpm 以獲得更快的安裝速度 |
Git | ≥ 2.0 | 用于代碼版本管理 |
SSH 客戶端 | OpenSSH / Xshell / FinalShell | 用于遠(yuǎn)程服務(wù)器連接 |
Node.js 版本檢查與安裝(本地):
# 檢查版本 node -v npm -v # 如未安裝,推薦使用 nvm 管理 Node.js 版本 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash source ~/.bashrc nvm install 18-lts nvm use 18-lts
服務(wù)器環(huán)境要求
服務(wù)器配置建議:
部署規(guī)模 | CPU | 內(nèi)存 | 硬盤 | 系統(tǒng) |
小型項(xiàng)目(PV < 1 萬 / 天) | 1 核 | 2GB | 40GB SSD | CentOS 7+/Ubuntu 20.04+ |
中型項(xiàng)目(PV 1-10 萬 / 天) | 2 核 | 4GB | 80GB SSD | CentOS 7+/Ubuntu 20.04+ |
大型項(xiàng)目(PV > 10 萬 / 天) | 4 核 + | 8GB+ | 200GB+ SSD | CentOS 7+/Ubuntu 20.04+ |
服務(wù)器必備軟件:
- Nginx ≥ 1.18(Web 服務(wù)器)
- Docker ≥ 20.0(容器化部署可選)
- OpenSSH Server(遠(yuǎn)程連接)
工具推薦
- SSH 連接工具:FinalShell、Xshell、MobaXterm
- 文件傳輸工具:FileZilla、WinSCP
- 服務(wù)器監(jiān)控:htop、iftop、nmon
- 域名與證書:阿里云 / 騰訊云域名、Let's Encrypt 免費(fèi) SSL 證書
本地打包構(gòu)建
Vue3 項(xiàng)目打包流程
1. 安裝依賴
# 使用 npm npm install # 使用 yarn yarn install # 使用 pnpm(推薦) pnpm install
2. 環(huán)境變量配置
在項(xiàng)目根目錄創(chuàng)建不同環(huán)境的配置文件:
\.env\.production(生產(chǎn)環(huán)境):
# 生產(chǎn)環(huán)境API地址 VITE_API_BASE_URL = https://api.yourdomain.com # 應(yīng)用標(biāo)題 VITE_APP_TITLE = 生產(chǎn)環(huán)境 # 公共路徑 VITE_PUBLIC_PATH = /
3. 執(zhí)行打包命令
# Vite 項(xiàng)目(Vue3 默認(rèn)) npm run build # Webpack 項(xiàng)目(Vue CLI 創(chuàng)建) npm run build
打包成功后,會(huì)在項(xiàng)目根目錄生成 dist 文件夾。
Vite 配置說明
vite\.config\.js 關(guān)鍵配置:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
// 生產(chǎn)環(huán)境基礎(chǔ)路徑,部署到子目錄時(shí)需要修改
base: '/',
build: {
// 輸出目錄
outDir: 'dist',
// 靜態(tài)資源目錄
assetsDir: 'assets',
// 小于此閾值的資源內(nèi)聯(lián)為 base64
assetsInlineLimit: 4096,
// 構(gòu)建后是否生成 source map
sourcemap: false,
// 代碼壓縮配置
minify: 'terser',
terserOptions: {
compress: {
// 生產(chǎn)環(huán)境移除 console
drop_console: true,
// 生產(chǎn)環(huán)境移除 debugger
drop_debugger: true
}
},
// 拆包策略優(yōu)化
rollupOptions: {
output: {
chunkFileNames: 'js/[name]-[hash].js',
entryFileNames: 'js/[name]-[hash].js',
assetFileNames: '[ext]/[name]-[hash].[ext]',
manualChunks(id) {
// 將 node_modules 單獨(dú)打包
if (id.includes('node_modules')) {
return 'vendor'
}
}
}
}
},
// 開發(fā)服務(wù)器配置(僅開發(fā)時(shí)使用)
server: {
port: 3000,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
}
})Webpack 配置說明(Vue CLI)
vue\.config\.js 配置:
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
// 生產(chǎn)環(huán)境路徑
publicPath: '/',
// 輸出目錄
outputDir: 'dist',
// 靜態(tài)資源目錄
assetsDir: 'assets',
// 生產(chǎn)環(huán)境不生成 sourceMap
productionSourceMap: false,
// Webpack 配置
configureWebpack: {
optimization: {
minimizer: [
require('terser-webpack-plugin')({
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
}
}
})
]
}
},
// 開發(fā)代理
devServer: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
}
})打包產(chǎn)物分析
dist 目錄結(jié)構(gòu)說明:
dist/ ├── index.html # 入口HTML文件 ├── favicon.ico # 網(wǎng)站圖標(biāo) ├── assets/ # 靜態(tài)資源目錄 │ ├── css/ │ │ └── index-[hash].css # 樣式文件 │ ├── js/ │ │ ├── index-[hash].js # 入口JS │ │ └── vendor-[hash].js # 第三方依賴 │ └── img/ # 圖片資源 └── robots.txt # 搜索引擎規(guī)則(可選)
打包后驗(yàn)證:
# 本地預(yù)覽打包結(jié)果 npm run preview # 或使用 http-server npm install -g http-server cd dist http-server -p 8080
上傳服務(wù)器
方式一:SCP(推薦,簡(jiǎn)單直接)
SCP 是基于 SSH 的文件傳輸協(xié)議,簡(jiǎn)單高效。
完整上傳命令:
# 基本語(yǔ)法:scp [參數(shù)] 本地文件 遠(yuǎn)程用戶@遠(yuǎn)程IP:遠(yuǎn)程路徑 # 上傳整個(gè) dist 目錄到服務(wù)器 scp -r ./dist/* root@192.168.1.100:/var/www/vue3-project/ # 指定端口(如果SSH端口不是22) scp -P 2222 -r ./dist/* root@192.168.1.100:/var/www/vue3-project/ # 顯示傳輸進(jìn)度 scp -rv ./dist/* root@192.168.1.100:/var/www/vue3-project/
優(yōu)點(diǎn):簡(jiǎn)單直接,無需額外軟件
缺點(diǎn):不支持增量傳輸,每次全量傳輸
方式二:Rsync(推薦生產(chǎn)環(huán)境)
Rsync 支持增量同步,只傳輸修改過的文件,速度快,支持?jǐn)帱c(diǎn)續(xù)傳。
服務(wù)器安裝 Rsync:
# CentOS yum install -y rsync # Ubuntu apt install -y rsync
Rsync 上傳命令:
# 增量同步 dist 目錄到服務(wù)器(推薦) rsync -avzP --delete ./dist/ root@192.168.1.100:/var/www/vue3-project/ # 參數(shù)說明: # -a: 歸檔模式,保留權(quán)限、時(shí)間等屬性 # -v: 顯示詳細(xì)信息 # -z: 傳輸時(shí)壓縮 # -P: 顯示進(jìn)度 + 斷點(diǎn)續(xù)傳 # --delete: 刪除目標(biāo)目錄中源目錄不存在的文件(重要?。? # 指定SSH端口 rsync -avzP -e "ssh -p 2222" ./dist/ root@192.168.1.100:/var/www/vue3-project/ # 排除某些文件 rsync -avzP --exclude="*.map" ./dist/ root@192.168.1.100:/var/www/vue3-project/
優(yōu)點(diǎn):增量傳輸、速度快、支持?jǐn)帱c(diǎn)續(xù)傳
缺點(diǎn):服務(wù)器需要安裝 rsync
方式三:SFTP(圖形化工具)
使用 FileZilla、WinSCP 等圖形化工具:
- 連接信息:協(xié)議選 SFTP,主機(jī)填 IP,端口 22
- 本地選擇 dist 目錄
- 遠(yuǎn)程導(dǎo)航到 /var/www/vue3-project
- 拖拽上傳
三種方式對(duì)比
方式 | 優(yōu)點(diǎn) | 缺點(diǎn) | 適用場(chǎng)景 |
SCP | 簡(jiǎn)單、無需額外安裝 | 全量傳輸、無斷點(diǎn) | 小型項(xiàng)目、首次部署 |
Rsync | 增量、壓縮、斷點(diǎn)續(xù)傳 | 需服務(wù)器安裝 rsync | 生產(chǎn)環(huán)境、頻繁更新 |
SFTP | 圖形化、易操作 | 速度慢、無增量 | 不熟悉命令行的用戶 |
Nginx 安裝配置(重點(diǎn)章節(jié))
Nginx 安裝
方式一:YUM 安裝(CentOS)
# 安裝 EPEL 源 yum install -y epel-release # 安裝 Nginx yum install -y nginx # 啟動(dòng)并設(shè)置開機(jī)自啟 systemctl start nginx systemctl enable nginx # 檢查狀態(tài) systemctl status nginx
方式二:APT 安裝(Ubuntu)
apt update apt install -y nginx systemctl start nginx systemctl enable nginx
方式三:源碼編譯安裝(推薦生產(chǎn)環(huán)境)
# 安裝依賴 yum install -y gcc gcc-c++ make zlib-devel pcre-devel openssl-devel # 下載源碼 cd /usr/local/src wget http://nginx.org/download/nginx-1.24.0.tar.gz tar zxf nginx-1.24.0.tar.gz cd nginx-1.24.0 # 編譯配置(包含常用模塊) ./configure \ --prefix=/usr/local/nginx \ --with-http_ssl_module \ --with-http_v2_module \ --with-http_gzip_static_module \ --with-http_stub_status_module \ --with-stream # 編譯安裝 make && make install # 創(chuàng)建 systemd 服務(wù) # (略,可參考官方文檔)
完整 Nginx 配置文件
*主配置文件 /etc/nginx/nginx\.conf:*
user nginx;
worker_processes auto;
worker_cpu_affinity auto;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
use epoll;
worker_connections 65535;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'$request_time $upstream_response_time';
access_log /var/log/nginx/access.log main;
# 核心優(yōu)化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 1000;
types_hash_max_size 2048;
server_names_hash_bucket_size 128;
client_max_body_size 50M;
# Gzip 壓縮配置
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/xhtml+xml
application/x-font-ttf
font/opentype
image/svg+xml
image/x-icon;
gzip_min_length 1k;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_disable "MSIE [1-6]\.";
# 虛擬主機(jī)配置
include /etc/nginx/conf.d/*.conf;
}Vue3 項(xiàng)目站點(diǎn)配置
*站點(diǎn)配置文件 /etc/nginx/conf\.d/vue3\-project\.conf:*
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
root /var/www/vue3-project;
index index.html;
# 字符集
charset utf-8;
# ==========================================
# 【關(guān)鍵配置】Vue Router History 模式支持
# ==========================================
# 原理:所有請(qǐng)求都重定向到 index.html,由前端路由處理
# 如果不配置,刷新頁(yè)面會(huì)出現(xiàn) 404 錯(cuò)誤
location / {
try_files $uri $uri/ /index.html;
}
# ==========================================
# 靜態(tài)資源緩存策略
# ==========================================
# 帶 hash 的資源(js、css)永久緩存
location ~* \.(js|css)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header Vary Accept-Encoding;
}
# 圖片、字體、媒體資源緩存
location ~* \.(jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public";
}
# html 不緩存(每次都檢查更新)
location ~* \.html$ {
expires -1;
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
# ==========================================
# 反向代理解決跨域問題
# ==========================================
location /api/ {
proxy_pass http://127.0.0.1:8080/; # 后端服務(wù)地址
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;
# 超時(shí)設(shè)置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# WebSocket 支持(如需要)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# ==========================================
# 安全頭配置
# ==========================================
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# ==========================================
# 隱藏敏感文件
# ==========================================
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
location ~ ~$ {
deny all;
access_log off;
log_not_found off;
}
}HTTPS 配置(SSL 證書部署)
完整 HTTPS 配置:
# HTTP 強(qiáng)制跳轉(zhuǎn) HTTPS
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$server_name$request_uri;
}
# HTTPS 服務(wù)
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
root /var/www/vue3-project;
index index.html;
# SSL 證書配置
ssl_certificate /etc/nginx/ssl/yourdomain.com.pem;
ssl_certificate_key /etc/nginx/ssl/yourdomain.com.key;
# SSL 優(yōu)化配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
# HSTS(開啟后用戶瀏覽器強(qiáng)制使用HTTPS)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
charset utf-8;
# History 模式支持
location / {
try_files $uri $uri/ /index.html;
}
# 靜態(tài)資源緩存(同上,省略)
# 反向代理(同上,省略)
# 安全頭(同上,省略)
}Nginx 配置驗(yàn)證與重載
# 檢查配置文件語(yǔ)法 nginx -t # 重載配置(不中斷服務(wù)) nginx -s reload # 重啟 Nginx systemctl restart nginx # 查看運(yùn)行狀態(tài) systemctl status nginx # 查看錯(cuò)誤日志 tail -f /var/log/nginx/error.log # 查看訪問日志 tail -f /var/log/nginx/access.log
Docker 部署方式
Docker 環(huán)境安裝
# CentOS 安裝 Docker yum install -y yum-utils yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum install -y docker-ce docker-ce-cli containerd.io # 啟動(dòng) Docker systemctl start docker systemctl enable docker # 安裝 docker-compose curl -L "https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose
Dockerfile 編寫(多階段構(gòu)建優(yōu)化)
*項(xiàng)目根目錄創(chuàng)建 Dockerfile:*
# ==========================================
# 第一階段:構(gòu)建階段(僅用于編譯打包)
# ==========================================
FROM node:18-alpine AS builder
# 設(shè)置工作目錄
WORKDIR /app
# 先復(fù)制依賴文件,利用 Docker 緩存
COPY package*.json ./
COPY pnpm-lock.yaml* ./
COPY yarn.lock* ./
# 安裝依賴(根據(jù)項(xiàng)目使用的包管理器選擇)
RUN npm config set registry https://registry.npmmirror.com && \
npm install
# 復(fù)制項(xiàng)目源碼
COPY . .
# 執(zhí)行構(gòu)建
RUN npm run build
# ==========================================
# 第二階段:運(yùn)行階段(僅包含 Nginx 和構(gòu)建產(chǎn)物)
# ==========================================
FROM nginx:1.24-alpine
# 設(shè)置時(shí)區(qū)
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone
# 從構(gòu)建階段復(fù)制打包產(chǎn)物
COPY --from=builder /app/dist /usr/share/nginx/html
# 復(fù)制自定義 Nginx 配置
COPY nginx.conf /etc/nginx/conf.d/default.conf
# 暴露端口
EXPOSE 80
# 啟動(dòng) Nginx
CMD ["nginx", "-g", "daemon off;"]Nginx 配置文件(容器內(nèi)使用)
項(xiàng)目根目錄創(chuàng)建 nginx\.conf:
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
charset utf-8;
# History 模式支持
location / {
try_files $uri $uri/ /index.html;
}
# 靜態(tài)資源緩存
location ~* \.(js|css)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
location ~* \.(jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf)$ {
expires 30d;
add_header Cache-Control "public";
}
location ~* \.html$ {
expires -1;
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
# 反向代理(如需要)
location /api/ {
proxy_pass http://backend:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Gzip 壓縮
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/javascript application/json application/javascript;
}docker-compose.yml 配置
項(xiàng)目根目錄創(chuàng)建 docker\-compose\.yml:
version: '3.8'
services:
# Vue3 前端服務(wù)
web:
build: .
container_name: vue3-web
restart: always
ports:
- "80:80"
- "443:443" # 如需HTTPS
volumes:
# 掛載 SSL 證書(如需HTTPS)
- ./ssl:/etc/nginx/ssl
# 掛載日志目錄
- ./logs/nginx:/var/log/nginx
networks:
- app-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
# 后端服務(wù)(如需要)
backend:
image: your-backend-image:latest
container_name: vue3-backend
restart: always
ports:
- "8080:8080"
networks:
- app-network
networks:
app-network:
driver: bridgeDocker 部署命令
# 構(gòu)建并啟動(dòng) docker-compose up -d --build # 查看日志 docker-compose logs -f web # 查看運(yùn)行狀態(tài) docker-compose ps # 停止服務(wù) docker-compose down # 重啟服務(wù) docker-compose restart web # 進(jìn)入容器 docker exec -it vue3-web sh
自動(dòng)化部署腳本
完整自動(dòng)化部署 Shell 腳本
在項(xiàng)目根目錄創(chuàng)建 deploy\.sh:
#!/bin/bash
set -e
# ==========================================
# Vue3 項(xiàng)目自動(dòng)化部署腳本
# 功能:本地構(gòu)建 -> 備份 -> 上傳 -> 部署 -> 回滾支持
# ==========================================
# ==================== 配置項(xiàng) ====================
PROJECT_NAME="vue3-project"
LOCAL_DIST_PATH="./dist"
REMOTE_USER="root"
REMOTE_HOST="192.168.1.100"
REMOTE_PORT="22"
REMOTE_BASE_PATH="/var/www/${PROJECT_NAME}"
BACKUP_KEEP_COUNT=5 # 保留備份數(shù)量
# ================================================
# 顏色輸出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 步驟1:本地構(gòu)建
build() {
log_info "開始本地構(gòu)建..."
npm run build
if [ ! -d "$LOCAL_DIST_PATH" ]; then
log_error "構(gòu)建失敗,dist 目錄不存在"
exit 1
fi
log_info "構(gòu)建完成"
}
# 步驟2:備份當(dāng)前版本
backup() {
log_info "備份當(dāng)前版本..."
local timestamp=$(date +%Y%m%d_%H%M%S)
local backup_path="${REMOTE_BASE_PATH}/backup/${timestamp}"
ssh -p $REMOTE_PORT $REMOTE_USER@$REMOTE_HOST << EOF
mkdir -p ${REMOTE_BASE_PATH}/backup
if [ -d "${REMOTE_BASE_PATH}/current" ]; then
cp -r ${REMOTE_BASE_PATH}/current $backup_path
log_info "備份完成: $backup_path"
fi
EOF
}
# 步驟3:清理舊備份
cleanup_backups() {
log_info "清理舊備份,保留最近 ${BACKUP_KEEP_COUNT} 個(gè)..."
ssh -p $REMOTE_PORT $REMOTE_USER@$REMOTE_HOST << EOF
cd ${REMOTE_BASE_PATH}/backup
ls -t | tail -n +\$((BACKUP_KEEP_COUNT + 1)) | xargs rm -rf
EOF
}
# 步驟4:上傳新文件
upload() {
log_info "上傳新文件到服務(wù)器..."
ssh -p $REMOTE_PORT $REMOTE_USER@$REMOTE_HOST "mkdir -p ${REMOTE_BASE_PATH}/releases"
local release_name=$(date +%Y%m%d_%H%M%S)
local remote_release_path="${REMOTE_BASE_PATH}/releases/${release_name}"
ssh -p $REMOTE_PORT $REMOTE_USER@$REMOTE_HOST "mkdir -p $remote_release_path"
rsync -avzP --delete \
-e "ssh -p $REMOTE_PORT" \
${LOCAL_DIST_PATH}/ \
${REMOTE_USER}@${REMOTE_HOST}:${remote_release_path}/
echo $release_name
}
# 步驟5:切換到新版本
switch_version() {
local release_name=$1
log_info "切換到新版本: $release_name"
ssh -p $REMOTE_PORT $REMOTE_USER@$REMOTE_HOST << EOF
# 創(chuàng)建軟鏈接指向新版本
ln -sfn ${REMOTE_BASE_PATH}/releases/${release_name} ${REMOTE_BASE_PATH}/current
echo "版本切換完成"
EOF
}
# 回滾功能
rollback() {
log_info "開始回滾..."
local previous_version=$(ssh -p $REMOTE_PORT $REMOTE_USER@$REMOTE_HOST "
ls -t ${REMOTE_BASE_PATH}/releases | sed -n '2p'
")
if [ -z "$previous_version" ]; then
log_error "沒有可回滾的版本"
exit 1
fi
log_warn "回滾到版本: $previous_version"
switch_version $previous_version
log_info "回滾完成"
}
# 主流程
main() {
case "${1:-deploy}" in
deploy)
log_info "========== 開始部署 =========="
build
backup
local release_name=$(upload)
switch_version $release_name
cleanup_backups
log_info "========== 部署成功 =========="
;;
rollback)
rollback
;;
build)
build
;;
*)
echo "用法: $0 [deploy|rollback|build]"
exit 1
;;
esac
}
main "$@"腳本使用方法
# 添加執(zhí)行權(quán)限 chmod +x deploy.sh # 完整部署 ./deploy.sh deploy # 回滾到上一個(gè)版本 ./deploy.sh rollback # 僅本地構(gòu)建 ./deploy.sh build
CI/CD 思路(GitHub Actions 示例)
項(xiàng)目根目錄創(chuàng)建 \.github/workflows/deploy\.yml:
name: Deploy to Production
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Deploy to server
uses: easingthemes/ssh-deploy@main
with:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
ARGS: "-avzP --delete"
SOURCE: "dist/"
REMOTE_HOST: ${{ secrets.REMOTE_HOST }}
REMOTE_USER: ${{ secrets.REMOTE_USER }}
TARGET: /var/www/vue3-project/current/常見問題排查
1. 刷新頁(yè)面出現(xiàn) 404 錯(cuò)誤
問題原因:Vue Router 使用 history 模式時(shí),Nginx 沒有配置 try_files
解決方案:在 Nginx 配置中添加:
location / {
try_files $uri $uri/ /index.html;
}驗(yàn)證:nginx \-t \&\& nginx \-s reload
2. 跨域問題(CORS Error)
問題原因:前端域名和后端接口域名不一致
解決方案:
- 方案 A:Nginx 反向代理(推薦)
location /api/ {
proxy_pass http://backend-server:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}- 方案 B:后端配置 CORS
// Spring Boot 示例 @CrossOrigin(origins = "https://yourdomain.com")
3. 靜態(tài)資源加載失敗(404)
問題原因:
- base 路徑配置錯(cuò)誤
- 資源路徑大小寫問題(Linux 區(qū)分大小寫)
- 文件權(quán)限問題
排查步驟:
# 1. 檢查文件是否存在 ls -la /var/www/vue3-project/assets/ # 2. 檢查文件權(quán)限 chown -R nginx:nginx /var/www/vue3-project/ chmod -R 755 /var/www/vue3-project/ # 3. 檢查 Nginx 配置的 root 路徑是否正確 # 4. 檢查 vite.config.js 中的 base 配置
4. 頁(yè)面白屏
排查步驟:
- F12 查看 Console 是否有 JS 報(bào)錯(cuò)
- 檢查 Network 是否有資源加載失敗
- 檢查是否開啟了 CSP(內(nèi)容安全策略)
- 檢查是否是瀏覽器緩存問題(Ctrl+F5 強(qiáng)制刷新)
- 查看 Nginx 錯(cuò)誤日志:
tail \-f /var/log/nginx/error\.log
5. HTTPS 不生效或證書錯(cuò)誤
排查命令:
# 檢查證書是否匹配 openssl x509 -noout -subject -in /etc/nginx/ssl/cert.pem openssl rsa -noout -check -in /etc/nginx/ssl/key.pem # 檢查證書有效期 openssl x509 -noout -dates -in /etc/nginx/ssl/cert.pem # 測(cè)試 HTTPS 連接 curl -v https://yourdomain.com
6. Gzip 壓縮不生效
驗(yàn)證方法:
# 檢查響應(yīng)頭是否包含 Content-Encoding: gzip curl -I -H "Accept-Encoding: gzip" https://yourdomain.com/assets/index.js
性能優(yōu)化建議
1. 構(gòu)建層面優(yōu)化
- 開啟代碼壓縮:生產(chǎn)環(huán)境移除 console、debugger
- 代碼分割:路由懶加載、第三方庫(kù)單獨(dú)打包
- Tree Shaking:移除未使用的代碼
- 圖片優(yōu)化:使用 WebP 格式、壓縮圖片大小
2. Nginx 層面優(yōu)化
- 開啟 Gzip/Brotli 壓縮:減少傳輸體積 60%+
- 配置瀏覽器緩存:帶 hash 的資源永久緩存
- 開啟 HTTP/2:多路復(fù)用提升加載速度
- 靜態(tài)資源 CDN 加速:將 js/css/ 圖片托管到 CDN
3. 服務(wù)器層面優(yōu)化
# 系統(tǒng)參數(shù)優(yōu)化(/etc/sysctl.conf) net.core.somaxconn = 65535 net.core.netdev_max_backlog = 5000 net.ipv4.tcp_max_syn_backlog = 8192 net.ipv4.tcp_fin_timeout = 30 net.ipv4.tcp_tw_reuse = 1 # 文件句柄限制(/etc/security/limits.conf) nginx soft nofile 65535 nginx hard nofile 65535
4. 前端層面優(yōu)化
- 路由懶加載:
const Home = \(\) =\> import\(\&\#39;\./views/Home\.vue\&\#39;\) - 組件懶加載:
defineAsyncComponent - 圖片懶加載:使用
v\-lazy或原生loading=\&\#34;lazy\&\#34; - 使用 CDN:Vue、VueRouter 等大庫(kù)使用 CDN 引入
生產(chǎn)環(huán)境最佳實(shí)踐
1. 目錄結(jié)構(gòu)規(guī)范
推薦目錄結(jié)構(gòu):
/var/www/vue3-project/ ├── current -> releases/20240101_120000/ # 當(dāng)前版本軟鏈接 ├── releases/ # 歷史版本目錄 │ ├── 20240101_120000/ │ ├── 20240102_153000/ │ └── ... ├── backup/ # 備份目錄 ├── shared/ # 共享文件(如配置) └── logs/ # 日志目錄
2. 權(quán)限配置
# 創(chuàng)建專用運(yùn)行用戶 useradd -r -s /sbin/nologin www # 設(shè)置目錄權(quán)限 chown -R www:www /var/www/vue3-project/ chmod -R 755 /var/www/vue3-project/ chmod 644 /var/www/vue3-project/current/index.html # Nginx 運(yùn)行用戶改為 www # 修改 /etc/nginx/nginx.conf: user www;
3. 日志管理
配置日志輪轉(zhuǎn)(/etc/logrotate.d/nginx):
/var/log/nginx/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 0640 www adm
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
endscript
}4. 安全加固
- 隱藏 Nginx 版本號(hào)
# nginx.conf http 塊中添加 server_tokens off;
- 防火墻配置
# 只開放必要端口 firewall-cmd --permanent --add-service=http firewall-cmd --permanent --add-service=https firewall-cmd --permanent --add-service=ssh firewall-cmd --reload
- Fail2ban 防暴力 破解
yum install -y fail2ban systemctl start fail2ban systemctl enable fail2ban
- 定期安全更新
yum update -y # 或 apt update && apt upgrade -y
5. 監(jiān)控與告警
基礎(chǔ)監(jiān)控腳本示例:
#!/bin/bash
# check_nginx.sh
NGINX_STATUS=$(systemctl is-active nginx)
if [ "$NGINX_STATUS" != "active" ]; then
echo "Nginx 服務(wù)異常!" | mail -s "告警:Nginx 服務(wù)停止" admin@yourdomain.com
systemctl restart nginx
fi
# 檢查磁盤使用率
DISK_USAGE=$(df / | awk 'NR==2 {print $5}' | sed 's/%//')
if [ $DISK_USAGE -gt 80 ]; then
echo "磁盤使用率超過 80%,當(dāng)前:${DISK_USAGE}%" | mail -s "告警:磁盤空間不足" admin@yourdomain.com
fi推薦監(jiān)控工具:Prometheus + Grafana、Zabbix、云監(jiān)控
6. 版本管理與回滾方案
藍(lán)綠部署:
- 同時(shí)運(yùn)行兩個(gè)版本(藍(lán)版、綠版)
- 新版本驗(yàn)證通過后,Nginx 切換 upstream
灰度發(fā)布:
- Nginx 根據(jù)權(quán)重分配流量
- 逐步將流量從舊版本切換到新版本
# 灰度發(fā)布配置示例
upstream web_servers {
server 127.0.0.1:8081 weight=9; # 舊版本 90% 流量
server 127.0.0.1:8082 weight=1; # 新版本 10% 流量
}總結(jié)
本文系統(tǒng)地講解了 Vue3 前端項(xiàng)目部署到 Linux 服務(wù)器的完整流程,涵蓋了從本地構(gòu)建、文件傳輸、Nginx 配置、容器化部署到自動(dòng)化運(yùn)維的各個(gè)環(huán)節(jié)。以下是核心要點(diǎn)回顧:
核心要點(diǎn)總結(jié)
- History 模式是關(guān)鍵:務(wù)必配置
try\_files $uri $uri/ /index\.html;,這是 SPA 部署的核心 - 緩存策略要合理:帶 hash 的資源永久緩存,html 不緩存
- HTTPS 是標(biāo)配:生產(chǎn)環(huán)境必須部署 SSL 證書
- 反向代理解跨域:Nginx 反向代理是解決跨域的最佳方案
- Rsync 增量部署:生產(chǎn)環(huán)境推薦使用 Rsync 而非 SCP
- Docker 標(biāo)準(zhǔn)化:容器化部署保證環(huán)境一致性
- 自動(dòng)化 + 回滾:部署腳本必須包含回滾功能
- 監(jiān)控不能少:生產(chǎn)環(huán)境必須有完善的監(jiān)控告警
部署流程速查
本地開發(fā) → npm run build → rsync 增量上傳 → Nginx 配置 → 測(cè)試驗(yàn)證 → 監(jiān)控告警
Vue3 項(xiàng)目的部署并不復(fù)雜,但細(xì)節(jié)決定成敗。一個(gè)好的部署方案不僅要能讓項(xiàng)目跑起來,更要保證穩(wěn)定、安全、高效。希望本文能幫助你建立標(biāo)準(zhǔn)化的前端部署流程,讓每次部署都成為一個(gè)可靠、可重復(fù)、可回滾的自動(dòng)化過程。
以上就是Vue3前端項(xiàng)目部署到Linux服務(wù)器的實(shí)戰(zhàn)指南的詳細(xì)內(nèi)容,更多關(guān)于Vue3前端項(xiàng)目部署到Linux的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
uniapp Vue3中如何解決web/H5網(wǎng)頁(yè)瀏覽器跨域的問題
存在跨域問題的原因是因?yàn)闉g覽器的同源策略,也就是說前端無法直接發(fā)起跨域請(qǐng)求,同源策略是一個(gè)基礎(chǔ)的安全策略,但是這也會(huì)給uniapp/Vue開發(fā)者在部署時(shí)帶來一定的麻煩,這篇文章主要介紹了在uniapp Vue3版本中如何解決web/H5網(wǎng)頁(yè)瀏覽器跨域的問題,需要的朋友可以參考下2024-06-06
使用 Element UI Table 的 slot-scope方法
這篇文章主要介紹了使用 Element UI Table 的 slot-scope方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
Vue.js實(shí)現(xiàn)可配置的登錄表單代碼詳解
這篇文章主要介紹了Vue.js實(shí)現(xiàn)可配置的登錄表單實(shí)例代碼詳解,文中給大家補(bǔ)充介紹了vue.js 全選與取消全選的實(shí)例代碼,需要的朋友可以參考下2018-03-03
Hexo已經(jīng)看膩了,來手把手教你使用VuePress搭建個(gè)人博客
vuepress是尤大大4月12日發(fā)布的一個(gè)全新的基于vue的靜態(tài)網(wǎng)站生成器,實(shí)際上就是一個(gè)vue的spa應(yīng)用,內(nèi)置webpack,可以用來寫文檔。這篇文章給大家介紹了VuePress搭建個(gè)人博客的過程,感興趣的朋友一起看看吧2018-04-04
vue監(jiān)聽屬性watch的用法及使用場(chǎng)景詳解
watch是vue中常用的監(jiān)聽器,它主要用于偵聽數(shù)據(jù)的變化,在數(shù)據(jù)發(fā)生變化的時(shí)候執(zhí)行一些操作,這篇文章主要介紹了vue監(jiān)聽屬性watch的用法及使用場(chǎng)景的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-09-09
vue實(shí)現(xiàn)滑動(dòng)驗(yàn)證條
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)滑動(dòng)驗(yàn)證條,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03

