Free tutorials & notes in Hindi & English · Clean code examples 🧰 मुफ़्त PDF और फ़ोटो टूल्स →
🛡️ Days 23–27 – Professional JavaScript  ·  दिन 25

दिन 25: DOM Performance और Patterns

⏱ 95 min📶 Pro🎯 100% self-study
दिन 25 / 30

✅ आज आप सीखेंगे

  • Browser कैसे render करता है: JS → style → layout → paint
  • Layout thrashing और reads/writes batch करना
  • requestAnimationFrame, passive listeners, code lazy-load
  • performance.now, DevTools Performance और Lighthouse से मापना
  • Patterns: module, pub/sub (observer) और छोटा store

🏢 असली दुनिया में

मालिक के ₹8,000 वाले phone पर product page उपयोग लायक होने में 4 सेकंड लेता है और scrolling अटकती है। Google इसे मापता है (INP, LCP) और धीमी sites को नीचे रखता है; customers चले जाते हैं। ज़्यादातर JavaScript धीमापन कुछ ग़लतियों से आता है – आज आप मापकर उन्हें ढूँढना और आज़माए patterns से ठीक करना सीखेंगे।

Browser एक frame कैसे बनाता है

JavaScript चलता हैStyle – कौन सी CSS लागूLayout – sizes और positions (महँगा)Paint – pixelsComposite – screen पर layers
60 fps पर हर frame को लगभग 16 ms
🧠 50 ms नियम

50 ms से लंबा कोई भी JavaScript task taps और scrolling रोकता है (“long task”)। Event handlers छोटे रखें, भारी काम मुख्य रास्ते से हटाएँ (chunks, Web Workers) और DOM batches में update करें।

Layout thrashing: पहले पढ़ो, फिर लिखो

HTML + JavaScript
<button id="slow">Slow: read/write mixed</button> <button id="fast">Fast: read all, then write all</button>
<p id="t"></p>
<div id="boxes"></div>

<script>
const boxes = document.querySelector('#boxes');
for (let i = 0; i < 400; i++) {
  const d = document.createElement('div');
  d.style.cssText = 'height:4px;margin:1px 0;background:#fde68a;width:50%';
  boxes.append(d);
}
const items = [...boxes.children];

document.querySelector('#slow').addEventListener('click', () => {
  const t0 = performance.now();
  for (const el of items) {
    const w = el.offsetWidth;          // READ (forces layout)
    el.style.width = (w % 300) + 20 + 'px';   // WRITE (invalidates layout) → next read recalculates
  }
  document.querySelector('#t').textContent = `Mixed: ${(performance.now() - t0).toFixed(1)} ms`;
});
document.querySelector('#fast').addEventListener('click', () => {
  const t0 = performance.now();
  const widths = items.map(el => el.offsetWidth);                  // all READS first
  items.forEach((el, i) => { el.style.width = (widths[i] % 300) + 20 + 'px'; });   // then all WRITES
  document.querySelector('#t').textContent = `Batched: ${(performance.now() - t0).toFixed(1)} ms`;
});
</script>
▶  Compare the timings – batching avoids hundreds of forced layouts
Write के बाद पढ़ने पर layout triggerबेहतर
offsetWidth/Height, clientWidth, scrollTopएक बार पढ़कर value cache करें
getBoundingClientRect()IntersectionObserver / ResizeObserver
getComputedStyle()Styles पढ़ने की जगह classes toggle
Loop में width/top बदलनाtransform और opacity (CSS Day 13)

requestAnimationFrame और passive listeners

HTML + JavaScript
<div id="bar" style="height:6px;background:#ca8a04;width:0;position:sticky;top:0;transition:none"></div>
<div id="page" style="height:240px;overflow:auto;border:1px solid #e5e7eb;border-radius:8px;padding:10px">
  <p>Scroll this article – the reading-progress bar above updates once per frame.</p>
  <div style="height:900px;background:linear-gradient(#fff,#fef3c7)"></div>
</div>

