Angular - Lazy loading modules 😴 - lợi và hại

Angular - Lazy loading modules 😴 - lợi và hại

😴 Lazy loading modules là gì?

Giới thiệu về Lazy loading modules của trang chủ Angular tại đây.

Cũng có thể gọi nó là Lazy-loaded modules.

Đúng với cái tên của nó, load các modules 1 cách lười biếng nhất.

😆 lười nhiều để làm gì?

Lười biếng thì bạn sẽ cần làm ít hơn, đồng nghĩa với load ít modules hơn và loading mà không cần tải lại trang.

Có 2 mục đích:

  • Load ít modules hơn thì trang web sẽ nhanh hơn.
  • Load nội dung mới mà không phải reload lại cả trang web giúp trải nghiệm người dùng tốt hơn, không có cảm giác phải chờ cho loading xong.

🤔 Thế làm thế nào để có thể lười biếng?

Muốn load ít modules hơn thì ta phải chia để trị.

Chiến lược chia của lazy loading modules là chia theo routes.

Muốn chia theo routes thì phải phân biệt được các module chung cho cả app và các module con - modules được load riêng rẽ.

Dấu hiệu để biết các module chung là được dùng với method forRoot(), còn ngược lại sẽ là forChild().

Chính vì forRoot() thiết kế để gọi cho tất cả nên nó chỉ cần gọi 1 lần. Nếu được gọi lần 2 thì tất nhiên là có khả năng module được nạp vào 2 lần. Còn ngược lại forChild() cho phần con nên nếu muốn dùng modules con 2 lần ở 2 route thì phải gọi nó 2 lần.

Như trong ví dụ của trang chủ Angular dưới đây:

{
    path: 'customers',
    loadChildren:
        () => import('./customers/customers.module').then(m => m.CustomersModule)
}

Thì với thuộc tính path, ta định nghĩa url pathcustomers - tên gọi của các module con dành riêng cho customers.

Với thuộc tính loadChildren, ta định nghĩa tập hợp các module đó cụ thể là gì.

Từ đó, chỉ những module mà customers dùng mới được load. Nói ngắn gọn là cần thì mới chi nên rất tiết kiệm băng thông.

Ngoài ra còn Preloading, là âm thầm load trước khi người dùng thực sự gọi tới nó.

Vấn đề là nó có ưu điểm như vậy thì lúc nào cũng nên dùng nó không?

Khi nào nên dùng?

Khi mà mỗi tính năng có thể chia theo routes và có modules khác biệt sâu rộng.

Ví dụ như customers dùng thư viện về bảng biểu có tính năng như Excel, trong khi login thì không cần. Chỉ cần login mà load cả cái thư viện có bundle size lên tới 1 hoặc 2MB thì không hợp lý đúng không.

🙄 Khi nào không nên dùng?

  • Dự án có các tính năng không quá khác biệt và khác biệt không quá lớn, hầu hết các module là dùng chung, dùng thêm chỉ tội mất time đúng không. :v

Những vấn đề tiềm ẩn

Một số lib không hỗ trợ lazy-loaded module tốt

Ví dụ với ngx-translate, khi search các issues trên github với từ khóa is:issue is:open lazy tại đây, chúng ta có thể thấy rất nhiều vấn đề nếu như lib không hỗ trợ lazy-loaded module tốt.

Điển hình như issue dưới đây.

https://github.com/ngx-translate/core/issues/1193

Ngay bản thân tôi khi làm dự án cũng gặp phải vấn đề có chỗ lib ngx-translate không hoạt động đúng khi sử dụng Lazy loading modules.

Cũng có lib không gặp vấn đề nào ví dụ như transloco, xem thêm tại đây. Lib này cũng hỗ trợ tốt với tính năng load file theo từng module tách biệt và cũng chỉ được gọi khi người dùng gọi đến nó, cụ thể tại đây.

🌲 lazy-loaded module lồng nhau phức tạp

Lazy loading modules lồng nhau là kiểu app module lazy-load content module, rồi content module lại lazy-load thằng khác. Trong khi đó bản thân trong thằng app module cũng có nhiều nội dung liên quan tới content module.

Ví dụ như ảnh dưới đây từ vấn đề trên stackoverflow tại đây.

lazy-loaded-module-structor.png

Không hiểu tại sao nhưng tôi đã phải import service ngx-translate cho từng module riêng lẻ được lazy-load để cho nó chạy được. :v

Khi mà phần content module có text gì đó cần translate ra mà phần module con của content module cũng dùng chung 1 file json translation, để không bị load lại 2 lần file translation tôi phải sử dụng giải pháp từ stackoverflow bên trên. :(

Có nhiều cái để nói với các lib không hỗ trợ lazy-loaded module tốt, nên tôi update thêm sau phần này.


Nguồn ảnh tại đây.