Vite · Part 2 — vite.config.ts Anatomy
The Vite config top to bottom: defineConfig, plugins, root and base, resolve.alias, the dev server (port, open, proxy), define, css, and build options — plus config as a function of command and mode. With a live config builder.
Config của Vite nổi tiếng nhỏ — đa số dự án cần chục dòng. Nhưng hiểu mỗi field làm gì là khác biệt giữa copy-paste và thông hiểu. Cùng đi qua cả object.
Bật/tắt tùy chọn bên dưới để xây vite.config.ts thật từng field:
1. defineConfig và vì sao
import { defineConfig } from "vite";
export default defineConfig({
// ...options
});
defineConfig không làm gì lúc runtime — nó thuần cho IntelliSense và kiểm tra kiểu TypeScript. Bạn có thể export default {}, nhưng mất autocomplete trên mọi field. Luôn dùng nó.
2. plugins — điểm mở rộng chính
Hầu hết mọi thứ ngoài JS/TS thuần đều đến từ plugin:
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react()],
});
Hỗ trợ framework (React Fast Refresh, Vue SFC, Svelte) là plugin; hỗ trợ trình duyệt cũ, PWA, và đa số tích hợp cũng vậy. Thứ tự có thể quan trọng — ta bàn API plugin và enforce ở Phần 9.
3. root và base
Hai field hay nhầm:
- thư mục dự án chứa
index.html(mặc địnhcwd). - đường dẫn công khai app được phục vụ dưới đó.
export default defineConfig({
base: "/app/", // app lives at https://example.com/app/
});
Nếu deploy vào sub-path (GitHub Pages project, mount /app), đặt base nếu không mọi URL asset sẽ 404. Đây là lỗi deploy phổ biến nhất.
4. resolve.alias
Thôi viết ../../../components:
import { fileURLToPath, URL } from "node:url";
export default defineConfig({
resolve: {
alias: { "@": fileURLToPath(new URL("./src", import.meta.url)) },
},
});
Giờ import Button from "@/components/Button" chạy từ bất cứ đâu. Như Webpack, nếu dùng TypeScript bạn phải phản chiếu trong paths của tsconfig.json để type-checker đồng ý.
5. server dev
export default defineConfig({
server: {
port: 3000,
open: true, // open the browser on start
proxy: {
// forward /api to your backend, sidestepping CORS in dev
"/api": { target: "http://localhost:8080", changeOrigin: true },
},
},
});
server.proxy là người hùng hằng ngày: cho frontend gọi /api/... khi dev và chuyển tới backend riêng, nên bạn không bao giờ vật lộn CORS cục bộ.
6. define, css, và build
export default defineConfig({
// compile-time constant replacement (string-replace, must be JSON-serializable)
define: { __APP_VERSION__: JSON.stringify("1.0.0") },
css: {
modules: { localsConvention: "camelCase" }, // .my-class → styles.myClass
},
build: {
outDir: "dist",
sourcemap: true,
rollupOptions: {
output: { manualChunks: { vendor: ["react", "react-dom"] } },
},
},
});
- thay thế văn bản nguyên văn lúc build — giá trị phải JSON-stringify.
- cấu hình CSS Modules, preprocessor, PostCSS (Phần 6).
- điều khiển output production của Rolldown (Phần 10).
7. Config dưới dạng hàm
Bạn thường cần thiết lập khác theo lệnh (dev vs build) hoặc mode. Xuất một hàm thay vì object:
export default defineConfig(({ command, mode }) => {
const isProd = command === "build";
return {
define: { __DEV__: !isProd },
build: { sourcemap: isProd ? "hidden" : true },
};
});
command là "serve" (dev) hoặc "build"; mode là "development", "production", hoặc mode tùy chỉnh (Phần 8).
8. Bài tập
1. App deploy tới https://acme.dev/dashboard/ nhưng mọi URL JS/CSS/ảnh 404 ở production trong khi dev vẫn chạy. Sửa gì?
Lời giải
Đặt base: "/dashboard/" — nếu không asset bị phân giải từ gốc server.
2. Khi dev frontend :3000 gọi /api/users nhưng lỗi CORS tới backend :8080. Sửa sao mà không động backend?
Lời giải
Vite proxy request cùng origin tới backend.
3. Bạn cần build.sourcemap chỉ cho production, và cờ __DEV__. Cấu trúc config sao?
Lời giải
Xuất hàm và rẽ nhánh theo command === "build".
Nâng cao:trong builder, bật plugin React, alias @, proxy, và vendor chunk thủ công, rồi đọc cách defineConfig lồng server và build riêng.
Điểm chính
- Bọc config trong
defineConfigđể có hỗ trợ TypeScript đầy đủ. pluginslà điểm mở rộng chính — gồm cả framework.basequan trọng khi deploy vào sub-path.resolve.aliasdiệt import../../(phản chiếu trongtsconfig.paths).server.proxyné CORS khi dev; config dạng hàm cho rẽ nhánh theo command/mode.
Tiếp theo
Phần 3 — Dev server & ESM native: cách Vite phục vụ source theo yêu cầu, viết lại bare import, và biến đổi từng file khi trình duyệt hỏi.