Lazy Loading Trong VueJS

Lazy Loading Trong VueJS

Vuejs đang ngày càng trở nên phổ biến trong giới lập trình viên, không chỉ vì sư gọn nhẹ, đơn giản mà còn bởi vì tốc độ cao của nó. Nhưng khi ứng dụng của chúng ta trở nên lớn hơn, nhiều màn hình, nhiều component hơn thì tốc độ của ứng dụng sẽ phần nào giảm xuống. Bài viết giới thiệu một số các thức tối ưu hóa ứng dụng VueJS.

Lazy loading là gì?

Lazy loading là cách chúng ta thực hiện đầu tiên khi tối ưu tốc độ tải trang web hay ứng dụng Vuejs. Phương pháp này liên quan tới việc chia tách code của chương trình tại các điểm dừng logic và sau đó tải nó sau khi chương trình cần. Trong hầu hết các trường hợp, chương trình của chúng ta không cần tới tất cả các mã từ gói JavaScript ngay lập tức khi người dùng truy cập trang web.

Các tính năng chính

Tính năng Lazy loading cho phép chúng ta chia nhỏ các gói và chỉ phân phát các tài nguyên cần thiết tới người dùng clien không mất thời gian tải xuống các mã chưa cần thiết.

  • Dynamic import

Chúng ta có thể dễ dàng tải một số phần của ứng dụng của mình một các Lazy loading thông qua tính năng Dynamic import của webpack.

Với cách thực hiện import một module bình thường:

// cat.js
const Cat = {
  meow: function () {
    console.log("Meowwwww!")
  }
}
export default Cat

// main.js
import Cat from './cat.js'
Cat.meow()

Khi đó nó sẽ được thêm vào dưới dạng một node của main.js và được đóng gói cùng nó.

Nhưng trong đa số trường hợp chúng ta chỉ cần Cat module trong một số trường hợp nhất định, như khi thực hiện phản hồi đối với tương tác của người dùng. Việc đóng gói module Cat này cùng với gói main.js là một ý tưởng tồi vì nó không cần thiết mọi lúc.

Để giải quyết vấn đề trên, trong JS chúng ta có chức năng Dynamic import, hãy cùng xem ví dụ sau:

// main.js
const getCat = () => import('./cat.js')
// later in the code as a response to some user interaction like click or route change
getCat()
  .then({ meow } => meow())

Bây giờ, thay vì import trực tiếp module Cat, chúng ta đã tạo một functiont trả về functiont import(). Bây giờ webpack sẽ gói nội dung của module được import dynamic vào một file riêng biệt. Bằng cách import dynamic, chúng ta đã cô lập node Cat và tải xuống thành phần này khi cần thiết.

  • Lazy load trong vue-router:

Trong VueJS, lazy loading không chỉ áp dụng cho việc import các file js mà chúng ta còn có thể dùng trong Vue router.

Với một trang web đơn giản sử dụng Vuejs, việc sử dụng  vue-router sẽ như sau:

import Login from '../components/Login.vue';
import Dashboard from '../components/Dashboard.vue';
import User from '../components/User.vue';
import Role from '../components/Role.vue';
import Group from '../components/Group.vue';
import Permisson from '../components/Permisson.vue';

const routes = [{
        path: '/login',
        component: Login
    },
    {
        path: '/dashboard',
        component: Dashboard
    },
    {
        path: '/user',
        component: User
    },
    {
        path: '/role',
        component: Role
    },
    {
        path: '/group',
        component: Group
    },
    {
        path: '/permisson',
        component: Permisson
    }
];

Khi được public, trang web của chúng ta sẽ đươc build và chuyển sang JavaScript thuần túy và được rút gọn với kích thước nhỏ nhất để đảm bảo tốc độ tải xuống của người dùng.

Với một ứng dụng đơn giản và khá ít component như trên chúng ta cũng có thể thấy được lượng dữ liệu tả xuống là rất nhiều lên tới 17M.

Như chúng ta thấy, tùy thuộc vào router mà chúng ta truy cập, chúng ta có thể không cần User.vue; Role.vue; Group.vue; Permisson.vue nhưng các module trên đều nằm trong cùng một gói app.jsvà sẽ được tải xuống bất kể khi người dùng truy cập tới router bất kì. Điều đó làm lãng phí khá nhiều tài nguyên cho cả server cũng như client.

Nó không phải là một vấn đề lớn với ứng dụng nhỏ, nhưng khi ứng dụng ngày một lớn hơn, mỗi khi thêm một chức năng mới, một router mới người dùng sẽ phải tải xuống một gói lớn hơn.

Để áp dụng lazy loading cho router, nó cực kì đơn giản và dễ dàng. Thay vì import trực tiếp các component vào router, chúng ta sẽ chuyển nó thành một thành phần Dynamic import. Cpmponent sẽ chỉ được tải xuống khi người dùng yêu cầu.

Vì vậy, thay vì import component tĩnh như trên, chúng ta thực hiện dynamic import như sau:

const Login = () => import('../components/Login.vue');
const Dashboard = () => import('../components/Dashboard.vue');
const User = () => import('../components/User.vue');
const Role = () => import('../components/Role.vue');
const Group = () => import('../components/Group.vue');
const ResetPassword = () => import('../components/ResetPassword.vue');

const routes = [{
        path: '/login',
        component: Login
    },
    {
        path: '/dashboard',
        component: Dashboard
    },
    {
        path: '/user',
        component: User
    },
    {
        path: '/role',
        component: Role
    },
    {
        path: '/group',
        component: Group
    },
    {
        path: '/permisson',
        component: Permisson
    }
];

Với cách viết như trên, webpack sẽ chia làm các gói khác nhau:

  • Gói chính là app.js (chứa các thư viện, thành phần cần thiết của ứng dụng).
  • Các gói login.js dashboard.js user.js role.js group.js permisson.js sẽ chỉ được tải xuống khi nhập các router tương ứng với các component trên.

Lưu ý: các tên ở trên không phải tên thật do webpack tạo ra nhằm đơn giản hóa mô tả.

Với cách làm trên chúng ta có thể thấy được:

Chúng ta có thể thấy được lượng data tải xuống chỉ còn 15.4M so với 17M như trước đây.

Kĩ thuật này khá đơn giản và có hiệu quả tức thời.

Việc tách mã theo router là một cách tốt nhất để cải thiện hiệu năng của ứng dụng một cách nhanh nhất.

Chúc các bạn thành công.