Skip to main content
Tools 6 mins read

Vite: Công Cụ Build Siêu Nhanh Cho Dự Án Web Hiện Đại

Khám phá Vite — công cụ build thế hệ mới siêu nhanh cho React, Vue, Svelte và Vanilla JS. Từ cài đặt, cấu hình đến triển khai production với HMR nhanh như chớp.

#Vite #Build Tool #Web Development #React #Vue #Frontend #Tooling #HMR #ES Modules

Minh họa Vite — công cụ build siêu nhanh

Bạn đã bao giờ ngồi chờ 30 giây để khởi động Webpack dev server? Hay chờ 5 giây mỗi lần sửa code và reload? Nếu bạn đang dùng Create React App, Webpack hay Parcel, có lẽ bạn đã quen với cảm giác này.

Nhưng mọi thứ đã thay đổi.

Vite (phát âm /vit/ — tiếng Pháp nghĩa là “nhanh”) là công cụ build thế hệ mới đang thay đổi cách chúng ta phát triển web. Với khởi động tức thì, HMR (Hot Module Replacement) nhanh như chớp, và cấu hình đơn giản, Vite đã trở thành tiêu chuẩn mới cho frontend tooling.

Trong bài viết này, chúng ta sẽ khám phá mọi khía cạnh của Vite — từ cài đặt cơ bản, cấu hình nâng cao, đến triển khai production — với nhiều ví dụ thực tế.

Vite là gì?

Vite là một build tooldev server thế hệ mới, được tạo bởi Evan You (tác giả của Vue.js) vào năm 2020. Vite tận dụng native ES Modules (ESM) trên trình duyệt hiện đại để loại bỏ hoàn toàn công đoạn bundle trong development — đây là bước đột phá so với các công cụ truyền thống.

So sánh Vite vs Webpack

Tính năngViteWebpack / CRA
Khởi động dev server< 1 giây (ESM native)20-60 giây (bundle toàn bộ)
HMRTức thì, giữ nguyên stateChậm hơn, thường reload full page
Cấu hìnhĐơn giản, ít boilerplatePhức tạp, nhiều config
TypeScriptBuilt-in, zero configCần cấu hình thêm
CSS ModulesBuilt-inCần cấu hình
Production buildRollup (nhanh, nhỏ)Webpack (chậm hơn)
Plugin ecosystemRollup-compatible, đang phát triểnLớn, nhiều plugin

Tại sao Vite nhanh hơn?

Bí mật nằm ở cách Vite xử lý code trong development:

Webpack (cách cũ): Khi bạn chạy npm start, Webpack phải:

  1. Đọc toàn bộ source code
  2. Parse và phân tích dependency graph
  3. Bundle tất cả file thành một (hoặc vài) file
  4. Gửi bundle đến trình duyệt

Dự án càng lớn, thời gian càng lâu.

Vite (cách mới): Khi bạn chạy npm run dev, Vite:

  1. Chia code thành hai nhóm: dependencies (node_modules, bundle bằng esbuild) và source code (ESM native)
  2. Serve source code trực tiếp qua trình duyệt — mỗi file là một ES module riêng
  3. Trình duyệt tự tải các module khi cần

Kết quả: Khởi động dưới 1 giây, bất kể dự án lớn cỡ nào.

Cài đặt Vite

Yêu cầu

  • Node.js phiên bản 18+ (khuyến nghị 20+)
  • npm, yarn, pnpm hoặc bun

Tạo dự án mới

Cách nhanh nhất để bắt đầu với Vite:

npm create vite@latest

Chạy lệnh trên và bạn sẽ thấy menu tương tác:

 Project name: my-app
 Select a framework: React
 Select a variant: TypeScript

Scaffolding project in /Users/you/my-app...
Done. Now run:
  cd my-app
  npm install
  npm run dev

Bạn cũng có thể tạo dự án trực tiếp với template:

# React với JavaScript
npm create vite@latest my-app -- --template react

