Suspense ба lazy loading
React апп нь default-аар бүх code-ийг нэг том файл болгон ачаалдаг. Апп томрох тусам энэ файл томрч, хэрэглэгч удаан хүлээх болно. Lazy loading нь code-ийг хэсгүүдэд хуваан, шаардлагатай үед л ачаалдаг. Suspense нь ачааллын үеийн UI-г удирддаг. Хоёулаа хамтдаа ажиллаж аппыг хурдасгана!
Lazy loading гэж юу вэ?
React.lazy() нь component-ийг динамикаар import хийдэг — тухайн component хэрэглэгдэх үед л сервераас татдаг:
import { lazy, Suspense } from "react";
// ✅ Lazy import — Dashboard хэрэглэгдэх үед л татагдана
const Dashboard = lazy(() => import("./Dashboard"));
const Settings = lazy(() => import("./Settings"));
const Profile = lazy(() => import("./Profile"));
// ❌ Энгийн import — бүгдийг нэгэн зэрэг татдаг
// import Dashboard from "./Dashboard";
// import Settings from "./Settings";
lazy() нь аргумент болгон функц авдаг — тэр функц нь import() буцаадаг. import() нь Promise учраас component татагдаж дуустал хүлээх хэрэгтэй болдог. Энд Suspense орж ирнэ.
Suspense ашиглах нь
Suspense нь lazy component татагдаж байх хугацаанд fallback UI харуулдаг:
import { lazy, Suspense, useState } from "react";
const Dashboard = lazy(() => import("./Dashboard"));
const Settings = lazy(() => import("./Settings"));
function LoadingSpinner() {
return (
<div style={{ textAlign: "center", padding: "40px" }}>
<p>Ачааллаж байна...</p>
</div>
);
}
export default function App() {
const [page, setPage] = useState("dashboard");
return (
<div>
<nav>
<button onClick={() => setPage("dashboard")}>Dashboard</button>
<button onClick={() => setPage("settings")}>Settings</button>
</nav>
{/* Suspense нь lazy component-уудаа боодог */}
<Suspense fallback={<LoadingSpinner />}>
{page === "dashboard" && <Dashboard />}
{page === "settings" && <Settings />}
</Suspense>
</div>
);
}
"Settings" товч анх дарахад тухайн component-н code татагдана — дуустал LoadingSpinner харагдана. Дараа дарахад cache-аас авдаг тул шууд харагдана.
React Router-тэй хослуулах
Route-уудыг lazy loading хийх нь хамгийн нийтлэг хэрэглээ:
import { lazy, Suspense } from "react";
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
// Бүх хуудсыг lazy import хийнэ
const Home = lazy(() => import("./pages/Home"));
const About = lazy(() => import("./pages/About"));
const Contact = lazy(() => import("./pages/Contact"));
const Blog = lazy(() => import("./pages/Blog"));
function PageLoader() {
return (
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "60vh",
fontSize: "18px",
color: "#6b7280",
}}
>
Хуудас ачааллаж байна...
</div>
);
}
export default function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">Нүүр</Link> |<Link to="/about">Бидний тухай</Link> |
<Link to="/contact">Холбоо барих</Link> |<Link to="/blog">Блог</Link>
</nav>
<Suspense fallback={<PageLoader />}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
<Route path="/blog" element={<Blog />} />
</Routes>
</Suspense>
</BrowserRouter>
);
}
Error Boundary-тэй хослуулах
Lazy loading хийх үед сүлжээний алдаа гарч болно — ErrorBoundary-тэй хослуулах нь зүйтэй:
import { lazy, Suspense } from "react";
import ErrorBoundary from "./ErrorBoundary";
const HeavyComponent = lazy(() => import("./HeavyComponent"));
export default function App() {
return (
<ErrorBoundary>
<Suspense
fallback={
<div style={{ padding: "20px", textAlign: "center" }}>
Ачааллаж байна...
</div>
}
>
<HeavyComponent />
</Suspense>
</ErrorBoundary>
);
}
Дараалал: ErrorBoundary → Suspense → lazy component. Ачааллын алдаа ErrorBoundary-д баригдана, ачааллын хүлээлт Suspense-д зохицуулагдана.
Хэр их ялгаа гарах вэ?
Том аппад lazy loading нь эхний ачааллын bundle хэмжээг 40–70% бууруулж чаддаг. Монголын хэрэглэгчид гар утсаараа удаан сүлжээгээр ордог учир энэ оновчлол онцгой чухал.
// Оновчлолын зөвлөмжүүд:
// ✅ Route-уудыг бүгдийг lazy болго
// ✅ Modal, drawer зэрэг том UI-г lazy болго
// ✅ Chart, editor зэрэг хүнд library-г lazy болго
// ❌ Жижиг, энгийн component-уудыг lazy болгох хэрэггүй
// ❌ Navbar, footer зэрэг эхнээс хэрэгтэй зүйлийг lazy болгох хэрэггүй
Дараагийн хичээлд:
Context-н дэвшилтэт хэрэглээ сурна — олон component дундаа state хуваалцах, Context-ийг reducer-тэй хослуулах, болон Context-н гүйцэтгэлийн нюансуудыг ойлгоно.