Chunking là một khái niệm được sử dụng trong rất nhiều các lĩnh vực khác nhau trong đời sống.

"Chunking is a method of presenting information which splits concepts into small pieces or "chunks" of information to make reading and understanding faster and easier" - theo Wikipedia.

Hiểu đơn giản, chunking là một kỹ thuật phân tách 1 nội dung lớn thành nhiều phần nhỏ hơn giúp cho việc tiếp cận, học hỏi nhanh và dễ dàng hơn. Và tất nhiên chunking hay code splitting được sử dụng rất triệt để trong development - đặc biệt là với Reactjs.

Với content chunking làm nhiệm vụ chia nhỏ nội dung để dễ tiếp cận và dễ đọc thì trong React development, chunking sẽ chia nhỏ code của bạn nhằm giúp tối ưu performance, tránh việc sau khi build ra các file JavaScript quá nặng.

A single giant bundle vs multiple smaller bundles

Trong bài viết này, chúng ta sẽ cùng tìm hiểu về thư viện React Loadable để xem cách thư viện này chunking code Reactjs ra sao. Ngoài ra, bạn cũng có thể xem thêm bài viết Tách code với React và Webpack rồi thử so sánh với cách sử dụng React Loadable xem sao nhé.

1. Component-bases chunking.

Tình huống đặt ra ở đây chúng ta sẽ có component RandomText sẽ render ra 1 thẻ div chứa text chứa 1 đoạn loremipsum siêu to khổng lồ đâu đó khoảng 500 đoạn văn. Vào đây để copy cho lẹ nhé: https://loremipsum.io/generator/?n=500&t=p.

Tiếp theo, ta sẽ muốn import component RandomText vào component App để render ra khi click vào 1 button.

function App() {
  const [isRandomText, setIsRandomText] = useState(false);
  const toggleRandomText = () => {
    setIsRandomText(!isRandomText);
  };
  return (
    <div className="App">
      <button onClick={toggleRandomText}>Toggle Random Text</button>
      {isRandomText ? <LoadableRandomText /> : ""}
    </div>
  );
}

Không có vấn đề gì với đoạn code trên phải không nào, thử chạy lệnh yarn build xem sao nhé.

Đây là kích thước file sau khi build ra, hơn 40kb text là cũng không hề ít phải không nào. Trong thực tế, ứng dụng của bạn khi build ra thì kích thước file sẽ còn khổng lồ hơn rất nhiều.

Vậy thì React Loadable có tác dụng như thế nào vậy, cùng xem nhé.

Để sử dụng React Loadable thì phải cài trước, lệnh cài như sau:

Nếu bạn dùng yarn:

yarn add react-loadable

Còn không thì:

npm i --save react-loadable

Import vào project và refactor lại code 1 chút:

import Loadable from "react-loadable";

const LoadableRandomText = Loadable({
  loader() {
    return import("./RandomText");
  },
  loading() {
    return <div>Loading...</div>;
  }
});

function App() {
  const [isRandomText, setIsRandomText] = useState(false);
  const toggleRandomText = () => {
    setIsRandomText(!isRandomText);
  };
  return (
    <div className="App">
      <button onClick={toggleRandomText}>Toggle Random Text</button>
      {isRandomText ? <LoadableRandomText /> : ""}
    </div>
  );
}

 

Hiểu đơn giản, Loadable sẽ tạo ra 1 component mới và trả về 1 trong 2 component khác tuỳ theo trạng thái:

  • loader được chạy khi đã load xong source của component RandomText và trả về component này bằng việc sử dụng import() để dynamic import nó. Tham khảo thêm về import() tại đây.
  • loading sẽ chạy trong quá trình load source của loader.

Ok vậy là xong phần config cho loadable, thử build lại xem sao:

Wow wow wow, nhìn vào kích thước của file main...chunk.js. Thật ra cũng không có gì ngạc nhiên lắm đâu, chỉ là React Loadable đã loại bỏ component RandomText của bạn ra khỏi source thôi vì ban đầu RandomText chưa hề xuất hiện trong ứng dụng này. Nó chỉ được gọi ra khi ta click vào button mà thôi. Để thấy rõ hơn sự thay đổi, cùng nhìn vào devtools nhé:

Khi chưa render RandomText:

Sau khi render RandomText:

2. Route-bases chunking.

Routes trong React là một khái niệm đã quen thuộc. Về bản chất, các route chỉ đơn giản là các component được gọi ra khi đường dẫn của url trùng với route đó.

Route vs. component centric code splitting

Vì vậy, ta hoàn toàn có thể chunking code với với các route.

Giả sử ta sẽ có 2 component tương ứng với 2 route là RandomText và RandomImage. Lại refactor code nào:

import { Switch, Route, Link } from "react-router-dom";

const Loading = () => <div>Loading...</div>;

const LoadableRandomText = Loadable({
  loader() {
    return import("./RandomText");
  },
  loading: Loading
});

const LoadableRandomImage = Loadable({
  loader() {
    return import("./RandomImage");
  },
  loading: Loading
});

 

Tách Loading thành 1 component riêng để tái sử dụng và import thêm mấy thứ của react-router.

function App() {
  return (
    <div className="App">
      <div className="nav">
        <Link to="/random-text">Random Text</Link>
        <Link to="/random-image">Random Image</Link>
      </div>
      <Switch>
        <Route path="/random-text" component={LoadableRandomText} />
        <Route path="/random-image" component={LoadableRandomImage} />
      </Switch>
    </div>
  );
}

Khai báo route cơ bản.

Xong! Bật dev tools lên và xem kết quả nhé.

Tham khảo thêm về React Loadable tại đây.

Happy coding!