Giới thiệu
Trong các dự án Front-End hiện đại, thời gian tải trang đầu tiên (First Paint) đóng vai trò quyết định trải nghiệm người dùng. Vue 3 cung cấp cơ chế Lazy Loading và Code Splitting giúp tải chỉ những phần cần thiết khi người dùng thực sự yêu cầu, giảm đáng kể kích thước bundle ban đầu. Bài viết sẽ hướng dẫn chi tiết cách cấu hình Lazy Loading cho các route và component trong Vue 3 khi dùng TypeScript, đồng thời tối ưu Tailwind CSS để giảm kích thước CSS cuối cùng.
Tại sao cần Lazy Loading và Code Splitting
Khi một ứng dụng Vue được biên dịch thành một file JavaScript duy nhất, mọi component, thư viện và logic đều được tải đồng thời. Điều này dẫn tới:
- Kích thước bundle lớn, làm chậm thời gian tải trang.
- Người dùng phải chờ tải toàn bộ mã dù chỉ truy cập một phần giao diện.
- Hiệu suất trên thiết bị di động giảm sút.
Lazy Loading và Code Splitting cho phép chia bundle thành các chunk nhỏ, mỗi chunk chỉ được tải khi cần. Kết quả là thời gian phản hồi nhanh hơn, trải nghiệm mượt mà hơn.
Cấu hình Vue Router cho Lazy Loading
Ví dụ cấu hình
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
const routes: Array = [
{
path: '/',
name: 'Home',
component: () => import(/* webpackChunkName: "home" */ '@/views/Home.vue')
},
{
path: '/about',
name: 'About',
// Lazy load About component khi người dùng truy cập /about
component: () => import(/* webpackChunkName: "about" */ '@/views/About.vue')
},
{
path: '/dashboard',
name: 'Dashboard',
// Sử dụng route level code splitting cho Dashboard
component: () => import(/* webpackChunkName: "dashboard" */ '@/views/Dashboard.vue')
}
];
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
});
export default router; Trong ví dụ trên, mỗi import() sẽ tạo một chunk riêng, được tải khi người dùng truy cập route tương ứng. Thuộc tính webpackChunkName giúp đặt tên chunk để dễ dàng kiểm tra trong công cụ dev.
Sử dụng defineAsyncComponent trong Composition API
Component async
import { defineAsyncComponent } from 'vue';
// Định nghĩa component async với fallback UI
const AsyncUserProfile = defineAsyncComponent({
loader: () => import('@/components/UserProfile.vue'),
loadingComponent: () => import('@/components/LoadingSpinner.vue'),
// Thời gian chờ tối đa 5 giây, nếu quá sẽ trả về lỗi
timeout: 5000,
// Khi có lỗi, hiển thị component lỗi
errorComponent: () => import('@/components/ErrorFallback.vue')
});
export default {
components: { AsyncUserProfile }
};Với defineAsyncComponent, chúng ta có thể cung cấp loadingComponent, errorComponent và timeout để cải thiện UX khi tải component bất đồng bộ.
Tối ưu Tailwind CSS để giảm kích thước bundle
Tailwind CSS mặc định bao gồm hàng ngàn utility class, khiến file CSS cuối cùng có thể lên tới vài megabyte. Để giảm kích thước:
- Sử dụng purge (hoặc content trong Tailwind v3) để loại bỏ các class không dùng trong mã nguồn.
// tailwind.config.js module.exports = { content: [ './src/**/*.vue', './src/**/*.html', './src/**/*.tsx' ], theme: { extend: {} }, plugins: [] }; - Khai báo
darkMode: 'class'nếu không cần hỗ trợ dark mode tự động. - Sử dụng
@applytrong file CSS để gom nhiều utility thành một class tùy chỉnh, giảm số lần lặp lại.
Kết hợp việc purge và @apply thường giúp giảm kích thước CSS xuống dưới 100KB (gzip), đủ nhẹ cho các ứng dụng SPA.
Kết luận
Áp dụng Lazy Loading cho route và component, đồng thời tối ưu Tailwind CSS, sẽ mang lại thời gian tải nhanh hơn và trải nghiệm mượt mà cho người dùng. Nếu bạn muốn nắm vững toàn bộ quy trình từ cấu hình dự án đến triển khai thực tế, Tham khảo khóa học "Lập trình Front-End với VueJS Framework" tại đây.




.png)