# React với TypeScript
npm create vite@latest my-app -- --template react-ts

# Vue
npm create vite@latest my-app -- --template vue

# Vue + TypeScript
npm create vite@latest my-app -- --template vue-ts

# Svelte
npm create vite@latest my-app -- --template svelte

# Svelte + TypeScript
npm create vite@latest my-app -- --template svelte-ts

# Vanilla JavaScript
npm create vite@latest my-app -- --template vanilla

# Vanilla TypeScript
npm create vite@latest my-app -- --template vanilla-ts

Templates có sẵn

Vite cung cấp các template chính thức:

  • vanilla / vanilla-ts — JavaScript/TypeScript thuần
  • vue / vue-ts — Vue 3
  • react / react-ts — React 18+
  • preact / preact-ts — Preact
  • lit / lit-ts — Lit (Web Components)
  • svelte / svelte-ts — Svelte
  • solid / solid-ts — SolidJS
  • qwik / qwik-ts — Qwik

Cấu trúc dự án Vite

Sau khi tạo dự án React với Vite, bạn sẽ thấy cấu trúc:

my-app/
├── index.html
├── package.json
├── vite.config.js
├── tsconfig.json
├── public/
│   └── vite.svg
└── src/
    ├── main.jsx
    ├── App.jsx
    ├── App.css
    └── assets/
        └── react.svg

index.html — Entry point khác biệt

Điểm khác biệt lớn nhất: index.html nằm ở root, không phải trong public/. Vite coi index.html là entry point thực sự của ứng dụng:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My App</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.jsx"></script>
  </body>
</html>

Chú ý type="module" — đây là cách Vite dùng native ESM.

vite.config.js — Trái tim cấu hình

File cấu hình chính của Vite, có thể viết bằng JS hoặc TS:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
})

Các tính năng chính của Vite

1. Hot Module Replacement (HMR)

HMR là tính năng “thần thánh” nhất của Vite. Khi bạn sửa code, chỉ file vừa sửa được cập nhật — không reload toàn bộ trang, và state của component được giữ nguyên.

// App.jsx — thử sửa dòng này
function App() {
  const [count, setCount] = useState(0)
  
  return (
    <div>
      <h1>Vite + React</h1>
      <p>Count: {count}</p>
      {/* Sửa nội dung button — HMR cập nhật ngay, count vẫn giữ nguyên */}
      <button onClick={() => setCount(c => c + 1)}>
        Click me!
      </button>
    </div>
  )
}

Với Vite HMR, bạn có thể sửa style, component, hoặc logic — mọi thay đổi xuất hiện trong dưới 50ms.

2. Native ES Modules

Vite không bundle source code trong development. Thay vào đó, nó serve source code nguyên bản dưới dạng ES modules:

// Bạn viết:
import { formatDate } from './utils/date'
import { Button } from './components/Button'

// Vite serve trực tiếp lên trình duyệt:
import { formatDate } from '/src/utils/date.js'
import { Button } from '/src/components/Button.jsx'

Trình duyệt hiện đại (Chrome, Firefox, Edge, Safari 15+) đều hỗ trợ type="module" — trình duyệt tự tải và cache các module.

3. TypeScript built-in

Vite hỗ trợ TypeScript không cần cấu hình. Chỉ cần import file .ts hoặc .tsx:

// utils/format.ts
export function formatPrice(price: number, currency: string): string {
  return new Intl.NumberFormat('vi-VN', {
    style: 'currency',
    currency
  }).format(price)
}

// App.tsx
import { formatPrice } from './utils/format'

function App() {
  return <div>Price: {formatPrice(25000, 'VND')}</div>
}

Lưu ý: Vite chỉ transpile TypeScript, không kiểm tra type (type checking). Để type checking, cài tsc --noEmit hoặc dùng IDE.

4. CSS & Preprocessor

Vite hỗ trợ CSS modules, CSS preprocessor, và PostCSS:

/* App.module.css */
.container {
  max-width: 1200px;
  margin: 0 auto;
}

