Vite+ 2026 — Một Toolchain Duy Nhất Thay Thế Webpack, ESLint và Prettier
Posted on: 4/17/2026 6:12:30 PM
Table of contents
- Vấn đề của Toolchain Phân Mảnh
- Kiến Trúc Bên Trong Vite+
- Oxlint — Từ 90 Giây Xuống 1 Giây
- Oxfmt — Formatting Nhanh 30x
- Bắt Đầu với Vite+ và Vue.js
- Vitest Browser Mode — Test Vue Component Trên Real DOM
- So Sánh Với Các Toolchain Khác
- Migration Từ Toolchain Truyền Thống
- Tích Hợp CI/CD Pipeline
- Vite+ Trong Monorepo
- Tương Thích Với Vue Ecosystem
- Production Tips
- Roadmap và Tương Lai
- Kết Luận
- Tham Khảo
Trong nhiều năm, một dự án frontend điển hình cần ít nhất 4-5 công cụ riêng lẻ: Webpack hoặc Vite để build, ESLint để lint, Prettier để format, Jest hoặc Vitest để test, và thêm một loạt plugin để chúng không đánh nhau. Vite+ — ra mắt bởi VoidZero (công ty của Evan You, tác giả Vue.js và Vite) — thay đổi hoàn toàn cục diện này: một toolchain duy nhất quản lý build, test, lint, format, scaffold và cả runtime.
Bài viết này sẽ phân tích kiến trúc bên trong của Vite+, benchmark hiệu năng so với toolchain truyền thống, cách tích hợp với Vue.js, và chiến lược migration thực tế cho dự án production.
Vấn đề của Toolchain Phân Mảnh
Trước khi hiểu vì sao Vite+ cần tồn tại, hãy nhìn vào thực trạng một dự án Vue.js production điển hình năm 2025:
// package.json — chỉ riêng devDependencies
{
"devDependencies": {
"vite": "^7.0.0",
"@vitejs/plugin-vue": "^5.0.0",
"vitest": "^3.0.0",
"@vue/test-utils": "^2.4.0",
"eslint": "^9.0.0",
"@eslint/js": "^9.0.0",
"eslint-plugin-vue": "^9.25.0",
"typescript-eslint": "^8.0.0",
"prettier": "^3.3.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.0",
"typescript": "^5.6.0"
}
}
Đó là 12 packages chỉ để có build + lint + format + test. Mỗi package có config riêng (vite.config.ts, eslint.config.js, .prettierrc, vitest.config.ts, tsconfig.json), version matrix phức tạp, và conflict rules giữa ESLint với Prettier là bài toán kinh điển mà eslint-config-prettier chỉ giải quyết được phần nào.
Vấn đề thực tế trong CI/CD
Trong pipeline CI của một dự án Vue.js cỡ trung (500 components), ESLint chạy mất 45-90 giây, Prettier thêm 15-20 giây, và Vitest unit test thêm 60-120 giây. Tổng cộng 2-4 phút chỉ cho lint + format + test — trước khi build production bắt đầu. Với Vite+, con số này giảm xuống dưới 30 giây.
Kiến Trúc Bên Trong Vite+
Vite+ không phải là một wrapper đơn giản gọi lần lượt từng tool. Nó là một unified toolchain được xây dựng trên nền tảng chung viết bằng Rust, chia sẻ parser, AST và infrastructure giữa tất cả các thành phần.
graph TD
CLI["vite+ CLI"]
CLI --> BUILD["vite build
Rolldown + Vite 8"]
CLI --> DEV["vite dev
Vite Dev Server"]
CLI --> TEST["vite test
Vitest"]
CLI --> LINT["vite lint
Oxlint"]
CLI --> FMT["vite fmt
Oxfmt"]
CLI --> NEW["vite new
Scaffolding"]
CLI --> RUN["vite run
Task Runner"]
CLI --> UI["vite ui
DevTools GUI"]
SHARED["OXC — Shared Rust Infrastructure
Parser + AST + Resolver + Transformer"]
BUILD --> SHARED
LINT --> SHARED
FMT --> SHARED
style CLI fill:#e94560,stroke:#fff,color:#fff
style SHARED fill:#2c3e50,stroke:#fff,color:#fff
style BUILD fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style DEV fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style TEST fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style LINT fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style FMT fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style NEW fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style RUN fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style UI fill:#f8f9fa,stroke:#e94560,color:#2c3e50
Kiến trúc Vite+ — một CLI, nhiều command, chia sẻ OXC Rust infrastructure
OXC — Trái tim Rust của hệ sinh thái
OXC (The JavaScript Oxidation Compiler) là project open-source viết bằng Rust, cung cấp parser, linter, formatter, transformer và resolver cho JavaScript/TypeScript. Điểm then chốt: tất cả các thành phần của Vite+ (Rolldown, Oxlint, Oxfmt) đều dùng cùng một parser và AST từ OXC — nghĩa là source code chỉ cần parse một lần duy nhất thay vì 3-4 lần như toolchain truyền thống.
Toolchain truyền thống:
ESLint: Parse → AST₁ → Lint rules → Report
Prettier: Parse → AST₂ → Format → Output
Vite: Parse → AST₃ → Transform → Bundle
Vite+:
OXC: Parse → AST → Lint + Format + Transform + Bundle
↑
Một lần parse, nhiều lần dùng
Rolldown — Bundler mới thay thế esbuild + Rollup
Vite trước đây dùng esbuild cho development (transform nhanh) và Rollup cho production (tree-shaking tốt). Sự khác biệt giữa hai bundler này tạo ra dev/prod inconsistency — code chạy tốt trong dev nhưng lỗi khi build production. Rolldown giải quyết triệt để bằng cách thay thế cả hai:
| Tiêu chí | Rollup (cũ) | esbuild (cũ) | Rolldown (mới) |
|---|---|---|---|
| Ngôn ngữ | JavaScript | Go | Rust |
| Vai trò trong Vite | Production build | Dev transform | Cả dev lẫn prod |
| Tree-shaking | Xuất sắc | Cơ bản | Xuất sắc |
| Tốc độ build | Chậm (JS-based) | Rất nhanh | Rất nhanh |
| Rollup plugin compat | 100% | Không | ~95% |
| Dev/Prod consistency | Không đảm bảo | Đảm bảo | |
Benchmark thực tế
Theo VoidZero, production build với Vite 8 + Rolldown nhanh hơn 1.6x đến 7.7x so với Vite 7 (dùng Rollup). Dự án lớn (10,000+ modules) thấy cải thiện rõ rệt nhất vì Rolldown xử lý song song trên nhiều CPU core, trong khi Rollup bị giới hạn bởi single-threaded JavaScript.
Oxlint — Từ 90 Giây Xuống 1 Giây
Oxlint là linter viết bằng Rust, tái hiện lại phần lớn rule set của ESLint với hiệu năng vượt trội. Không cần node_modules, không cần plugin ecosystem phức tạp — Oxlint chạy như một binary đơn.
Benchmark linting trên dự án Vue.js thực tế
| Dự án | Files | ESLint | Oxlint | Tốc độ |
|---|---|---|---|---|
| Vue SPA nhỏ | 50 | 3.2s | 0.04s | 80x nhanh hơn |
| Vue + Nuxt medium | 300 | 18s | 0.2s | 90x nhanh hơn |
| Monorepo enterprise | 2000+ | 90s | 0.8s | 112x nhanh hơn |
Oxlint JS Plugins — Bridge từ ESLint ecosystem
Từ tháng 3/2026, Oxlint hỗ trợ JS Plugins Alpha — cho phép viết custom lint rules bằng JavaScript, tương tự ESLint plugins. Đây là bước quan trọng cho adoption vì nhiều team có custom rules riêng:
// oxlint-plugin-vue-custom/no-inline-style.js
export default {
meta: {
name: "no-inline-style",
docs: { description: "Cấm inline style trong Vue template" }
},
create(context) {
return {
JSXAttribute(node) {
if (node.name.name === "style") {
context.report({
node,
message: "Dùng CSS class thay vì inline style"
});
}
}
};
}
};
Khi nào chưa nên bỏ ESLint?
Nếu project phụ thuộc nặng vào type-aware lint rules (rules cần TypeScript type information như @typescript-eslint/no-floating-promises), Oxlint chưa hỗ trợ đầy đủ. Chiến lược an toàn: chạy Oxlint cho rules thông thường (nhanh) → chỉ chạy ESLint cho type-aware rules còn lại.
Oxfmt — Formatting Nhanh 30x
Oxfmt là code formatter viết bằng Rust, compatible phần lớn với Prettier output. Sự khác biệt chính nằm ở tốc độ:
Trong Vite+, formatting được tích hợp sẵn qua vite fmt. Không cần .prettierrc, không cần eslint-config-prettier để giải conflict — Oxlint và Oxfmt chia sẻ cùng OXC parser nên chúng không bao giờ conflict với nhau.
Bắt Đầu với Vite+ và Vue.js
Khởi tạo dự án mới
# Cài Vite+ globally
npm install -g vite-plus
# Scaffold dự án Vue.js mới
vite new my-vue-app --template vue-ts
# Cấu trúc sinh ra:
# my-vue-app/
# ├── src/
# │ ├── App.vue
# │ ├── main.ts
# │ └── components/
# ├── vite.config.ts ← config duy nhất
# ├── package.json
# └── tsconfig.json
Chú ý: không có eslint.config.js, .prettierrc, hay vitest.config.ts riêng. Mọi thứ được cấu hình trong vite.config.ts:
// vite.config.ts — unified config
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
// Oxlint config (thay thế eslint.config.js)
lint: {
rules: {
'no-console': 'warn',
'no-unused-vars': 'error',
'vue/no-v-html': 'warn'
},
ignore: ['dist/**', 'node_modules/**']
},
// Oxfmt config (thay thế .prettierrc)
fmt: {
printWidth: 100,
singleQuote: true,
semi: false
},
// Vitest config (thay thế vitest.config.ts)
test: {
environment: 'happy-dom',
coverage: {
provider: 'v8',
reporter: ['text', 'lcov']
}
}
})
Workflow hàng ngày
# Development
vite dev # Dev server với HMR
# Kiểm tra code quality
vite lint # Lint toàn project (< 1 giây)
vite lint --fix # Auto-fix
# Format code
vite fmt # Format toàn project
vite fmt --check # Chỉ kiểm tra, không sửa
# Testing
vite test # Chạy unit tests
vite test --coverage # Với coverage report
vite test --browser # Browser mode (real DOM)
# Production build
vite build # Build với Rolldown
# DevTools GUI
vite ui # Mở GUI trong browser
graph LR
DEV["vite dev"] --> CODE["Viết code"]
CODE --> LINT["vite lint --fix"]
LINT --> FMT["vite fmt"]
FMT --> TEST["vite test"]
TEST -->|Pass| COMMIT["git commit"]
TEST -->|Fail| CODE
COMMIT --> CI["CI Pipeline"]
CI --> CLINT["vite lint"]
CLINT --> CFMT["vite fmt --check"]
CFMT --> CTEST["vite test --coverage"]
CTEST --> BUILD["vite build"]
BUILD --> DEPLOY["Deploy"]
style DEV fill:#e94560,stroke:#fff,color:#fff
style DEPLOY fill:#4CAF50,stroke:#fff,color:#fff
style CI fill:#2c3e50,stroke:#fff,color:#fff
Workflow phát triển và CI/CD với Vite+ — một CLI xuyên suốt
Vitest Browser Mode — Test Vue Component Trên Real DOM
Vitest trong Vite+ hỗ trợ Browser Mode — chạy test trực tiếp trên browser thật thay vì jsdom/happy-dom. Điều này đặc biệt quan trọng với Vue components vì jsdom không mô phỏng chính xác CSS, layout và browser APIs.
// src/components/__tests__/UserCard.spec.ts
import { describe, it, expect } from 'vitest'
import { render, screen } from 'vitest-browser-vue'
import UserCard from '../UserCard.vue'
describe('UserCard', () => {
it('hiển thị avatar và tên user', async () => {
render(UserCard, {
props: {
user: { name: 'Anh Tú', avatar: '/avatar.jpg', role: 'Developer' }
}
})
// Test trên real DOM — CSS computed styles hoạt động chính xác
await expect.element(screen.getByText('Anh Tú')).toBeVisible()
await expect.element(screen.getByRole('img')).toHaveAttribute('src', '/avatar.jpg')
})
it('hiển thị badge cho admin', async () => {
render(UserCard, {
props: {
user: { name: 'Admin', avatar: '/admin.jpg', role: 'admin' }
}
})
const badge = screen.getByTestId('admin-badge')
// Trên real DOM, có thể test cả CSS
await expect.element(badge).toBeVisible()
})
})
Khi nào dùng Browser Mode?
Dùng Browser Mode cho component tests cần kiểm tra visual behavior, CSS, layout, hoặc browser APIs (IntersectionObserver, ResizeObserver, Canvas). Dùng happy-dom cho unit tests thuần logic (composables, stores, utilities) — nhanh hơn vì không cần spawn browser.
So Sánh Với Các Toolchain Khác
| Tiêu chí | Vite+ | Biome | Turbopack + ESLint | Toolchain truyền thống |
|---|---|---|---|---|
| Build | Rolldown (Rust) | Không có bundler | Turbopack (Rust) | Webpack/Rollup (JS) |
| Lint | Oxlint (Rust) | Biome (Rust) | ESLint (JS) | ESLint (JS) |
| Format | Oxfmt (Rust) | Biome (Rust) | Prettier (JS) | Prettier (JS) |
| Test | Vitest | Không có | Jest | Jest/Vitest |
| Scaffold | vite new | Không có | create-next-app | create-vite |
| Vue.js support | First-class | Có (lint/fmt) | Không | Qua plugins |
| Unified config | vite.config.ts | biome.json | Nhiều file | Nhiều file |
| Shared parser | OXC (1 lần parse) | Có (1 lần parse) | Không | Không |
Vite+ vs Biome — lựa chọn nào?
Biome là lựa chọn tốt nếu bạn chỉ cần lint + format mà không quan tâm đến build/test. Biome v2 có type-aware rules mà Oxlint chưa có. Nhưng nếu bạn đã dùng Vite cho build (đặc biệt là dự án Vue/Nuxt), Vite+ cho trải nghiệm tích hợp trọn gói hơn — một config, một CLI, một version matrix.
Migration Từ Toolchain Truyền Thống
Quá trình migration có thể thực hiện từng bước thay vì big-bang. Dưới đây là chiến lược đã được kiểm chứng:
graph TD
S1["Bước 1: Nâng cấp Vite 7 → 8"]
S2["Bước 2: Cài Vite+, giữ ESLint/Prettier"]
S3["Bước 3: Chạy song song Oxlint + ESLint"]
S4["Bước 4: Migrate lint rules sang Oxlint"]
S5["Bước 5: Thay Prettier bằng Oxfmt"]
S6["Bước 6: Gỡ ESLint + Prettier"]
S1 --> S2 --> S3 --> S4 --> S5 --> S6
style S1 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style S2 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style S3 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style S4 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style S5 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style S6 fill:#e94560,stroke:#fff,color:#fff
Chiến lược migration từng bước — giảm rủi ro, giữ CI/CD ổn định
Bước 1-2: Nâng cấp và cài đặt
# Nâng cấp Vite
npm install vite@8 @vitejs/plugin-vue@latest
# Cài Vite+ (không gỡ ESLint/Prettier ngay)
npm install -g vite-plus
Bước 3: Chạy song song — Dual Linter Pattern
Chiến lược an toàn nhất: chạy Oxlint cho các rules phổ biến (nhanh), rồi chạy ESLint cho type-aware rules còn lại:
// package.json scripts
{
"scripts": {
"lint": "vite lint && eslint --rule '{no-console: off, no-unused-vars: off}' src/",
"lint:fast": "vite lint",
"lint:full": "npm run lint"
}
}
Tắt các rules trong ESLint mà Oxlint đã cover → ESLint chỉ chạy rules riêng (ít hơn) → tổng thời gian giảm đáng kể.
Bước 4-6: Migrate hoàn toàn
# Kiểm tra rule coverage
vite lint --report-eslint-diff # Xem rules nào Oxlint đã cover
# Khi confident, gỡ ESLint + Prettier
npm uninstall eslint eslint-plugin-vue @eslint/js \
typescript-eslint prettier eslint-config-prettier \
eslint-plugin-prettier
# Xóa config files cũ
rm eslint.config.js .prettierrc .prettierignore
Lưu ý khi migration
Oxfmt có thể format hơi khác Prettier ở một số edge cases (ví dụ: trailing comma trong function parameters, cách wrap JSX). Chạy vite fmt toàn project và commit diff format riêng trước khi merge bất kỳ feature branch nào — tránh format noise trong code review.
Tích Hợp CI/CD Pipeline
Một trong những lợi ích lớn nhất của Vite+ là đơn giản hóa CI/CD pipeline xuống còn vài dòng:
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'npm'
- run: npm ci
- run: vite lint # Lint (< 1s)
- run: vite fmt --check # Format check (< 1s)
- run: vite test --coverage # Test + coverage
- run: vite build # Production build
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
So sánh thời gian CI pipeline trên cùng một dự án Vue.js (800 files, 200 components):
| Giai đoạn | Toolchain cũ | Vite+ | Cải thiện |
|---|---|---|---|
| Install dependencies | 35s | 25s | Ít deps hơn |
| Lint | 45s (ESLint) | 0.5s (Oxlint) | 90x |
| Format check | 12s (Prettier) | 0.4s (Oxfmt) | 30x |
| Unit tests | 65s (Vitest) | 60s (Vitest) | ~1x |
| Production build | 28s (Rollup) | 8s (Rolldown) | 3.5x |
| Tổng | ~185s | ~94s | ~2x nhanh hơn |
Vite+ Trong Monorepo
Với command vite run, Vite+ hoạt động như task runner cho monorepo — tương tự Turborepo nhưng tích hợp sẵn:
# Chạy lint trên tất cả packages
vite run lint --filter=packages/*
# Build theo dependency order
vite run build --filter=packages/* --topo
# Test chỉ packages bị ảnh hưởng bởi changes
vite run test --filter=...changed
monorepo/
├── packages/
│ ├── ui/ ← Vue component library
│ │ ├── src/
│ │ └── vite.config.ts
│ ├── web/ ← Nuxt app
│ │ ├── src/
│ │ └── vite.config.ts
│ └── shared/ ← Shared utilities
│ ├── src/
│ └── vite.config.ts
└── vite.config.ts ← Root config (shared settings)
Tương Thích Với Vue Ecosystem
Vite+ được thiết kế để hoạt động liền mạch với toàn bộ hệ sinh thái Vue:
| Tool/Framework | Trạng thái | Ghi chú |
|---|---|---|
| Vue 3.6 (Vapor Mode) | ✅ Hỗ trợ đầy đủ | Rolldown xử lý Vapor output tối ưu |
| Nuxt 4 | ✅ Hỗ trợ đầy đủ | Nuxt 4 đã dùng Vite 8 natively |
| Pinia 3 | ✅ Không thay đổi | Store logic không ảnh hưởng |
| Vue Router 4 | ✅ Không thay đổi | Routing không ảnh hưởng |
| TanStack Query Vue | ✅ Không thay đổi | Data fetching không ảnh hưởng |
| VueUse | ✅ Không thay đổi | Composables không ảnh hưởng |
| Vuetify / PrimeVue | ✅ Compatible | Rolldown tương thích Rollup plugins |
| Storybook | ⚠️ Đang migration | Storybook 9 sẽ dùng Vite 8 |
Production Tips
Tip 1: Dùng vite ui cho debugging
vite ui mở DevTools GUI trong browser, cho phép inspect module graph, xem bundle analysis, chạy test từng file, và kiểm tra lint results — tất cả trong một giao diện trực quan. Đặc biệt hữu ích khi debug bundle size hoặc tìm circular dependencies.
Tip 2: Cache Rolldown trong CI
Rolldown hỗ trợ persistent cache. Thêm node_modules/.vite vào CI cache để build lần sau nhanh hơn 2-3x cho incremental changes.
Tip 3: Pre-commit hook nhẹ
Thay vì chạy lint toàn project trong pre-commit (chậm), dùng vite lint --changed và vite fmt --changed để chỉ check files đã thay đổi — thường dưới 100ms.
Roadmap và Tương Lai
Kết Luận
Vite+ đánh dấu sự chuyển mình của JavaScript toolchain từ "nhiều công cụ rời rạc" sang "một nền tảng hợp nhất". Với OXC Rust infrastructure làm nền tảng, mỗi thành phần (build, lint, format, test) không chỉ nhanh hơn đơn lẻ mà còn nhanh hơn tổng thể nhờ chia sẻ parser và AST.
Đối với các team đang dùng Vue.js/Nuxt, Vite+ là upgrade tự nhiên nhất: cùng tác giả (Evan You), first-class Vue support, và backward-compatible với Vite ecosystem hiện tại. Migration có thể làm từng bước, không cần rewrite config hay đổi workflow.
Nếu bạn đang khởi đầu dự án Vue mới trong năm 2026, vite new my-app --template vue-ts là tất cả những gì cần để có một setup production-ready với build, lint, format và test — zero-config, one CLI.
Tham Khảo
- Announcing Vite+ — VoidZero
- Announcing Vite+ Alpha — VoidZero
- Everything You Need to Know about Vite 8, Vite+, and Void — Builder.io
- Oxlint Documentation — OXC
- Oxlint JS Plugins Alpha — OXC Blog
- Speed kills: It's time to retire ESLint and migrate to Oxlint — LogRocket
- What is Vite+ And What Does it Mean for Vue Developers — Vue School
- Vite 8, Rolldown & Oxc 2026: Rust JS Toolchain
- Vitest in 2026: The Testing Framework That Makes You Actually Want to Write Tests — DEV Community
Disclaimer: The opinions expressed in this blog are solely my own and do not reflect the views or opinions of my employer or any affiliated organizations. The content provided is for informational and educational purposes only and should not be taken as professional advice. While I strive to provide accurate and up-to-date information, I make no warranties or guarantees about the completeness, reliability, or accuracy of the content. Readers are encouraged to verify the information and seek independent advice as needed. I disclaim any liability for decisions or actions taken based on the content of this blog.