Vue3前端项目部署到Linux服务器的实战指南

 更新时间:2026年06月02日 09:19:37   作者:染翰  
在现代Web开发流程中,前端项目的部署是连接开发与生产环境的关键环节,Vue3作为当前最主流的前端框架之一,其部署方式相较于传统页面有着显著差异,本文将从环境准备、本地构建、服务器配置、容器化部署到自动化运维,全方位讲解Vue3项目在Linux服务器上的部署实战

前言

在现代 Web 开发流程中,前端项目的部署是连接开发与生产环境的关键环节。一个规范、高效的部署方案不仅能保证项目稳定运行,还能提升用户访问体验、降低运维成本。Vue3 作为当前最主流的前端框架之一,其部署方式相较于传统页面有着显著差异 —— 特别是单页应用(SPA)的路由机制、静态资源管理等方面,对运维配置提出了特殊要求。

本文将以专业运维工程师的视角,从环境准备、本地构建、服务器配置、容器化部署到自动化运维,全方位讲解 Vue3 项目在 Linux 服务器上的部署实战。无论你是前端开发者希望掌握部署技能,还是运维工程师需要标准化前端项目部署流程,本文都将为你提供可直接落地的完整方案。

本文适用人群:

  • 前端开发者需要掌握项目部署技能
  • 运维工程师负责前端项目的生产环境部署
  • 全栈开发者需要独立完成项目上线
  • DevOps 工程师搭建自动化部署流水线

环境准备

本地开发环境

必备软件:

软件

版本要求

说明

Node.js

≥ 16.0.0

Vue3 官方推荐最低版本,建议使用 LTS 版本

包管理器

npm ≥ 8.x / yarn ≥ 1.22 / pnpm ≥ 7.x

推荐使用 pnpm 以获得更快的安装速度

Git

≥ 2.0

用于代码版本管理

SSH 客户端

OpenSSH / Xshell / FinalShell

用于远程服务器连接

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

服务器环境要求

服务器配置建议:

部署规模

CPU

内存

硬盘

系统

小型项目(PV < 1 万 / 天)

1 核

2GB

40GB SSD

CentOS 7+/Ubuntu 20.04+

中型项目(PV 1-10 万 / 天)

2 核

4GB

80GB SSD

CentOS 7+/Ubuntu 20.04+

大型项目(PV > 10 万 / 天)

4 核 +

8GB+

200GB+ SSD

CentOS 7+/Ubuntu 20.04+

服务器必备软件:

  • Nginx ≥ 1.18(Web 服务器)
  • Docker ≥ 20.0(容器化部署可选)
  • OpenSSH Server(远程连接)

工具推荐

  1. SSH 连接工具:FinalShell、Xshell、MobaXterm
  2. 文件传输工具:FileZilla、WinSCP
  3. 服务器监控:htop、iftop、nmon
  4. 域名与证书:阿里云 / 腾讯云域名、Let's Encrypt 免费 SSL 证书

本地打包构建

Vue3 项目打包流程

1. 安装依赖

# 使用 npm
npm install
# 使用 yarn
yarn install
# 使用 pnpm(推荐)
pnpm install

2. 环境变量配置

在项目根目录创建不同环境的配置文件:

\.env\.production(生产环境):

# 生产环境API地址
VITE_API_BASE_URL = https://api.yourdomain.com
# 应用标题
VITE_APP_TITLE = 生产环境
# 公共路径
VITE_PUBLIC_PATH = /

3. 执行打包命令

# Vite 项目(Vue3 默认)
npm run build
# Webpack 项目(Vue CLI 创建)
npm run build

打包成功后,会在项目根目录生成 dist 文件夹。

Vite 配置说明