.title {
  font-size: 2rem;
  color: #646cff;
}
import styles from './App.module.css'

function App() {
  return (
    <div className={styles.container}>
      <h1 className={styles.title}>Hello Vite!</h1>
    </div>
  )
}

Dùng Sass: Chỉ cần cài package và import .scss:

npm install -D sass
// styles/variables.scss
$primary: #646cff;
$padding: 16px;

// components/Card.scss
@use '../styles/variables' as *;

.card {
  padding: $padding;
  background: $primary;
  color: white;
}

5. Static Assets

Import ảnh, font, JSON, và các file tĩnh trực tiếp:

import reactLogo from './assets/react.svg'
import data from './data.json'

function App() {
  return (
    <div>
      <img src={reactLogo} alt="React" />
      <p>{data.title}</p>
    </div>
  )
}

6. Environment Variables

Vite dùng import.meta.env thay vì process.env:

# .env
VITE_API_URL=https://api.example.com
VITE_APP_TITLE=My App
// Trong code
const apiUrl = import.meta.env.VITE_API_URL
const title = import.meta.env.VITE_APP_TITLE

Quan trọng: Chỉ biến có prefix VITE_ mới được expose ra client.

Cấu hình nâng cao

Aliases (Đường dẫn ngắn)

Thay vì ../../../components/Button, dùng alias:

// vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
      '@components': path.resolve(__dirname, './src/components'),
      '@utils': path.resolve(__dirname, './src/utils'),
    }
  }
})
// Giờ bạn có thể viết:
import Button from '@components/Button'
import { formatDate } from '@utils/date'

Proxy API

Tránh CORS khi gọi API từ dev server:

// vite.config.js
export default defineConfig({
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  }
})

Khi bạn gọi fetch('/api/users'), Vite sẽ proxy đến http://localhost:3000/users.

Global CSS / Reset CSS

Import global CSS trong main.jsx:

// main.jsx
import './styles/global.css'
import './styles/reset.css'

Multi-page App

Vite hỗ trợ multi-page app với cấu hình:

// vite.config.js
import { defineConfig } from 'vite'
import { resolve } from 'path'

export default defineConfig({
  build: {
    rollupOptions: {
      input: {
        main: resolve(__dirname, 'index.html'),
        about: resolve(__dirname, 'about/index.html'),
        blog: resolve(__dirname, 'blog/index.html'),
      }
    }
  }
})

Production Build

Build cơ bản

npm run build
# hoặc
npx vite build

Kết quả trong thư mục dist/:

dist/
├── index.html
├── assets/
│   ├── index-abc123.js
│   ├── index-abc123.css
│   └── react-xyz789.js

Vite tự động:

  • Code splitting — tách vendor (React, library) ra khỏi app code
  • CSS minification — nén CSS
  • Tree-shaking — loại bỏ code không dùng
  • Asset hashing — thêm hash vào filename cho cache busting

Preview build

npm run preview
# Serve thư mục dist/ để kiểm tra trước khi deploy

Tối ưu build

// vite.config.js
export default defineConfig({
  build: {
    // Tắt sourcemap cho production
    sourcemap: false,
    
    // Chunk size warning (mặc định 500KB)
    chunkSizeWarningLimit: 1000,
    
    // Rollup options
    rollupOptions: {
      output: {
        // Tách thủ công vendor chunks
        manualChunks: {
          vendor: ['react', 'react-dom'],
          ui: ['antd', '@ant-design/icons'],
        }
      }
    }
  }
})

Deploy Vite Project

Deploy lên Vercel (Miễn phí)

  1. Kết nối GitHub repo với Vercel
  2. Vercel tự động nhận diện Vite và cấu hình:
    • Build command: npm run build
    • Output directory: dist
  3. Deploy — xong!

Deploy lên Netlify

Thêm file netlify.toml:

[build]
  command = "npm run build"
  publish = "dist"

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

Deploy lên GitHub Pages

