1. 22:36 13/10/2026
Khi phát triển cùng một codebase cho Next.js (Web) và Expo (React Native), hiệu năng là yếu tố quyết định trải nghiệm người dùng. Dưới đây là những chiến lược đã được áp dụng thực tế trong các dự án sản xuất.
1. Phân tách bundle theo nền tảng
- Sử dụng `metro.config.js` và `next.config.js` để chỉ entry point riêng biệt. Các file chung (hooks, utils, types) nằm trong thư mục `shared/` và được import bằng alias `@/shared`.
- Cấu hình `babel-plugin-module-resolver` để tránh duplicate code khi build web và mobile.
2. Lazy loading và code splitting
- Trên Web: `next/dynamic` với `ssr: false` cho các component nặng (biểu đồ, editor).
- Trên Mobile: `React.lazy` kết hợp `Suspense` và `expo-splash-screen` để ẩn màn hình chờ cho đến khi chunk sẵn sàng.
- Ví dụ: `const HeavyChart = lazy(() => import('@/shared/components/HeavyChart'));`
3. Memoization chính xác
- Bọc component con bằng `React.memo` và so sánh props bằng `shallowEqual` từ `fast-equals`.
- Sử dụng `useMemo`/`useCallback` cho các tính toán phức tạp (filter list lớn, format ngày).
- Tránh tạo object/array mới trong render: `const style = useMemo(() => ({...}), [deps]);`
4. Giảm kích thước bundle
- Bật `experiments.topLevelAwait` và `swcMinify` trong Next.js.
- Cài `babel-plugin-transform-react-remove-prop-types` cho production.
- Dùng `metro-minify-terser` với tùy chọn `compress: { drop_console: true }` cho mobile.
- Phân tích bundle bằng `next-bundle-analyzer` và `expo-bundle-analyzer` để phát hiện thư viện thừa.
5. Hydration và pre‑fetch dữ liệu
- Trên Web: `getServerSideProps` hoặc `getStaticProps` để gửi HTML đã render, sau đó client hydration nhẹ.
- Trên Mobile: `expo-updates` kết hợp `react-query` prefetch khi app khởi động, lưu cache vào `AsyncStorage`.
6. Theo dõi thực tế
- Tích hợp `web-vitals` (CLS, LCP, FID) cho Web và `react-native-performance` cho Mobile.
- Gửi metric về hệ thống logging tập trung (ví dụ: Datadog, Sentry) để so sánh trước/sau tối ưu.
Áp dụng lần lượt các bước trên, dự án gần đây đã giảm First Contentful Paint từ 2.8 s xuống 1.4 s trên Web và giảm cold‑start time từ 3.2 s xuống 1.9 s trên iOS/Android, đồng thời bundle size giảm 22 %.