vite\.config\.js 关键配置:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
  plugins: [vue()],
  // 生产环境基础路径,部署到子目录时需要修改
  base: '/',
  build: {
    // 输出目录
    outDir: 'dist',
    // 静态资源目录
    assetsDir: 'assets',
    // 小于此阈值的资源内联为 base64
    assetsInlineLimit: 4096,
    // 构建后是否生成 source map
    sourcemap: false,
    // 代码压缩配置
    minify: 'terser',
    terserOptions: {
      compress: {
        // 生产环境移除 console
        drop_console: true,
        // 生产环境移除 debugger
        drop_debugger: true
      }
    },
    // 拆包策略优化
    rollupOptions: {
      output: {
        chunkFileNames: 'js/[name]-[hash].js',
        entryFileNames: 'js/[name]-[hash].js',
        assetFileNames: '[ext]/[name]-[hash].[ext]',
        manualChunks(id) {
          // 将 node_modules 单独打包
          if (id.includes('node_modules')) {
            return 'vendor'
          }
        }
      }
    }
  },
  // 开发服务器配置(仅开发时使用)
  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,
  // 生产环境路径
  publicPath: '/',
  // 输出目录
  outputDir: 'dist',
  // 静态资源目录
  assetsDir: 'assets',
  // 生产环境不生成 sourceMap
  productionSourceMap: false,
  // Webpack 配置
  configureWebpack: {
    optimization: {
      minimizer: [
        require('terser-webpack-plugin')({
          terserOptions: {
            compress: {
              drop_console: true,
              drop_debugger: true
            }
          }
        })
      ]
    }
  },
  // 开发代理
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true
      }
    }
  }
})

打包产物分析

dist 目录结构说明:

dist/
├── index.html              # 入口HTML文件
├── favicon.ico             # 网站图标
├── assets/                 # 静态资源目录
│   ├── css/
│   │   └── index-[hash].css    # 样式文件
│   ├── js/
│   │   ├── index-[hash].js     # 入口JS
│   │   └── vendor-[hash].js    # 第三方依赖
│   └── img/                 # 图片资源
└── robots.txt              # 搜索引擎规则(可选)

打包后验证:

# 本地预览打包结果
npm run preview
# 或使用 http-server
npm install -g http-server
cd dist
http-server -p 8080

上传服务器

方式一:SCP(推荐,简单直接)

SCP 是基于 SSH 的文件传输协议,简单高效。

完整上传命令:

