InterviewHubPRO
Section Overview
Q520

Question 520 of 521

Part 8: Modern JavaScript APIs, WeakRef, Proxy & Performance (464 - 521)

100%
JavaScript Internals (521 Qs)•Part 8: Modern JavaScript APIs, WeakRef, Proxy & Performance (464 - 521)

How do you implement a lazy loading pattern for modules?

Lazy loading defers module loading until they're actually needed, reducing initial bundle size and improving load time.

Dynamic import (ES modules):

javascript
 // Traditional import - loaded immediately
 import { heavyFunction } from './heavy-module.js';

 // Dynamic import - loaded on demand
 async function loadModule() {
   const module = await import('./heavy-module.js');
   module.heavyFunction();
 }

 // Or with destructuring
 const { heavyFunction } = await import('./heavy-module.js');

Route-based lazy loading (React):

javascript
 import { lazy, Suspense } from 'react';

 const Dashboard = lazy(() => import('./Dashboard'));
 const Profile = lazy(() => import('./Profile'));

 function App() {
   return (
     <Router>
       <Suspense fallback={<div>Loading...</div>}>
         <Routes>
           <Route path="/dashboard" element={<Dashboard />} />
           <Route path="/profile" element={<Profile />} />
         </Routes>
       </Suspense>
     </Router>
   );
 }

Feature-based lazy loading:

javascript
 class FeatureLoader {
   constructor() {
     this.features = new Map();
   }

   async loadFeature(name) {
     if (this.features.has(name)) {
       return this.features.get(name);
     }

     const module = await import(`./features/${name}.js`);
     this.features.set(name, module);
     return module;
   }
 }

 const loader = new FeatureLoader();

 // Load feature only when needed
 button.addEventListener('click', async () => {
   const feature = await loader.loadFeature('advanced-charts');
   feature.render(data);
 });

Intersection Observer lazy loading:

javascript
 const observer = new IntersectionObserver((entries) => {
   entries.forEach(async (entry) => {
     if (entry.isIntersecting) {
       const moduleName = entry.target.dataset.module;
       const module = await import(`./modules/${moduleName}.js`);
       module.init(entry.target);
       observer.unobserve(entry.target);
     }
   });
 });

 // Observe elements
 document.querySelectorAll('[data-module]').forEach(el => {
   observer.observe(el);
 });

Conditional lazy loading:

javascript
 async function loadEditor() {
   if (window.innerWidth > 768) {
     // Load full editor for desktop
     const { FullEditor } = await import('./FullEditor.js');
     return new FullEditor();
   } else {
     // Load mobile editor
     const { MobileEditor } = await import('./MobileEditor.js');
     return new MobileEditor();
   }
 }

Prefetching for better UX:

javascript
 // Prefetch on hover
 link.addEventListener('mouseenter', () => {
   import(/* webpackPrefetch: true */ './heavy-module.js');
 });

 // Preload critical modules after initial load
 window.addEventListener('load', () => {
   setTimeout(() => {
     import(/* webpackPreload: true */ './important-module.js');
   }, 1000);
 });

Module caching:

javascript
 class ModuleCache {
   constructor() {
     this.cache = new Map();
     this.pending = new Map();
   }

   async load(path) {
     // Return cached module
     if (this.cache.has(path)) {
       return this.cache.get(path);
     }

     // Return pending promise
     if (this.pending.has(path)) {
       return this.pending.get(path);
     }

     // Load module
     const promise = import(path).then(module => {
       this.cache.set(path, module);
       this.pending.delete(path);
       return module;
     });

     this.pending.set(path, promise);
     return promise;
   }
 }

 const moduleCache = new ModuleCache();
 const module = await moduleCache.load('./module.js');

Webpack code splitting:

javascript
 // Magic comments for webpack
 const module = await import(
   /* webpackChunkName: "my-chunk" */
   /* webpackMode: "lazy" */
   './module.js'
 );