<script>
const page = document.querySelector('#page');
const bar = document.querySelector('#bar');
let ticking = false;

page.addEventListener('scroll', () => {
  if (ticking) return;                     // at most one update per frame
  ticking = true;
  requestAnimationFrame(() => {
    const max = page.scrollHeight - page.clientHeight;
    bar.style.width = (page.scrollTop / max * 100) + '%';
    ticking = false;
  });
}, { passive: true });                     // promise not to call preventDefault → smoother scrolling
</script>
▶  A reading-progress bar: scroll + rAF + passive listener

Long tasks: काम को टुकड़ों में बाँटें

JavaScript
// Processing 50,000 order rows in one go blocks the page; yield between chunks
const orders = Array.from({ length: 50000 }, (_, i) => ({ id: i, total: (i * 37) % 2500 }));
const yieldToBrowser = () => new Promise(r => setTimeout(r, 0));   // browsers also have scheduler.yield()

async function totalInChunks(rows, size = 5000) {
  let sum = 0, chunks = 0;
  for (let i = 0; i < rows.length; i += size) {
    for (const row of rows.slice(i, i + size)) sum += row.total;
    chunks++;
    await yieldToBrowser();                  // let clicks and paints happen between chunks
  }
  return { sum, chunks };
}
const t0 = performance.now();
totalInChunks(orders).then(r => console.log(`₹${r.sum.toLocaleString('en-IN')} in ${r.chunks} chunks, ${Math.round(performance.now() - t0)} ms total`));
₹6,24,75,000 in 10 chunks, 40 ms total
💡 भारी code सिर्फ़ ज़रूरत पर load

सिर्फ़ admin report page पर लगने वाली chart library home page धीमा न करे: btn.onclick = async () => { const { drawChart } = await import("./chart.js"); drawChart(); }। Vite इसे अपने-आप अलग file में बाँटता है।

Optimise करने से पहले मापें

Toolदिखाता है
performance.now() / console.timeएक function कितना समय लेता है
DevTools → Performance → RecordLong tasks (लाल कोने), हर frame में layout, paint
LighthouseLCP, INP, CLS, total blocking time + सुझाव
DevTools → Coverageबेकार JS और CSS bytes
Network tab (Slow 4G throttling)असली Indian mobile user का अनुभव

बड़े apps को व्यवस्थित रखने वाले patterns

JavaScript
// Pub/Sub (observer): parts of the app talk without knowing each other
function createEventBus() {
  const listeners = {};
  return {
    on(event, fn) { (listeners[event] ||= []).push(fn); return () => this.off(event, fn); },
    off(event, fn) { listeners[event] = (listeners[event] || []).filter(f => f !== fn); },
    emit(event, data) { (listeners[event] || []).forEach(fn => fn(data)); },
  };
}

// A tiny store: one state object, updates through actions, subscribers re-render
function createStore(initial, bus) {
  let state = initial;
  return {
    get: () => state,
    update(change) { state = { ...state, ...change(state) }; bus.emit('change', state); },
  };
}

const bus = createEventBus();
const store = createStore({ cart: [], total: 0 }, bus);
const stopBadge = bus.on('change', s => console.log(`🛒 badge: ${s.cart.length} item(s)`));
bus.on('change', s => console.log(`💰 summary: ₹${s.total}`));

store.update(s => ({ cart: [...s.cart, 'Kaju'], total: s.total + 900 }));
stopBadge();                                     // unsubscribe one listener
store.update(s => ({ cart: [...s.cart, 'Ladoo'], total: s.total + 500 }));
🛒 badge: 1 item(s) 💰 summary: ₹900 💰 summary: ₹1400
Patternक्या हल करता हैकहाँ दिखता है
ModulePrivate details + छोटा public APIES modules, हर library
Observer / pub-subएक बदलाव पर कई हिस्से प्रतिक्रिया देंaddEventListener, Redux subscribe, Vue reactivity
Store (single state)एक सत्य स्रोतRedux, Zustand, हमारा to-do app
Delegationकई elements के लिए एक listenerLists, tables, menus
FactoryConfigured objects बनानाcreateStore, createCounter

