Vue + Vite 項目部署 Docker 全攻略:原理、路由機制、問題排查與開發代理解析
本文面向希望將 Vue 3 + Vite 項目部署到生產環境(Docker + NGINX)并深入理解路由行為、構建機制與常見問題排查的開發者。
📦 一、項目準備
以 Vue 3 + Vite + Vue Router(history 模式)為基礎結構,假設你項目結構如下:
my-app/
├── src/
│ ├── main.ts
│ ├── App.vue
│ └── router/index.ts
├── index.html
├── vite.config.ts
├── Dockerfile
├── nginx.conf
└── ...
🚀 二、構建產物與部署
1. 構建 Vite 項目
運行:
npm run build
生成的 dist 目錄即為生產環境靜態資源(包含 index.html 和 /assets 目錄)。
2. Dockerfile 示例
# 構建階段
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build# 生產部署階段
FROM nginx:stable-alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
3. NGINX 配置 nginx.conf
必須添加路由 fallback 規則,否則刷新頁面會 404:
server {listen 80;server_name localhost;root /usr/share/nginx/html;index index.html;location / {try_files $uri $uri/ /index.html;}
}
4. 構建并運行容器
docker build -t vue-app .
docker run -d -p 8080:80 vue-app
🔁 三、路由訪問原理
以 Vue Router 的 history 模式為例,訪問 http://localhost:8080/login 時,完整流程如下:
1. 瀏覽器發起 GET /login 請求
2. NGINX 未找到 /login.html ? fallback 到 /index.html
3. 瀏覽器加載 index.html 中的 /assets/index.[hash].js
4. Vue 應用執行,router 檢測當前路徑為 /login
5. 匹配到 /login 路由,渲染 Login.vue
如圖:
Browser ──GET /login────? NGINX ──fallback──? /index.html│ │▼ ▼Vue App 加載 Vue Router 路由解析▼ ▼渲染 Login.vue ? Login 頁面展示
🧭 四、常見問題與排查
1. 訪問 /login 顯示 index.html 內容,頁面不渲染組件?
可能原因:
- App.vue 中未寫 <router-view />
- Login.vue 模板為空或未正確導出組件
- 使用了復雜 App.vue 包裹 layout,但 login 頁依賴不滿足導致 setup 被短路
- 構建后的 chunk 文件加載失敗(JS 路徑不對 / base 配置錯誤)
- import(‘…/views/Login.vue’) 懶加載路徑大小寫錯誤
建議排查:
- console.log in main.ts & Login.vue → 是否執行?
- F12 → Network → JS 文件是否 404?
- 控制臺是否有紅色錯誤?
- 使用 vite preview 驗證構建產物是否可用
2. run dev 模式正常,build 后訪問失敗?
開發模式(vite dev):
- 動態模塊按需加載,容錯強
- 頁面路徑自動 fallback
- 即使 Login.vue 結構有問題,也可能渲染成功
構建模式(vite build):
- 靜態資源路徑必須精確
- Vue 模塊必須正確導出組件
- 任一導入錯誤(如路徑拼寫、未 export)將導致頁面白屏
? 為什么 dev 模式能訪問 login,而 build 后失敗?
這是一個非常常見的問題,其核心原因如下:
比較點 | vite dev | vite build(部署后) |
---|---|---|
模塊加載 | 動態、按需、容錯 | 靜態 chunk、路徑嚴格、錯誤即失敗 |
Vue Router fallback | 自動支持 history 模式 | 需依賴 nginx try_files 配置 |
模塊路徑大小寫 | 忽略大小寫錯誤 | 區分大小寫,路徑不對即加載失敗 |
setup 異常容忍度 | 容錯強,console 報錯但頁面仍可加載 | setup 異常可能中斷組件加載 ? 白屏 |
異步 import() 失敗 | console 警告 | 路由無法 resolve 組件 ? 頁面不渲染 |
舉例:
- App.vue 中訪問 localStorage 中的 user_info,但 login 頁并未設置這些字段 ? dev 模式容忍,build 模式直接 setup 錯誤掛掉;
- import(‘@/views/Login.vue’) 寫錯為 ‘@/Views/Login.vue’,dev 模式不會報錯但 build 后 404;
- login 頁未使用 <router-view /> 包裹,則 dev 模式可能能跑,build 無響應。
解決方案:
- 使用 layout 分離 login 與主框架頁面;
- App.vue 中僅保留 <router-view />;
- 路由組件路徑大小寫、export default 必須正確;
- 在 vite preview 中模擬 build 效果進行測試。
🌐 五、代理的作用與使用場景
開發環境中調用 API 常涉及跨域,解決方案是配置 Vite 的代理。
vite.config.ts:
export default defineConfig({server: {proxy: {'/api': {target: 'http://localhost:3000',changeOrigin: true,rewrite: path => path.replace(/^\/api/, '')}}}
})
示例:fetch(‘/api/user’) 實際會轉發到 http://localhost:3000/user
使用代理的場景:
場景 | 是否需要代理 |
---|---|
npm run dev(本地開發) | ? 是 |
npm run build + NGINX | ? 否,需后端支持 CORS 或同源 |
📘 六、構建建議與最佳實踐
- 使用 layout + 嵌套路由結構分離 login 與后臺頁面
- App.vue 僅做 router-view 容器,復雜結構移入 layout
- 所有懶加載路由組件建議添加 import().catch() 兜底
- 使用 vite preview 模擬部署環境進行驗證
? 七、總結
Vue + Vite 項目部署到 Docker 時,雖然構建簡單,但需要理解以下關鍵點:
- 路由使用 history 模式必須配置 NGINX fallback
- 登錄頁等頁面不要被主框架強行包裹
- dev 與 build 模式模塊解析行為不同,容忍度不同
- 構建后的資源必須正確掛載并引用
- 開發代理僅限本地調試,部署后應有真實接口
理解這些機制,才能真正做到:在本地能跑、部署也穩定。