[{"data":1,"prerenderedAt":116},["ShallowReactive",2],{"qa-\u002Freact\u002Frendering-and-performance\u002Fcode-splitting-lazy":3},{"page":4,"siblings":96,"blog":113},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":20,"order":21,"path":22,"questions":23,"questionsCount":86,"related":87,"seo":88,"seoDescription":89,"stem":90,"subtopic":91,"topic":92,"topicSlug":93,"updated":94,"__hash__":95},"qa\u002Freact\u002Frendering-and-performance\u002Fcode-splitting-lazy.md","Code Splitting Lazy",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"medium","md","React","react",{"subtopicSlug":19},"code-splitting-lazy",true,4,"\u002Freact\u002Frendering-and-performance\u002Fcode-splitting-lazy",[24,29,33,37,41,45,49,53,57,61,65,70,74,78,82],{"id":25,"difficulty":26,"q":27,"a":28},"what-is-code-splitting","easy","What is code splitting and why does it matter in React?","**Code splitting** is the practice of breaking a JavaScript bundle into\nsmaller **chunks** that are loaded on demand instead of shipping everything\nin one large file. Without it, every user downloads your entire app upfront —\neven code for routes or features they never visit.\n\n```jsx\n\u002F\u002F Without splitting — one giant bundle (bad for initial load)\nimport HeavyDashboard from '.\u002FHeavyDashboard'\nimport ReportsPDF from '.\u002FReportsPDF'\n\n\u002F\u002F With splitting — each module loads only when needed\nconst HeavyDashboard = React.lazy(() => import('.\u002FHeavyDashboard'))\nconst ReportsPDF     = React.lazy(() => import('.\u002FReportsPDF'))\n```\n\nThe browser only fetches a chunk when the user triggers the code path that\nneeds it, dramatically reducing **Time to Interactive (TTI)** and\n**First Contentful Paint (FCP)** for the initial page. Tools like Webpack,\nVite, and Rollup split bundles automatically at every `import()` call.\n\nBenefits include faster initial load, smaller parse\u002Fcompile work on the main\nthread, and better cache granularity — a chunk for a rarely-changed library\nwon't bust the cache when your app logic changes.\n\n**Rule of thumb:** Split at route boundaries first — that alone cuts most\napps' initial bundle by 30–60 % without any layout complexity.\n",{"id":30,"difficulty":26,"q":31,"a":32},"react-lazy-dynamic-import","How do React.lazy and dynamic import() work together?","`React.lazy` accepts a **factory function** that returns a promise of a\nmodule with a **default export** that is a React component. Under the hood\nit wraps the dynamic `import()` expression, which is a native browser\u002Fbundler\nfeature that triggers on-demand chunk loading.\n\n```jsx\nimport React, { lazy, Suspense } from 'react'\n\n\u002F\u002F dynamic import() returns Promise\u003Cmodule>\n\u002F\u002F React.lazy unwraps the default export for you\nconst SettingsPage = lazy(() => import('.\u002Fpages\u002FSettingsPage'))\n\nfunction App() {\n  return (\n    \u003CSuspense fallback={\u003Cdiv>Loading settings…\u003C\u002Fdiv>}>\n      \u003CSettingsPage \u002F>\n    \u003C\u002FSuspense>\n  )\n}\n```\n\nWhen React first tries to render `\u003CSettingsPage \u002F>`, it kicks off the\n`import()` call. While the network request is in flight, React throws a\n**promise** (internally), and the nearest `\u003CSuspense>` boundary catches it\nand renders the `fallback`. Once the chunk resolves, React re-renders with\nthe real component.\n\nThe bundle tool (Webpack\u002FVite) sees the `import()` and automatically creates\na separate output chunk at build time.\n\n**Rule of thumb:** Always wrap the factory in an arrow function —\n`lazy(import('.\u002FFoo'))` executes immediately and defeats lazy loading.\n",{"id":34,"difficulty":26,"q":35,"a":36},"suspense-boundary-required","Why is a Suspense boundary required when using React.lazy?","`React.lazy` components are **asynchronous** — they need to fetch their\nchunk from the network before they can render. React's Suspense mechanism\nlets a component signal \"I'm not ready yet\" by throwing a promise. Without a\n`\u003CSuspense>` ancestor to catch that signal, React has nowhere to show a\nloading state and will throw an unhandled error instead.\n\n```jsx\n\u002F\u002F ❌ Missing Suspense — throws at runtime\nfunction App() {\n  return \u003CLazyChart \u002F>  \u002F\u002F React.lazy component with no Suspense ancestor\n}\n\n\u002F\u002F ✅ Suspense boundary catches the pending state\nfunction App() {\n  return (\n    \u003CSuspense fallback={\u003CSpinner \u002F>}>\n      \u003CLazyChart \u002F>\n    \u003C\u002FSuspense>\n  )\n}\n```\n\nYou can place the boundary anywhere above the lazy component in the tree.\nNesting multiple boundaries lets you control fallback granularity — a\ntop-level boundary shows a full-page spinner while inner boundaries show\nsmaller skeletons for individual sections.\n\n**Rule of thumb:** Put `\u003CSuspense>` as close to the lazy component as\nmakes sense for your UX — the tighter the boundary, the less UI is\nreplaced by the fallback.\n",{"id":38,"difficulty":14,"q":39,"a":40},"route-based-vs-component-based-splitting","What is the difference between route-based and component-based code splitting?","**Route-based splitting** loads an entire page component only when the user\nnavigates to that route. It is the highest-leverage split because each route\nis a natural isolation boundary and users rarely visit every route in one\nsession.\n\n**Component-based splitting** defers loading of a single heavy widget\n(e.g., a rich-text editor, chart library, or PDF viewer) until it is\nactually rendered on the page, regardless of route.\n\n```jsx\n\u002F\u002F Route-based — whole pages are lazy\nconst Home     = lazy(() => import('.\u002Fpages\u002FHome'))\nconst Dashboard = lazy(() => import('.\u002Fpages\u002FDashboard'))\n\n\u003CRoutes>\n  \u003CRoute path=\"\u002F\" element={\n    \u003CSuspense fallback={\u003CPageSpinner \u002F>}>\u003CHome \u002F>\u003C\u002FSuspense>\n  } \u002F>\n  \u003CRoute path=\"\u002Fdashboard\" element={\n    \u003CSuspense fallback={\u003CPageSpinner \u002F>}>\u003CDashboard \u002F>\u003C\u002FSuspense>\n  } \u002F>\n\u003C\u002FRoutes>\n\n\u002F\u002F Component-based — a heavy widget on one page\nconst RichEditor = lazy(() => import('.\u002FRichEditor'))\n\nfunction PostEditor({ showEditor }) {\n  return showEditor\n    ? \u003CSuspense fallback={\u003CEditorSkeleton \u002F>}>\u003CRichEditor \u002F>\u003C\u002FSuspense>\n    : \u003CSimplePlaceholder \u002F>\n}\n```\n\nRoute-based is always the first step; component-based is used when a single\nroute still bundles too much.\n\n**Rule of thumb:** Start with route-based splitting; add component-based\nsplitting only when bundle analysis identifies a specific heavy dependency\non a single route.\n",{"id":42,"difficulty":26,"q":43,"a":44},"suspense-fallback-prop","What should you pass to the Suspense fallback prop?","The `fallback` prop accepts **any renderable React node** — a string, JSX,\na spinner component, or a skeleton layout. It renders while the lazy chunk\nis loading and is replaced by the real content once the import resolves.\n\n```jsx\n\u002F\u002F Simple text fallback\n\u003CSuspense fallback=\"Loading…\">\n  \u003CLazyComponent \u002F>\n\u003C\u002FSuspense>\n\n\u002F\u002F Spinner component\n\u003CSuspense fallback={\u003CSpinner size=\"lg\" \u002F>}>\n  \u003CLazyComponent \u002F>\n\u003C\u002FSuspense>\n\n\u002F\u002F Skeleton that matches the real layout (best UX)\n\u003CSuspense fallback={\u003CDashboardSkeleton \u002F>}>\n  \u003CLazyDashboard \u002F>\n\u003C\u002FSuspense>\n\n\u002F\u002F null — renders nothing while loading (use with care)\n\u003CSuspense fallback={null}>\n  \u003CLazyModal \u002F>\n\u003C\u002FSuspense>\n```\n\nA skeleton that mirrors the real component's layout reduces **Cumulative\nLayout Shift (CLS)** because the page structure does not jump when the real\ncontent appears. Avoid heavy fallbacks that are themselves expensive to\nrender.\n\nThe fallback is only shown on the **first** load of a chunk; subsequent\nrenders use the cached module and skip the fallback entirely.\n\n**Rule of thumb:** Match the fallback's dimensions to the real component to\nprevent layout shift — even a simple fixed-height `\u003Cdiv>` is better than\nnothing.\n",{"id":46,"difficulty":14,"q":47,"a":48},"named-exports-with-lazy","React.lazy only works with default exports. How do you lazy-load a named export?","`React.lazy` requires the resolved module to have a **default export**. For\ncomponents exported as named exports, wrap the import in an intermediate\nre-export or inline re-map inside the factory function.\n\n```jsx\n\u002F\u002F components\u002FCharts.tsx — named export\nexport function BarChart() { \u002F* … *\u002F }\nexport function LineChart() { \u002F* … *\u002F }\n\n\u002F\u002F Option 1: inline re-map in the factory\nconst BarChart = lazy(() =>\n  import('.\u002Fcomponents\u002FCharts').then(mod => ({ default: mod.BarChart }))\n)\n\n\u002F\u002F Option 2: create a thin re-export file (Charts.BarChart.ts)\n\u002F\u002F Charts.BarChart.ts\nexport { BarChart as default } from '.\u002FCharts'\n\n\u002F\u002F then lazy-import that file normally\nconst BarChart = lazy(() => import('.\u002Fcomponents\u002FCharts.BarChart'))\n```\n\nBoth approaches satisfy React.lazy's contract of a promise that resolves to\n`{ default: Component }`. The inline `.then()` approach is convenient for\none-offs; a separate re-export file is cleaner when you lazy-load the same\nnamed export in multiple places.\n\n**Rule of thumb:** Prefer Option 1 for a single use case and Option 2 when\nthe same named export is lazy-loaded in more than two places — it avoids\nrepetitive `.then()` boilerplate.\n",{"id":50,"difficulty":14,"q":51,"a":52},"error-boundaries-with-lazy","How should you handle errors when a lazy component fails to load?","If the network request for a lazy chunk fails (e.g., 404, offline), the\nthrown promise rejects and React propagates an **error** up the tree.\nA `\u003CSuspense>` boundary does not catch errors — you need a separate\n**Error Boundary** component wrapping the lazy component.\n\n```jsx\nimport { Component } from 'react'\n\nclass ChunkErrorBoundary extends Component {\n  state = { hasError: false }\n\n  static getDerivedStateFromError() {\n    return { hasError: true }\n  }\n\n  render() {\n    if (this.state.hasError) {\n      return (\n        \u003Cbutton onClick={() => this.setState({ hasError: false })}>\n          Retry\n        \u003C\u002Fbutton>\n      )\n    }\n    return this.props.children\n  }\n}\n\n\u002F\u002F Wrap lazy component with both boundaries\n\u003CChunkErrorBoundary>\n  \u003CSuspense fallback={\u003CSpinner \u002F>}>\n    \u003CLazySettings \u002F>\n  \u003C\u002FSuspense>\n\u003C\u002FChunkErrorBoundary>\n```\n\nThe error boundary must sit **outside** `\u003CSuspense>` so it can catch chunk\nfetch errors after Suspense has already caught the pending promise. Libraries\nlike `react-error-boundary` provide a hook-friendly API for this pattern.\n\n**Rule of thumb:** Always pair `React.lazy` with an error boundary in\nproduction — chunk load failures are real and users deserve a recovery path,\nnot a blank screen.\n",{"id":54,"difficulty":14,"q":55,"a":56},"preloading-lazy-components","How can you preload a lazy component before the user navigates to it?","Because `React.lazy` wraps a factory function, you can **trigger the\nimport manually** before React needs to render the component. The browser\nfetches and caches the chunk, so by the time the component mounts, the\nmodule is already available and the Suspense fallback is skipped.\n\n```jsx\nconst LazyDashboard = lazy(() => import('.\u002FDashboard'))\n\n\u002F\u002F Preload on hover — user shows intent before clicking\nfunction NavLink() {\n  const preload = () => import('.\u002FDashboard')  \u002F\u002F same import() as lazy\n  return (\n    \u003Ca\n      href=\"\u002Fdashboard\"\n      onMouseEnter={preload}   \u002F\u002F starts fetch on hover\n      onFocus={preload}        \u002F\u002F keyboard nav support\n    >\n      Dashboard\n    \u003C\u002Fa>\n  )\n}\n\n\u002F\u002F Or preload after idle time with requestIdleCallback\nif (typeof requestIdleCallback !== 'undefined') {\n  requestIdleCallback(() => import('.\u002FDashboard'))\n}\n```\n\nCall the same dynamic `import()` path used inside `lazy()` — the bundler\nand browser cache the result by URL, so the second call (from React.lazy)\nis instant.\n\n**Rule of thumb:** Preload on `mouseenter` or `focus` for navigation links —\nyou get a ~100–300 ms head start for free, and most users never notice the\nchunk was loaded proactively.\n",{"id":58,"difficulty":14,"q":59,"a":60},"magic-comments-chunk-naming","How do you control the output chunk name for a lazy import?","Webpack and Vite both support **magic comments** inside `import()` to set\nthe output filename and other chunk behavior. The most common is\n`\u002F* webpackChunkName: \"…\" *\u002F` (Webpack) or `\u002F* @vite-ignore *\u002F` (Vite, for\nsuppressing warnings).\n\n```jsx\n\u002F\u002F Webpack — names the output chunk \"dashboard~chunk.js\"\nconst Dashboard = lazy(\n  () => import(\u002F* webpackChunkName: \"dashboard\" *\u002F '.\u002Fpages\u002FDashboard')\n)\n\n\u002F\u002F Webpack prefetch hint — browser fetches in idle time after initial load\nconst Reports = lazy(\n  () => import(\n    \u002F* webpackChunkName: \"reports\" *\u002F\n    \u002F* webpackPrefetch: true *\u002F\n    '.\u002Fpages\u002FReports'\n  )\n)\n\n\u002F\u002F Webpack preload hint — fetches in parallel with parent chunk\nconst HeroChart = lazy(\n  () => import(\n    \u002F* webpackChunkName: \"hero-chart\" *\u002F\n    \u002F* webpackPreload: true *\u002F\n    '.\u002Fcomponents\u002FHeroChart'\n  )\n)\n```\n\nNamed chunks are easier to identify in bundle reports and give cache-friendly\nfilenames. `webpackPrefetch` emits a `\u003Clink rel=\"prefetch\">` tag;\n`webpackPreload` emits `\u003Clink rel=\"preload\">` — use preload sparingly as it\ncompetes with critical resources.\n\n**Rule of thumb:** Name every lazy chunk — anonymous hashes like `3.js`\nare useless in production error logs and bundle analysis tools.\n",{"id":62,"difficulty":26,"q":63,"a":64},"impact-on-initial-load-time","How does code splitting reduce initial load time?","Without splitting, the browser must **download, parse, and compile** the\nentire JavaScript bundle before any interactive content appears. Code\nsplitting reduces all three phases for the initial visit by shipping only\nthe code needed for the landing route.\n\n```\nBefore splitting:\n  Bundle: 1.2 MB  →  parse: 800 ms  →  TTI: 3.2 s\n\nAfter route-based splitting:\n  Initial chunk: 280 KB  →  parse: 180 ms  →  TTI: 1.1 s\n  \u002Fdashboard chunk: 420 KB  ← loaded only when user navigates there\n  \u002Freports chunk:   500 KB  ← loaded only when user navigates there\n```\n\n```jsx\n\u002F\u002F Each lazy() call becomes a separate network request only on demand\nconst Dashboard = lazy(() => import(\u002F* webpackChunkName: \"dashboard\" *\u002F '.\u002FDashboard'))\nconst Reports   = lazy(() => import(\u002F* webpackChunkName: \"reports\"   *\u002F '.\u002FReports'))\n\n\u002F\u002F First paint only fetches the initial chunk\n\u002F\u002F Dashboard and Reports chunks are fetched on navigation\n```\n\nThe savings compound with caching: once a user has visited `\u002Fdashboard`,\nthe chunk is cached and subsequent navigations are instant.\n\n**Rule of thumb:** Measure before and after with `npm run build -- --report`\nor Vite's `--reporter` flag — aim to keep your initial chunk under 200 KB\ngzipped.\n",{"id":66,"difficulty":67,"q":68,"a":69},"lazy-loading-in-ssr","hard","What are the limitations of React.lazy in a server-side rendering (SSR) environment?","`React.lazy` is **not supported in SSR** with React 17 and earlier — it only\nworks in the browser. On the server, calling a lazy component throws because\nthere is no Suspense-compatible server renderer to handle the dynamic import.\n\nReact 18's `renderToPipeableStream` and `renderToReadableStream` do support\nSuspense on the server, but `React.lazy` itself still requires the module to\nbe available synchronously during SSR unless you use a framework that handles\nit.\n\n```jsx\n\u002F\u002F For SSR, use framework-native lazy loading instead:\n\n\u002F\u002F Next.js — next\u002Fdynamic handles SSR by default\nimport dynamic from 'next\u002Fdynamic'\n\nconst HeavyChart = dynamic(() => import('.\u002FHeavyChart'), {\n  loading: () => \u003CChartSkeleton \u002F>,\n  ssr: false,   \u002F\u002F skip server render entirely for browser-only widgets\n})\n\n\u002F\u002F Remix — uses route-level splitting natively via its file-system router\n\u002F\u002F No extra config needed — every route file is a split point\n```\n\nFor framework-agnostic SSR, `@loadable\u002Fcomponent` is the standard solution —\nit serializes which chunks were used on the server and preloads them on the\nclient to avoid hydration mismatches.\n\n**Rule of thumb:** In SSR apps, reach for your framework's dynamic import\nhelper (Next.js `dynamic`, Remix routes, Nuxt `defineAsyncComponent`) rather\nthan bare `React.lazy`.\n",{"id":71,"difficulty":14,"q":72,"a":73},"multiple-lazy-one-suspense","Can multiple lazy components share a single Suspense boundary?","Yes. A single `\u003CSuspense>` boundary handles **all** lazy descendants — it\nshows the fallback until **every** lazy child in its subtree has resolved.\nThis is fine when you want a single loading state for a group of components\nthat logically appear together.\n\n```jsx\nconst Sidebar  = lazy(() => import('.\u002FSidebar'))\nconst MainFeed = lazy(() => import('.\u002FMainFeed'))\nconst Widgets  = lazy(() => import('.\u002FWidgets'))\n\n\u002F\u002F One boundary — fallback shows until ALL three chunks are ready\n\u003CSuspense fallback={\u003CPageSkeleton \u002F>}>\n  \u003CSidebar \u002F>\n  \u003CMainFeed \u002F>\n  \u003CWidgets \u002F>\n\u003C\u002FSuspense>\n\n\u002F\u002F Nested boundaries — each section shows its own fallback independently\n\u003CSuspense fallback={\u003CSidebarSkeleton \u002F>}>\n  \u003CSidebar \u002F>\n\u003C\u002FSuspense>\n\u003CSuspense fallback={\u003CFeedSkeleton \u002F>}>\n  \u003CMainFeed \u002F>\n  \u003CWidgets \u002F>   {\u002F* Widgets shares MainFeed's boundary *\u002F}\n\u003C\u002FSuspense>\n```\n\nMultiple lazy components under one boundary also means all their network\nrequests fire in **parallel** — React does not wait for one to finish before\nstarting the next.\n\n**Rule of thumb:** Share a single boundary when the components form one\nvisual unit; nest separate boundaries when different sections can\nindependently become interactive.\n",{"id":75,"difficulty":14,"q":76,"a":77},"react-lazy-limitations","What are the key limitations of React.lazy?","`React.lazy` is powerful but has several constraints worth knowing for\ninterviews:\n\n```jsx\n\u002F\u002F 1. Default exports only — named exports need re-mapping\nconst Foo = lazy(() => import('.\u002FFoo'))               \u002F\u002F ✅\nconst Bar = lazy(() => import('.\u002FBar').then(m => ({ default: m.Bar }))) \u002F\u002F ✅ workaround\n\n\u002F\u002F 2. Must be called at module level, not inside render\nfunction BadParent() {\n  \u002F\u002F ❌ Creates a new lazy reference every render — loses state and re-fetches\n  const Lazy = lazy(() => import('.\u002FChild'))\n  return \u003CLazy \u002F>\n}\n\n\u002F\u002F 3. No server-side rendering support (React 17 and earlier)\n\u002F\u002F Use next\u002Fdynamic or @loadable\u002Fcomponent in SSR apps\n\n\u002F\u002F 4. Requires a Suspense boundary — no built-in fallback\n\u002F\u002F 5. No built-in error handling — needs an Error Boundary\n```\n\nAdditional limitations: you cannot lazy-load hooks or context providers\n(only renderable components), and `React.lazy` does not support passing\noptions like timeout or retry logic — those require custom wrappers.\n\n**Rule of thumb:** Declare `lazy()` at module scope, not inside component\nbodies — creating a new lazy reference on every render causes the chunk to\nre-fetch and the component to remount, destroying local state.\n",{"id":79,"difficulty":67,"q":80,"a":81},"splitting-third-party-libraries","How do you code-split heavy third-party libraries in React?","Third-party packages imported at the top of a file are bundled into\nwhichever chunk imports them. To split them out, import them **dynamically**\ninside the component or effect that needs them instead of at the top level.\n\n```jsx\n\u002F\u002F ❌ Static import — lands in the initial bundle even if rarely used\nimport { Chart } from 'chart.js'\n\n\u002F\u002F ✅ Dynamic import — chunk created only for routes that use Chart\nfunction SalesChart({ data }) {\n  const [ChartLib, setChartLib] = useState(null)\n\n  useEffect(() => {\n    import('chart.js').then(mod => setChartLib(() => mod.Chart))\n  }, [])\n\n  if (!ChartLib) return \u003CChartSkeleton \u002F>\n  return \u003CChartLib data={data} \u002F>\n}\n\n\u002F\u002F ✅ Better: wrap with React.lazy for Suspense support\nconst PDFViewer = lazy(() =>\n  import('react-pdf').then(mod => ({ default: mod.Document }))\n)\n\n\u002F\u002F ✅ Webpack vendor chunk — group stable libs into a long-cached chunk\n\u002F\u002F In webpack.config.js:\n\u002F\u002F optimization.splitChunks.cacheGroups.vendors: { test: \u002Fnode_modules\u002F }\n```\n\nFor libraries like Moment.js or lodash, also check if tree-shaking and\nlighter alternatives (date-fns, lodash-es) eliminate the need to split at all.\n\n**Rule of thumb:** Check `bundle-analyzer` output first — if a library\naccounts for over 50 KB gzipped in your initial bundle and is not needed on\nthe landing page, it is a prime split candidate.\n",{"id":83,"difficulty":14,"q":84,"a":85},"measuring-bundle-size-impact","How do you measure the impact of code splitting on bundle size?","Three complementary tools cover the full picture: the bundler's built-in\nstats, a visual analyzer, and a real-browser network trace.\n\n```bash\n# Webpack — generate stats.json then open in webpack-bundle-analyzer\nnpx webpack --profile --json > stats.json\nnpx webpack-bundle-analyzer stats.json\n\n# Vite — built-in rollup visualizer plugin\n# vite.config.ts\nimport { visualizer } from 'rollup-plugin-visualizer'\nplugins: [react(), visualizer({ open: true, gzipSize: true })]\n\n# CRA — source-map-explorer\nnpm run build\nnpx source-map-explorer 'build\u002Fstatic\u002Fjs\u002F*.js'\n```\n\n```jsx\n\u002F\u002F After splitting, compare chunk sizes in the build output:\n\u002F\u002F dist\u002Fassets\u002Findex-3f2a.js      → 87 KB  (initial)\n\u002F\u002F dist\u002Fassets\u002Fdashboard-9c1b.js  → 142 KB (on demand)\n\u002F\u002F dist\u002Fassets\u002Freports-4d7e.js    → 198 KB (on demand)\n\u002F\u002F Initial savings: 340 KB removed from first load\n```\n\nAlso check the **Network tab** in DevTools with throttling enabled — confirm\nthat on-demand chunks appear as separate requests timed to navigation, not\non initial page load.\n\n**Rule of thumb:** Run bundle analysis in CI and set a size budget (e.g.,\n`bundlesize` or Vite's `build.chunkSizeWarningLimit`) — that way regressions\nare caught before they reach production.\n",15,null,{"description":11},"React code splitting and lazy loading interview questions — React.lazy, dynamic imports, Suspense boundaries, route-based splitting, bundle optimization, and prefetching strategies.","react\u002Frendering-and-performance\u002Fcode-splitting-lazy","Code Splitting and Lazy Loading","Rendering and Performance","rendering-and-performance","2026-06-24","wV_XCzM0ToidDuok6CjeIfLx02W6hMUv62fftXfy7Sc",[97,101,104,108,109],{"subtopic":98,"path":99,"order":100},"Virtual DOM and Reconciliation","\u002Freact\u002Frendering-and-performance\u002Fvirtual-dom-reconciliation",1,{"subtopic":102,"path":103,"order":12},"React.memo","\u002Freact\u002Frendering-and-performance\u002Freact-memo",{"subtopic":105,"path":106,"order":107},"useMemo and useCallback Patterns","\u002Freact\u002Frendering-and-performance\u002Fusememo-usecallback-patterns",3,{"subtopic":91,"path":22,"order":21},{"subtopic":110,"path":111,"order":112},"Suspense and Concurrent Rendering","\u002Freact\u002Frendering-and-performance\u002Fsuspense-concurrent",5,{"path":114,"title":115},"\u002Fblog\u002Freact-code-splitting-lazy-guide","React Code Splitting and Lazy Loading — A Complete Guide",1782244101015]