# 基本语法:scp [参数] 本地文件 远程用户@远程IP:远程路径
# 上传整个 dist 目录到服务器
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/
# 显示传输进度
scp -rv ./dist/* root@192.168.1.100:/var/www/vue3-project/

优点:简单直接,无需额外软件
缺点:不支持增量传输,每次全量传输

方式二:Rsync(推荐生产环境)

Rsync 支持增量同步,只传输修改过的文件,速度快,支持断点续传。

服务器安装 Rsync:

# CentOS
yum install -y rsync
# Ubuntu
apt install -y rsync

Rsync 上传命令:

# 增量同步 dist 目录到服务器(推荐)
rsync -avzP --delete ./dist/ root@192.168.1.100:/var/www/vue3-project/
# 参数说明:
# -a: 归档模式,保留权限、时间等属性
# -v: 显示详细信息
# -z: 传输时压缩
# -P: 显示进度 + 断点续传
# --delete: 删除目标目录中源目录不存在的文件(重要!)
# 指定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/

优点:增量传输、速度快、支持断点续传
缺点:服务器需要安装 rsync

方式三:SFTP(图形化工具)

使用 FileZilla、WinSCP 等图形化工具:

  1. 连接信息:协议选 SFTP,主机填 IP,端口 22
  2. 本地选择 dist 目录
  3. 远程导航到 /var/www/vue3-project
  4. 拖拽上传

三种方式对比

方式

优点

缺点

适用场景

SCP

简单、无需额外安装

全量传输、无断点

小型项目、首次部署

Rsync

增量、压缩、断点续传

需服务器安装 rsync

生产环境、频繁更新

SFTP

图形化、易操作

速度慢、无增量

不熟悉命令行的用户

Nginx 安装配置(重点章节)

Nginx 安装

方式一:YUM 安装(CentOS)

# 安装 EPEL 源
yum install -y epel-release
# 安装 Nginx
yum install -y nginx
# 启动并设置开机自启
systemctl start nginx
systemctl enable nginx
# 检查状态
systemctl status nginx

方式二:APT 安装(Ubuntu)

apt update
apt install -y nginx
systemctl start nginx
systemctl enable nginx

方式三:源码编译安装(推荐生产环境)

# 安装依赖
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
# 创建 systemd 服务
# (略,可参考官方文档)

完整 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;
    # 核心优化
    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]\.";
    # 虚拟主机配置
    include /etc/nginx/conf.d/*.conf;
}

Vue3 项目站点配置

*站点配置文件 /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;
    # ==========================================
    # 【关键配置】Vue Router History 模式支持
    # ==========================================
    # 原理:所有请求都重定向到 index.html,由前端路由处理
    # 如果不配置,刷新页面会出现 404 错误
    location / {
        try_files $uri $uri/ /index.html;
    }
    # ==========================================
    # 静态资源缓存策略
    # ==========================================
    # 带 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/;  # 后端服务地址
        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 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 强制跳转 HTTPS
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    return 301 https://$server_name$request_uri;
}
# HTTPS 服务
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 优化配置
    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(开启后用户浏览器强制使用HTTPS)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    charset utf-8;
    # History 模式支持
    location / {
        try_files $uri $uri/ /index.html;
    }
    # 静态资源缓存(同上,省略)
    # 反向代理(同上,省略)
    # 安全头(同上,省略)
}

Nginx 配置验证与重载

# 检查配置文件语法
nginx -t
# 重载配置(不中断服务)
nginx -s reload
# 重启 Nginx
systemctl restart nginx
# 查看运行状态
systemctl status nginx
# 查看错误日志
tail -f /var/log/nginx/error.log
# 查看访问日志
tail -f /var/log/nginx/access.log

Docker 部署方式

Docker 环境安装

# 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
# 启动 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 编写(多阶段构建优化)

*项目根目录创建 Dockerfile:*

# ==========================================
# 第一阶段:构建阶段(仅用于编译打包)
# ==========================================
FROM node:18-alpine AS builder
# 设置工作目录
WORKDIR /app
# 先复制依赖文件,利用 Docker 缓存
COPY package*.json ./
COPY pnpm-lock.yaml* ./
COPY yarn.lock* ./
# 安装依赖(根据项目使用的包管理器选择)
RUN npm config set registry https://registry.npmmirror.com && \
    npm install
# 复制项目源码
COPY . .
# 执行构建
RUN npm run build
# ==========================================
# 第二阶段:运行阶段(仅包含 Nginx 和构建产物)
# ==========================================
FROM nginx:1.24-alpine
# 设置时区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo "Asia/Shanghai" > /etc/timezone
# 从构建阶段复制打包产物
COPY --from=builder /app/dist /usr/share/nginx/html
# 复制自定义 Nginx 配置
COPY nginx.conf /etc/nginx/conf.d/default.conf
# 暴露端口
EXPOSE 80
# 启动 Nginx
CMD ["nginx", "-g", "daemon off;"]

Nginx 配置文件(容器内使用)

项目根目录创建 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;
    }
    # 静态资源缓存
    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 配置

项目根目录创建 docker\-compose\.yml

version: '3.8'
services:
  # Vue3 前端服务
  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
  # 后端服务(如需要)
  backend:
    image: your-backend-image:latest
    container_name: vue3-backend
    restart: always
    ports:
      - "8080:8080"
    networks:
      - app-network
networks:
  app-network:
    driver: bridge

Docker 部署命令

# 构建并启动
docker-compose up -d --build
# 查看日志
docker-compose logs -f web
# 查看运行状态
docker-compose ps
# 停止服务
docker-compose down
# 重启服务
docker-compose restart web
# 进入容器
docker exec -it vue3-web sh

自动化部署脚本

完整自动化部署 Shell 脚本

在项目根目录创建 deploy\.sh

#!/bin/bash
set -e
# ==========================================
# Vue3 项目自动化部署脚本
# 功能:本地构建 -> 备份 -> 上传 -> 部署 -> 回滚支持
# ==========================================
# ==================== 配置项 ====================
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  # 保留备份数量
# ================================================
# 颜色输出
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:本地构建
build() {
    log_info "开始本地构建..."
    npm run build
    if [ ! -d "$LOCAL_DIST_PATH" ]; then
        log_error "构建失败,dist 目录不存在"
        exit 1
    fi
    log_info "构建完成"
}
# 步骤2:备份当前版本
backup() {
    log_info "备份当前版本..."
    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} 个..."
    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 "上传新文件到服务器..."
    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
        # 创建软链接指向新版本
        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 "$@"

脚本使用方法

# 添加执行权限
chmod +x deploy.sh
# 完整部署
./deploy.sh deploy
# 回滚到上一个版本
./deploy.sh rollback
# 仅本地构建
./deploy.sh build

CI/CD 思路(GitHub Actions 示例)

项目根目录创建 \.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. 刷新页面出现 404 错误

问题原因:Vue Router 使用 history 模式时,Nginx 没有配置 try_files

解决方案:在 Nginx 配置中添加:

location / {
    try_files $uri $uri/ /index.html;
}

验证nginx \-t \&amp;\&amp; 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. 静态资源加载失败(404)

问题原因:

  • base 路径配置错误
  • 资源路径大小写问题(Linux 区分大小写)
  • 文件权限问题

排查步骤:

# 1. 检查文件是否存在
ls -la /var/www/vue3-project/assets/
# 2. 检查文件权限
chown -R nginx:nginx /var/www/vue3-project/
chmod -R 755 /var/www/vue3-project/
# 3. 检查 Nginx 配置的 root 路径是否正确
# 4. 检查 vite.config.js 中的 base 配置

4. 页面白屏

排查步骤:

  1. F12 查看 Console 是否有 JS 报错
  2. 检查 Network 是否有资源加载失败
  3. 检查是否开启了 CSP(内容安全策略)
  4. 检查是否是浏览器缓存问题(Ctrl+F5 强制刷新)
  5. 查看 Nginx 错误日志:tail \-f /var/log/nginx/error\.log

5. HTTPS 不生效或证书错误

排查命令:

# 检查证书是否匹配
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
# 测试 HTTPS 连接
curl -v https://yourdomain.com

6. Gzip 压缩不生效

验证方法:

# 检查响应头是否包含 Content-Encoding: gzip
curl -I -H "Accept-Encoding: gzip" https://yourdomain.com/assets/index.js

性能优化建议

1. 构建层面优化

  • 开启代码压缩:生产环境移除 console、debugger
  • 代码分割:路由懒加载、第三方库单独打包
  • Tree Shaking:移除未使用的代码
  • 图片优化:使用 WebP 格式、压缩图片大小

2. Nginx 层面优化

  • 开启 Gzip/Brotli 压缩:减少传输体积 60%+
  • 配置浏览器缓存:带 hash 的资源永久缓存
  • 开启 HTTP/2:多路复用提升加载速度
  • 静态资源 CDN 加速:将 js/css/ 图片托管到 CDN

3. 服务器层面优化

# 系统参数优化(/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. 前端层面优化

  • 路由懒加载const Home = \(\) =\&gt; import\(\&\#39;\./views/Home\.vue\&\#39;\)
  • 组件懒加载defineAsyncComponent
  • 图片懒加载:使用 v\-lazy 或原生 loading=\&\#34;lazy\&\#34;
  • 使用 CDN:Vue、VueRouter 等大库使用 CDN 引入

生产环境最佳实践

1. 目录结构规范

推荐目录结构:

/var/www/vue3-project/
├── current -> releases/20240101_120000/  # 当前版本软链接
├── releases/                             # 历史版本目录
│   ├── 20240101_120000/
│   ├── 20240102_153000/
│   └── ...
├── backup/                               # 备份目录
├── shared/                               # 共享文件(如配置)
└── logs/                                 # 日志目录

2. 权限配置

# 创建专用运行用户
useradd -r -s /sbin/nologin www
# 设置目录权限
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 运行用户改为 www
# 修改 /etc/nginx/nginx.conf: user www;

3. 日志管理

配置日志轮转(/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. 安全加固

  1. 隐藏 Nginx 版本号
# nginx.conf http 块中添加
server_tokens off;
  1. 防火墙配置
# 只开放必要端口
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --permanent --add-service=ssh
firewall-cmd --reload
  1. Fail2ban 防暴力 破解
yum install -y fail2ban
systemctl start fail2ban
systemctl enable fail2ban
  1. 定期安全更新
yum update -y
# 或
apt update && apt upgrade -y

5. 监控与告警

基础监控脚本示例:

#!/bin/bash
# check_nginx.sh
NGINX_STATUS=$(systemctl is-active nginx)
if [ "$NGINX_STATUS" != "active" ]; then
    echo "Nginx 服务异常!" | mail -s "告警:Nginx 服务停止" 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%,当前:${DISK_USAGE}%" | mail -s "告警:磁盘空间不足" admin@yourdomain.com
fi

推荐监控工具:Prometheus + Grafana、Zabbix、云监控

6. 版本管理与回滚方案

蓝绿部署:

  • 同时运行两个版本(蓝版、绿版)
  • 新版本验证通过后,Nginx 切换 upstream

灰度发布:

  • Nginx 根据权重分配流量
  • 逐步将流量从旧版本切换到新版本
# 灰度发布配置示例
upstream web_servers {
    server 127.0.0.1:8081 weight=9;  # 旧版本 90% 流量
    server 127.0.0.1:8082 weight=1;  # 新版本 10% 流量
}

总结

本文系统地讲解了 Vue3 前端项目部署到 Linux 服务器的完整流程,涵盖了从本地构建、文件传输、Nginx 配置、容器化部署到自动化运维的各个环节。以下是核心要点回顾:

核心要点总结

  1. History 模式是关键:务必配置 try\_files $uri $uri/ /index\.html;,这是 SPA 部署的核心
  2. 缓存策略要合理:带 hash 的资源永久缓存,html 不缓存
  3. HTTPS 是标配:生产环境必须部署 SSL 证书
  4. 反向代理解跨域:Nginx 反向代理是解决跨域的最佳方案
  5. Rsync 增量部署:生产环境推荐使用 Rsync 而非 SCP
  6. Docker 标准化:容器化部署保证环境一致性
  7. 自动化 + 回滚:部署脚本必须包含回滚功能
  8. 监控不能少:生产环境必须有完善的监控告警

部署流程速查

本地开发 → npm run build → rsync 增量上传 → Nginx 配置 → 测试验证 → 监控告警

Vue3 项目的部署并不复杂,但细节决定成败。一个好的部署方案不仅要能让项目跑起来,更要保证稳定、安全、高效。希望本文能帮助你建立标准化的前端部署流程,让每次部署都成为一个可靠、可重复、可回滚的自动化过程。

以上就是Vue3前端项目部署到Linux服务器的实战指南的详细内容,更多关于Vue3前端项目部署到Linux的资料请关注脚本之家其它相关文章!

相关文章

  • uniapp Vue3中如何解决web/H5网页浏览器跨域的问题

    uniapp Vue3中如何解决web/H5网页浏览器跨域的问题

    存在跨域问题的原因是因为浏览器的同源策略,也就是说前端无法直接发起跨域请求,同源策略是一个基础的安全策略,但是这也会给uniapp/Vue开发者在部署时带来一定的麻烦,这篇文章主要介绍了在uniapp Vue3版本中如何解决web/H5网页浏览器跨域的问题,需要的朋友可以参考下
    2024-06-06
  • 使用 Element UI Table 的 slot-scope方法

    使用 Element UI Table 的 slot-scope方法

    这篇文章主要介绍了使用 Element UI Table 的 slot-scope方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • Vue.js实现可配置的登录表单代码详解

    Vue.js实现可配置的登录表单代码详解

    这篇文章主要介绍了Vue.js实现可配置的登录表单实例代码详解,文中给大家补充介绍了vue.js 全选与取消全选的实例代码,需要的朋友可以参考下
    2018-03-03
  • Hexo已经看腻了,来手把手教你使用VuePress搭建个人博客

    Hexo已经看腻了,来手把手教你使用VuePress搭建个人博客

    vuepress是尤大大4月12日发布的一个全新的基于vue的静态网站生成器,实际上就是一个vue的spa应用,内置webpack,可以用来写文档。这篇文章给大家介绍了VuePress搭建个人博客的过程,感兴趣的朋友一起看看吧
    2018-04-04
  • Vue滚动到指定位置的多种方式示例详解

    Vue滚动到指定位置的多种方式示例详解

    当容器有滚动条时,有时需要将指定的内容自动滚动到可视区域,怎么实现呢,下面小编给大家带来了多种方法实现Vue滚动到指定位置,感兴趣的朋友跟随小编一起看看吧
    2023-08-08
  • 降低vue-router版本的2种解决方法实例

    降低vue-router版本的2种解决方法实例

    vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用,下面这篇文章主要给大家介绍了关于降低vue-router版本的2种解决方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-07-07
  • vue监听属性watch的用法及使用场景详解

    vue监听属性watch的用法及使用场景详解

    watch是vue中常用的监听器,它主要用于侦听数据的变化,在数据发生变化的时候执行一些操作,这篇文章主要介绍了vue监听属性watch的用法及使用场景的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-09-09
  • vue3如何通过ref获取元素离顶部的距离

    vue3如何通过ref获取元素离顶部的距离

    这篇文章主要给大家介绍了关于vue3如何通过ref获取元素离顶部的距离,文中通过代码以及图文介绍的非常详细,对大家学习或者使用vue3具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-10-10
  • vue实现滑动验证条

    vue实现滑动验证条

    这篇文章主要为大家详细介绍了vue实现滑动验证条,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Vue如何指定不编译的文件夹和favicon.ico

    Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04

最新评论