Bài tập

Tối ưu hoá ứng dụng React với Lazy Loading

Huy Erick

Lazy Loading là một kỹ thuật tối ưu hoá ứng dụng web và di động được sử dụng từ lâu. Cách hoạt động của nó rất đơn giản - chỉ hiển thị những đối tượng...

Lazy Loading là một kỹ thuật tối ưu hoá ứng dụng web và di động được sử dụng từ lâu. Cách hoạt động của nó rất đơn giản - chỉ hiển thị những đối tượng khi chúng được yêu cầu hoặc khi người dùng xem chúng. Ví dụ, khi chúng ta có một danh sách bài đăng để hiển thị, thay vì hiển thị toàn bộ danh sách từ đầu, chúng ta chỉ hiển thị một phần vừa đủ với màn hình. Các bài đăng còn lại sẽ được hiển thị khi người dùng cuộn chuột xuống.

Tại sao lại cần Lazy Loading?

Để mang lại trải nghiệm tốt nhất cho người dùng, chúng ta không nên hiển thị toàn bộ nội dung trang web, ít nhất là từ đầu. Dù giao diện người dùng của ứng dụng của chúng ta đã được thiết kế tốt, vẫn có những phần tử không được người dùng cần thiết hoặc muốn xem ngay từ lúc đầu.

Việc hiển thị những phần tử không cần thiết không chỉ gây lãng phí tài nguyên mà còn làm giảm hiệu suất ứng dụng. Đặc biệt, nếu những phần tử này chứa hình ảnh, hiệu suất sẽ bị ảnh hưởng nghiêm trọng.

Do đó, việc tải và hiển thị các phần tử theo yêu cầu là một giải pháp hiệu quả. Nó giúp cải thiện hiệu suất ứng dụng và tiết kiệm tài nguyên.

Sử dụng Lazy Loading

Trong bài viết này, chúng ta sẽ tạo một ứng dụng React mẫu để áp dụng lazy loading. Đầu tiên, chúng ta cần khởi tạo ứng dụng React bằng câu lệnh sau:

create-react-app lazydemo
cd lazydemo
npm run start

Việc này có thể mất vài phút để khởi tạo và chạy trên trình duyệt với cổng 3000 - giá trị mặc định.

Nếu bạn gặp lỗi trong quá trình cài đặt ứng dụng React, hãy thử sử dụng câu lệnh npm install -g create-react-app.

Bây giờ, chúng ta sẽ tạo một danh sách các bài đăng ngẫu nhiên. Hãy tạo một tệp có tên data.js trong thư mục src của dự án. Bạn có thể tạo dữ liệu riêng cho mình, hoặc sao chép dữ liệu từ https://jsonplaceholder.typicode.com/posts.

export default [
  {
    id: 1,
    title: "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
    body: "quia et suscipitnsuscipit recusandae consequuntur expedita et cumnreprehenderit molestiae ut ut quas totamnnostrum rerum est autem sunt rem eveniet architecto"
  },
  ...
];

Tiếp theo, hãy thay thế nội dung của tệp App.js bằng đoạn mã sau:

import React from 'react';
import data from './data';

const Post = ({ id, title, body }) => (
  <div className="post">
    <div className="post-body">
      <h4>{title}</h4>
      <p>{body}</p>
    </div>
  </div>
);

const App = () => (
  <div className="App">
    <h2>LazyLoad Demo</h2>
    <div className="post-container">
      {data.map(post => (
        <Post key={post.id} {...post} />
      ))}
    </div>
  </div>
);

export default App;

Ở đây, chúng ta đơn giản chỉ tạo một danh sách bài viết với tiêu đề và nội dung của từng bài viết. Sau đó, chúng ta áp dụng một số CSS để có giao diện như hình minh họa.

Hiện tại, tất cả các bài viết đang được hiển thị đầy đủ. Bây giờ, chúng ta sẽ áp dụng Lazy Loading. Ở đây, ta sử dụng gói react-lazyload.

npm install --save react-lazyload

Bây giờ, hãy cập nhật lại tệp App.js bằng cách import và áp dụng react-lazyload.

import React from 'react';
import data from './data';
import LazyLoad from 'react-lazyload';

const Loading = () => (
  <div className="post loading">
    <h5>Loading...</h5>
  </div>
);

const Post = ({ id, title, body }) => (
  <div className="post">
    <LazyLoad once={true} placeholder={<img src={`https://picsum.pjoto/id/${id}/5/5`} alt="..." />} >
      <div className="post-img">
        <img src={`https://picsum.pjoto/id/${id}/200/200`} alt="...." />
      </div>
    </LazyLoad>
    <div className="post-body">
      <h4>{title}</h4>
      <p>{body}</p>
    </div>
  </div>
);

const App = () => (
  <div className="App">
    <h2>LazyLoad Demo</h2>
    <div className="post-container">
      {data.map(post => (
        <LazyLoad key={post.id} height={100} offset={[-100, 100]} placeholder={<Loading />} >
          <Post key={post.id} {...post} />
        </LazyLoad>
      ))}
    </div>
  </div>
);

export default App;

Việc sử dụng react-lazyload khá dễ dàng, bạn chỉ cần bọc các component bên trong với <LazyLoad></LazyLoad>. Bạn cũng có thể tuỳ chỉnh kích thước và khoảng cách bằng cách thêm props heightoffset. Chi tiết về cách sử dụng có thể tham khảo tại đây.

Bây giờ, tất cả các bài viết không được hiển thị từ đầu. Chỉ một số bài viết được hiển thị ban đầu tùy thuộc vào chế độ xem. Tuy nhiên, chúng ta không thể nhận ra sự thay đổi trừ khi kiểm tra DOM và xem các phần tử chuyển đổi giữa trạng thái loading và loaded.

Để tạo trải nghiệm hình ảnh tốt hơn cho người dùng, chúng ta sẽ kết hợp ảnh vào trong nội dung bài viết như sau:

const Post = ({ id, title, body }) => (
  <div className="post">
    <div className="post-img">
      <img src={`https://picsum.photos/id/${id}/200/200`} alt="...." />
    </div>
    <div className="post-body">
      <h4>{title}</h4>
      <p>{body}</p>
    </div>
  </div>
);

Lưu ý: URL của ảnh là https://picsum.photos/id/[image_id]/[width]/[height].

Mặc dù toàn bộ component đã được lazy loaded, hình ảnh vẫn được tải cùng với component và không mượt mà. Vì vậy, để cải thiện trải nghiệm hình ảnh cho người dùng, chúng ta sẽ sử dụng LazyLoad cho từng hình ảnh.

const Post = ({ id, title, body }) => (
  <div className="post">
    <LazyLoad once={true} placeholder={<img src={`https://picsum.pjoto/id/${id}/5/5`} alt="..." />} >
      <div className="post-img">
        <img src={`https://picsum.pjoto/id/${id}/200/200`} alt="...." />
      </div>
    </LazyLoad>
    <div className="post-body">
      <h4>{title}</h4>
      <p>{body}</p>
    </div>
  </div>
);

Bằng cách sử dụng LazyLoad, chúng ta có thể chạy danh sách bài viết khi cuộn cửa sổ và kiểm tra thay đổi giữa các component.

Nguồn: https://medium.freecodecamp.org/how-to-optimize-react-applications-with-lazy-loading-232183e02768

1