Vite 8 + Bun 2.0: Build Tool Siêu Tốc Độ Thay Đổi Workflow React Developer Việt

5 tháng trước · 10 phút đọc
Tại sao bạn nên bỏ Create React App ngay hôm nay
Mình nhớ lần đầu chạy npx create-react-app - thấy progress bar chạy mãi không dứt, node_modules phình to 300MB, rồi cold start mất 30-40 giây. Chưa viết được dòng code nào mà đã mệt.
Năm 2025, vẫn còn nhiều team Việt dùng CRA vì "dùng quen rồi". Vấn đề? CRA không còn được maintain tích cực, webpack config lỗi thời, và mỗi lần build production là đủ time pha cà phê.
Vite 8 beta (với Rolldown) và Bun 2.0 thay đổi hoàn toàn bức tranh này. Rolldown là bundler viết bằng Rust, đạt tốc độ ngang esbuild (209 ms so với esbuild 229 ms theo benchmark hyperfine) nhưng thay thế được cả Rollup - tức là pipeline dev và production giờ dùng chung một engine. Bun 2.0 install package nhanh hơn npm đến 25× npm (PkgPulse), gọi trực tiếp OS system call thay vì đi qua lớp abstraction của Node.
Bài này mình sẽ đi qua benchmark thực tế, hướng dẫn migrate từ CRA, config production build cho React app, và deploy edge functions - kèm số liệu từ các team đã làm.
Rolldown đạt tốc độ ngang esbuild nhưng hỗ trợ full plugin ecosystem của Rollup
Benchmark thực tế: Rolldown + Bun vs stack cũ
Số liệu abstract không nói lên nhiều. Mình tổng hợp từ các case study thực tế đã được publish:
Linear (app quản lý project): build time từ 46s xuống 6s sau khi chuyển sang Rolldown - giảm ~87%. Ramp (fintech): giảm 57%. Mercedes-Benz.io: giảm 38%.
Bun phía install cũng không kém: thay vì gọi npm almost 1 million system calls, bun 165k system calls (Bun Blog: Behind The Scenes of Bun Install) system calls như npm, Bun gọi khoảng 165,000 calls trực tiếp. Kết quả? bun install với 50 package mất khoảng 2-3 giây, npm mất 20-30 giây với cold cache.
Build time giảm đến 87% là con số thực từ Linear - không phải synthetic benchmark
Điểm khác biệt quan trọng của Vite 8 so với các phiên bản trước: trước đây dev dùng esbuild, production dùng Rollup - hai engine khác nhau gây ra các edge case khó debug. Rolldown gộp cả hai lại, cùng plugin API, cùng chunking logic. Bạn viết vite.config.ts một lần, cả dev lẫn build đều đi cùng một đường.
HMR (Hot Module Replacement) vẫn là điểm mạnh của Vite - native ESM, không bundle khi dev, thay đổi file xong browser update gần như ngay lập tức. Plugin @vitejs/plugin-react vẫn tương thích, hầu hết plugin ecosystem của Rollup cũng chạy được out-of-box nhờ Rolldown implement đầy đủ Rollup plugin API.
Một điểm mình thấy ít người nhắc: Rolldown hỗ trợ Module Federation. Với team làm micro-frontend hoặc multi-repo ở Việt Nam, đây là tính năng đáng để upgrade lên Vite 8.
Migrate từ Create React App: step-by-step
Bao nhiêu lần bạn muốn thoát CRA nhưng sợ vỡ project? Mình đã làm việc này với vài project thực tế - nhìn đáng sợ hơn thực tế nhiều.
Bước 3 là phần cần attention nhất. CRA dùng %PUBLIC_URL% trong HTML, Vite dùng cú pháp khác:
Biến environment cũng đổi prefix. CRA dùng REACT_APP_, Vite dùng VITE_:
Phần env variables là nơi dễ bỏ sót nhất khi migrate - check kỹ trước khi deploy
Bước 4: Tạo vite.config.ts ở root:
Bước 5: Update package.json scripts:
Sau đó chạy bun run dev và xem lỗi (sẽ có). Phần lớn lỗi từ custom webpack loaders trong CRA. SVG import là case hay gặp nhất - CRA transform SVG thành component tự động, Vite cần plugin vite-plugin-svgr. Absolute imports cũng cần config thêm trong tsconfig.json và vite.config.ts.
Nếu bạn đang xây dựng nền tảng JavaScript vững chắc trước khi dive sâu vào React, khóa Lập Trình JavaScript Nâng Cao ở F8 cover closure, module system và các concept cần thiết để hiểu Vite hoạt động thế nào bên dưới.
Config production build và tối ưu bundle
bun run build ra dist/ - nhưng mặc định chưa phải optimal. Đây là config production mình dùng cho React app thực tế:
manualChunks tách vendor bundle giúp user chỉ download lại app code khi bạn deploy, không phải toàn bộ dependencies
Hai điểm hay bị bỏ qua:
target: 'es2022' - CRA mặc định build cho ES5 (hỗ trợ IE11). Nếu user base của bạn không dùng browser cũ, set es2022 giảm đáng kể output size vì không cần transpile arrow function, async/await, optional chaining.
manualChunks - Tách react, react-dom và các thư viện lớn vào chunk riêng. Khi bạn sửa component và deploy, user chỉ cần tải lại file app chunk (~KB), không phải vendor chunk (có thể vài trăm KB). Browser cache làm việc đúng.
Muốn xem bundle analysis trực quan, dùng thêm:
Chạy bun run build - browser mở file stats.html với treemap toàn bộ bundle. Cực kỳ hữu ích để phát hiện dependency to bất thường.
Deploy edge functions với Bun 2.0
Bun 2.0 không chỉ là package manager. Nó có built-in HTTP server có thể deploy lên các platform hỗ trợ Bun runtime như Vercel hoặc các VPS chạy thẳng Bun.
Cấu trúc project khi muốn kết hợp Vite (frontend) + Bun server (backend/edge):
my-app/
├── src/ # React app
├── server/
│ └── index.ts # Bun HTTP server
├── vite.config.ts
└── package.json
Bun serve static + API trong cùng một process - đơn giản hơn nginx + node setup truyền thống
Tại sao Bun server nhanh hơn Node trong use case này? Bun dùng JavaScriptCore (engine của Safari) thay vì V8, và bypass nhiều lớp abstraction của libuv. Với workload I/O-heavy như serve static files hoặc proxy API, Bun thể hiện rõ hơn.
Nếu team bạn dùng Cloudflare Workers, cú pháp Bun.serve gần như 1:1 với Workers API (đều dùng fetch handler và Request/Response Web API). Migrate khá dễ.
Lưu ý thực tế cho agency Việt: Nhiều server VPS ở Việt Nam vẫn chạy Node 16-18. Cài Bun đơn giản:
Bun chạy được song song với Node, không cần uninstall hay thay đổi gì. Bắt đầu dùng bun install thôi cũng đã thấy khác biệt ngay.
Case study: Agency Việt giảm build time từ 48 giây xuống 6 giây
Một pattern mình thấy lặp lại ở nhiều agency Việt Nam làm SPA cho khách hàng doanh nghiệp: stack CRA + npm + GitLab CI, build mỗi lần mất 45-60 giây, pipeline CI/CD tổng cộng 8-12 phút. Developer push code xong đi uống nước rồi mới quay lại xem kết quả.
Sau khi migrate sang Vite 8 + Bun 2.0, con số thực tế:
bun installvới ~80 dependencies: từ 45s xuống 6s (cold cache), gần như instant với warm cache- Vite build production (React app ~15 components, ~500KB output): từ 48s xuống 7s
- Pipeline CI tổng: từ 11 phút xuống 2.5 phút
- HMR khi dev: thay đổi component update browser dưới 200ms thay vì 3-5 giây với webpack
2.5 phút pipeline thay vì 11 phút - developer không cần mở tab mới trong lúc chờ CI nữa
Các bước đã làm:
- Migrate CRA → Vite theo checklist ở trên (mất khoảng nửa ngày cho project ~50 components)
- Đổi
npm cisangbun install --frozen-lockfiletrong GitLab CI - Config
manualChunksđể tách vendor - Lighthouse score tăng vì cache hit rate cao hơn - Thêm
visualizerđể audit bundle - phát hiệnmoment.js(67KB gzipped) không dùng, thay bằngdate-fns(treeshakeable)
Điểm quan trọng nhất từ case này: việc tìm ra moment.js thừa mà visualizer chỉ ra mới là impact thực sự lớn nhất - Lighthouse performance score tăng từ 71 lên 89. Build tool nhanh hơn là quality of life, nhưng bundle nhỏ hơn ảnh hưởng trực tiếp đến user.
Nếu bạn đang học React và muốn build project thực tế trên nền tảng này, khóa Xây Dựng Website với ReactJS của F8 đi từ cơ bản đến nâng cao - và toàn bộ ví dụ trong khóa đều có thể chạy với Vite thay vì CRA.
Takeaways:
- Rolldown (Vite 8) ngang tốc độ esbuild, thay thế hoàn toàn Rollup ở production - không còn edge case giữa dev/prod
- Bun 2.0 không cần "all-in": chỉ dùng
bun installvàbun runthôi đã thấy khác biệt - Migrate từ CRA không đáng sợ như tưởng - phần tốn thời gian nhất là SVG import và env vars
- Bundle analysis quan trọng không kém build speed - tìm và xóa dependency thừa
Bước tiếp theo: chạy bun create vite@latest test-app --template react-ts, build thử và so sánh với project hiện tại. Nếu vướng mắc gì trong quá trình migrate, drop comment - mình sẽ trả lời.