Dùng plugin vite-plugin-gh-pages hoặc cấu hình:

// vite.config.js
export default defineConfig({
  base: '/your-repo-name/', // Quan trọng!
  plugins: [react()],
})

Vite Plugin Ecosystem

Plugin phổ biến

# React
npm install -D @vitejs/plugin-react

# Vue
npm install -D @vitejs/plugin-vue

# PWA
npm install -D vite-plugin-pwa

# SVG as Component
npm install -D vite-plugin-svg-loader

# Visualize bundle
npm install -D rollup-plugin-visualizer

# Legacy browser support
npm install -D @vitejs/plugin-legacy

Cấu hình nhiều plugin

// vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { VitePWA } from 'vite-plugin-pwa'
import { visualizer } from 'rollup-plugin-visualizer'

export default defineConfig({
  plugins: [
    react(),
    VitePWA({
      registerType: 'autoUpdate',
      includeAssets: ['favicon.ico'],
      manifest: {
        name: 'My App',
        short_name: 'App',
        theme_color: '#646cff',
      }
    }),
    visualizer({
      open: true,
      filename: 'dist/stats.html',
    })
  ]
})

Vite + React: Ví dụ thực tế

Tạo một dự án React hoàn chỉnh với Vite:

npm create vite@latest todo-app -- --template react-ts
cd todo-app
npm install
npm run dev

Mở src/App.tsx và viết một Todo app đơn giản:

import { useState } from 'react'
import './App.css'

interface Todo {
  id: number
  text: string
  completed: boolean
}

function App() {
  const [todos, setTodos] = useState<Todo[]>([])
  const [input, setInput] = useState('')

  const addTodo = () => {
    if (!input.trim()) return
    setTodos([...todos, {
      id: Date.now(),
      text: input,
      completed: false
    }])
    setInput('')
  }

  const toggleTodo = (id: number) => {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ))
  }

  return (
    <div className="app">
      <h1>Todo App with Vite + React</h1>
      <div className="input-group">
        <input
          value={input}
          onChange={e => setInput(e.target.value)}
          onKeyDown={e => e.key === 'Enter' && addTodo()}
          placeholder="Thêm việc cần làm..."
        />
        <button onClick={addTodo}>Thêm</button>
      </div>
      <ul className="todo-list">
        {todos.map(todo => (
          <li
            key={todo.id}
            onClick={() => toggleTodo(todo.id)}
            className={todo.completed ? 'completed' : ''}
          >
            {todo.text}
          </li>
        ))}
      </ul>
      <p className="stats">
        Đã hoàn thành: {todos.filter(t => t.completed).length} / {todos.length}
      </p>
    </div>
  )
}

export default App

Chạy npm run build để build production, rồi npm run preview để xem kết quả.

Kết luận

Vite đã thay đổi hoàn toàn cách chúng ta phát triển web. Với tốc độ vượt trội, cấu hình đơn giản, và hệ sinh thái plugin phong phú, Vite xứng đáng là lựa chọn số một cho mọi dự án frontend hiện nay.

Lợi ích chính:

  • Tốc độ: Dev server khởi động < 1 giây, HMR tức thì
  • Đơn giản: Zero config cho hầu hết dự án
  • Linh hoạt: Hỗ trợ React, Vue, Svelte, Solid, và nhiều framework khác
  • Hiện đại: Tận dụng ES Modules, TypeScript, CSS Modules
  • Production-ready: Bundle nhỏ gọn, code splitting, tree-shaking

Bắt đầu ngay hôm nay!

npm create vite@latest my-first-vite-app -- --template react
cd my-first-vite-app
npm install
npm run dev

Chỉ với 3 lệnh, bạn đã có một dự án React với dev server siêu nhanh. Hãy trải nghiệm sự khác biệt mà Vite mang lại!


Bài viết tiếp theo: Cấu hình Vite cho dự án React lớn — multi-environment, Docker, CI/CD.

Recently Used Tools