🏅 आज के Job Skills

✔ Rendering pipeline और long tasks समझाना✔ Layout thrashing से बचना और rAF / passive listeners✔ लंबा काम बाँटना और भारी code lazy-load✔ DevTools से मापना और pub/sub व stores से code व्यवस्थित

Practice tasks

🏋️ Practice – ख़ुद करें

Task 1: 300px scroll के बाद दिखने वाला “back to top” button बनाएँ – scroll listener की जगह sentinel पर IntersectionObserver।
Task 2: Item जुड़ने पर दो स्वतंत्र modules से cart badge और toast update करने के लिए event bus लें।
Task 3: 50 tasks जोड़ते समय अपने Day 14 to-do app का Performance profile record करें और सबसे लंबा task ढूँढें।

Quick quiz

🧠 Quick Quiz – ख़ुद को जाँचें

1. Layout thrashing किससे होता है?
जबरन synchronous layout।
2. Scroll पर visual updates किससे schedule करें?
हर frame एक बार।
3. Scroll listener पर { passive: true }…
Browser तुरंत scroll कर सकता है।
4. … ms से लंबा task “long task” है:
Interaction रोकता है।
5. Pub/sub modules को…
ढीला जुड़ाव।

Interview corner

💼 Interview Corner

धीमा page कैसे तेज़ करेंगे?

पहले मापें (Lighthouse, Performance panel)। फिर JavaScript घटाएँ और defer करें (code-split, lazy-load), long tasks से बचें (काम बाँटें, Web Workers), DOM reads/writes batch करें, rAF और passive listeners, images/fonts optimise, API data cache, और Core Web Vitals दोबारा मापें।

Reflow (layout) क्या है और अनावश्यक reflows से कैसे बचें?

Reflow browser का element geometry दोबारा गिनना है। यह DOM/style बदलाव के बाद होता है और write के बाद layout properties पढ़ने पर जबरन synchronous होता है। Writes से पहले reads batch करके, कई inline styles की जगह classes बदलकर, transform/opacity animate करके और positions polling की जगह observers लेकर बचें।

सारांश

  • Frames के पास ~16 ms; 50 ms से लंबे tasks interaction रोकते हैं।
  • Writes से पहले DOM reads batch; rAF और passive listeners।
  • लंबा काम बाँटें, भारी modules lazy-load, DevTools से मापें।
  • Pub/sub और एक store बढ़ते apps व्यवस्थित रखते हैं।
➡️ आगे

Day 26: security और clean code – XSS, सुरक्षित rendering, secrets, CSP और ऐसा code जिसके लिए team आपको धन्यवाद दे।

अक्सर पूछे जाने वाले प्रश्न (FAQ)

Web Workers क्या हैं?
Background threads जो page रोके बिना JavaScript चलाते हैं – बड़ी CSV reports parse करने जैसी भारी गणना के लिए आदर्श। ये DOM सीधे नहीं छूते और postMessage से बात करते हैं।
क्या vanilla JS React से तेज़ है?
अच्छा लिखा vanilla code बहुत तेज़ हो सकता है; frameworks थोड़ी लागत जोड़ते हैं पर ढाँचा और कुशल updates देते हैं। ज़्यादातर धीमापन app code से आता है, framework के चुनाव से नहीं।
← JavaScript (30 Days)
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

अगला topicदिन 26: Security और Clean Code आपकी प्रगति: 25 / 30 (83%) · Lesson 26 / 30 आगे बढ़ें →

यह lesson कैसा लगा?

आपकी राय से हम content और बेहतर बनाते हैं।

अपना review और सुझाव लिखें (वैकल्पिक)

Review approve होने के बाद आपका नाम और शहर इसके साथ public दिख सकते हैं। Email या phone न लिखें।

▶ CodingEasily on YouTube

Video से सीखें – आसान Hindi में

चुनी हुई video: RDBMS भाग 3 – Class XI Commerce IT

▶ Channel subscribe करें