jvinhit//lab

Search posts

Type to search across journal entries.

navigate open esc close

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. rootbase

Hai field hay nhầm:

  • thư mục dự án chứa index.html (mặc định cwd).
  • đườ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"serve" (dev) hoặc "build"; mode"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 serverbuild riêng.


Điểm chính

  • Bọc config trong defineConfig để có hỗ trợ TypeScript đầy đủ.
  • plugins là điểm mở rộng chính — gồm cả framework.
  • base quan trọng khi deploy vào sub-path.
  • resolve.alias diệt import ../../ (phản chiếu trong tsconfig.paths).
  • server.proxy né 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.