<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Yadhunandan S</title>
    <description>The latest articles on DEV Community by Yadhunandan S (@yadhubuilds).</description>
    <link>https://dev.to/yadhubuilds</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F553753%2F659ad8b6-e76d-4263-9c0b-299ca9ea3cd2.jpg</url>
      <title>DEV Community: Yadhunandan S</title>
      <link>https://dev.to/yadhubuilds</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yadhubuilds"/>
    <language>en</language>
    <item>
      <title>How to catch the frozen tabs and jank your monitoring misses</title>
      <dc:creator>Yadhunandan S</dc:creator>
      <pubDate>Sat, 12 Sep 2026 09:03:32 +0000</pubDate>
      <link>https://dev.to/yadhubuilds/how-to-catch-the-frozen-tabs-and-jank-your-monitoring-misses-3h2a</link>
      <guid>https://dev.to/yadhubuilds/how-to-catch-the-frozen-tabs-and-jank-your-monitoring-misses-3h2a</guid>
      <description>&lt;p&gt;One user's page froze, and every dashboard stayed green. It was a long-lived single-page app, the kind of tab someone keeps open for hours. A customer writes in: yesterday the page locked up and they lost work. You open your monitoring to pull that exact session, and it is not there, because your replay tool sampled it away and it threw no error to catch on.&lt;/p&gt;

&lt;p&gt;Modern error-monitoring and real user monitoring (RUM) tools are good: real Core Web Vitals in the field, session replay, per-session drill-down, and rage-click and dead-click detection all ship today. Three failures still fall through, though, and this post is how we caught them, with a per-session recorder built on tooling most teams already own.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The session behind a complaint is often missing: replay tools sample sessions for cost, and silent failures throw no error to trigger capture. Keep every session on infrastructure you own, and any complaint stays traceable.&lt;/li&gt;
&lt;li&gt;Scroll jank and sustained drag stutter go uncaptured, because these tools detect frustration through clicks only. Each needs a small detector that samples the gesture with timestamps.&lt;/li&gt;
&lt;li&gt;A permanent &lt;strong&gt;main-thread freeze&lt;/strong&gt; can't be reported from the main thread that froze. Run the watchdog in a Web Worker so it survives and sends the report itself, from a snapshot handed over while the tab was healthy.&lt;/li&gt;
&lt;li&gt;INP measures how responsive interactions feel, but misses dead and rage clicks, scroll jank, drags, and the merely-bad interaction. Per-session logs match how people actually complain.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  On this page
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Why isn't the session you need in your monitoring tool?&lt;/li&gt;
&lt;li&gt;Why can't standard monitoring detect a frozen browser tab?&lt;/li&gt;
&lt;li&gt;What is per-session real user monitoring?&lt;/li&gt;
&lt;li&gt;Measuring what users feel with INP&lt;/li&gt;
&lt;li&gt;What does INP not measure?&lt;/li&gt;
&lt;li&gt;Small detectors for the four blind spots&lt;/li&gt;
&lt;li&gt;The measurement trap we walked into first&lt;/li&gt;
&lt;li&gt;How do you detect a frozen browser tab from a thread that isn't frozen?&lt;/li&gt;
&lt;li&gt;Send the instant you know, do not batch&lt;/li&gt;
&lt;li&gt;Run it on infrastructure you already own&lt;/li&gt;
&lt;li&gt;Record for the machine, communicate for the human&lt;/li&gt;
&lt;li&gt;What carries over&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why isn't the session you need in your monitoring tool?
&lt;/h2&gt;

&lt;p&gt;The session you need is often missing because session replay tools sample sessions to control cost. They reliably capture a session only when a JavaScript error fires. The failures this post is about throw no error. Unless that exact session landed in the small sampled fraction, it was never recorded.&lt;/p&gt;

&lt;p&gt;Replay is expensive to store, so tools keep only a portion of traffic dependably:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A sampled fraction of all sessions, often a small slice, say 10 percent (illustrative, not any vendor's exact default).&lt;/li&gt;
&lt;li&gt;Sessions where an error is thrown.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That works for loud failures. A thrown exception flags the session, and you can open it later and watch it back.&lt;/p&gt;

&lt;p&gt;The failures here are silent. A tab that slows over a long session, a scroll that stutters, a drag that lags, a main thread that freezes: none of them throw. With no exception for on-error capture to catch, the session is recorded only by luck, if it fell inside the sampled fraction. When a user complains about yesterday, their session is unlikely to be among the sampled few.&lt;/p&gt;

&lt;p&gt;Replay length is usually capped too, often to a set window, sometimes around an hour (illustrative). Sensible for cost, awkward for a long-lived single-page app. A session that runs for hours can be truncated. The stretch you care about, the slow run-up before the freeze, can sit outside the recorded window even when the session was sampled.&lt;/p&gt;

&lt;p&gt;So session replay can miss the very sessions you care about most. Sampling optimizes for a representative view of the fleet, not for guaranteeing that one arbitrary complaint is reproducible. The fix is not a cleverer sampling rule. It is &lt;strong&gt;full fidelity&lt;/strong&gt;: keep every session. That is affordable only when you record onto infrastructure you already own, which we come back to later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why can't standard monitoring detect a frozen browser tab?
&lt;/h2&gt;

&lt;p&gt;Standard monitoring cannot detect a frozen browser tab for two reasons. It aggregates individual sessions into percentiles that cannot be traced back to one user. And the monitoring script it runs inside your page sits on the same main thread that just froze. Both problems point at the same missing unit of measurement, the session.&lt;/p&gt;

&lt;p&gt;Error monitors and APM tools are built around transactions: a page load, a route change, an API call. Each is a bounded event with a start and an end, and the tool rolls thousands into percentiles you read on a dashboard. That model fits a server, where a request arrives, does its work, and leaves. A long-lived browser tab fits it far less comfortably.&lt;/p&gt;

&lt;p&gt;The failure our users described was a property of a session, not a transaction. "It got slow after a while, then froze" is a claim about how one tab behaved across its whole lifetime. The state that explains it, memory creeping up, a growing document, an interaction that quietly regressed, lives in the gaps between the transactions the tools recorded.&lt;/p&gt;

&lt;p&gt;Percentiles make this worse, because a percentile cannot be traced back to a session. When your p75 interaction latency (the value three-quarters of interactions come in under) rises, there is no thread to pull back to the person who complained. You cannot ask a percentile which session it came from, or what the tab looked like right before it stalled.&lt;/p&gt;

&lt;p&gt;The aggregate is lossy by construction. It throws away exactly the per-session detail you need to reproduce a slow-then-frozen tab.&lt;/p&gt;

&lt;p&gt;The second reason is sharper, and it motivates the whole build. A freeze that never ends cannot be reported by code that runs on the frozen thread, because that monitoring script wedges with it. The watchdog section returns to why, and what to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is per-session real user monitoring?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Per-session real user monitoring&lt;/strong&gt; records the raw, ordered story of each browser session as its own log, tagged with a session id, instead of averaging interactions into percentiles. It matches the unit you record to the unit people complain in.&lt;/p&gt;

&lt;p&gt;That is the single change of unit the rest of this post builds on. Keep the raw story of each session, and any complaint can be walked back to the events that produced it.&lt;/p&gt;

&lt;p&gt;The trade is deliberate. Percentiles are cheap and answer questions about the fleet; per-session logs are heavier and answer questions about a person. For a failure that belongs to one long session and ends in a frozen tab, the per-session log is the only artifact that can reconstruct it, so that is the one we keep.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measuring what users feel with INP
&lt;/h2&gt;

&lt;p&gt;The main number worth recording is Interaction to Next Paint. INP is the time from a user action to the next frame that visibly reflects it, a good measure of how responsive an interface feels. Thanks to the &lt;a href="https://github.com/GoogleChrome/web-vitals" rel="noopener noreferrer"&gt;&lt;code&gt;web-vitals&lt;/code&gt; library&lt;/a&gt;, it now reads across Chrome, Firefox, and Safari rather than one engine. The canonical definition lives on &lt;a href="https://web.dev/articles/inp" rel="noopener noreferrer"&gt;web.dev&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That reach is recent. INP is built on the browser's Event Timing API, and the property it depends on, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEventTiming/interactionId" rel="noopener noreferrer"&gt;&lt;code&gt;interactionId&lt;/code&gt;&lt;/a&gt;, was Chromium-only from Chrome 96 back in 2021. Firefox did not ship it until version 144, and Safari until 26.2, both in late 2025. Safari had no Event Timing API at all before 26.2.&lt;/p&gt;

&lt;p&gt;Because that cross-browser support is so new, a real share of your Firefox and Safari sessions, the ones still on older versions, emit no INP whatsoever. They report the recorder's other signals fine. They just cannot produce INP. So measure what fraction of your sessions can actually report INP before you quote a number.&lt;/p&gt;

&lt;h3&gt;
  
  
  The attribution build
&lt;/h3&gt;

&lt;p&gt;A bare INP number tells you something was slow, not what. That is what the library's attribution build is for. It breaks each interaction into the pieces that actually consumed the time: the input delay before your handler ran, the processing duration of the handler itself, and the presentation delay while the browser laid out and painted the result.&lt;/p&gt;

&lt;p&gt;That is the difference between "an interaction took 600 milliseconds" and "a click on this control spent 500 milliseconds in processing" (both figures illustrative). One is a fact. The other is a place to start reading code.&lt;/p&gt;

&lt;p&gt;The three phases each point at a different cause:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A large input delay means the main thread was busy elsewhere when the click landed, so the fix lives elsewhere in the session, not in the handler.&lt;/li&gt;
&lt;li&gt;A large processing duration puts the cost in your own handler.&lt;/li&gt;
&lt;li&gt;A large presentation delay means the browser spent its time in layout and paint.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same slow interaction, three different files to open, and for a long session input delay is the telling one: it often signals a tab that has been accumulating work.&lt;/p&gt;

&lt;p&gt;Reading it is a few lines. You import &lt;code&gt;onINP&lt;/code&gt; from the attribution entry point and log the breakdown it hands back.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;onINP&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;web-vitals/attribution&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;onINP&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attribution&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Where the time actually went, plus the element the user touched.&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INP&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ms on&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interactionTarget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;  input delay   &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inputDelay&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;  processing    &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;processingDuration&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;  presentation  &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;presentationDelay&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the teaching version, not production code, but it shows the shape of the signal: a value, a target, and three phases that say where the value came from.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does INP not measure?
&lt;/h2&gt;

&lt;p&gt;INP does not measure four real failures: dead and rage clicks where nothing repaints, scroll jank, sustained drags that stutter across many frames, and the merely-bad interaction dropped by worst-N sampling. INP is well defined, and these four fall outside its edges.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;INP captures&lt;/th&gt;
&lt;th&gt;INP does not capture&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Clicks, taps, and key presses that produce a visible paint&lt;/td&gt;
&lt;td&gt;Dead and rage clicks, where nothing repaints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;How responsive those interactions feel&lt;/td&gt;
&lt;td&gt;Scroll jank, which is continuous rather than discrete&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Each interaction split into input delay, processing, and presentation&lt;/td&gt;
&lt;td&gt;Sustained drags that stutter across many frames&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The element the user touched&lt;/td&gt;
&lt;td&gt;The merely-bad interaction dropped by worst-N sampling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Naming these four is not academic. Each is a gap you fill on purpose rather than a number that appears on its own. INP will never surface a dead click, so you watch the DOM for a non-response. It folds a stuttering drag into one clean entry, so you sample the gesture yourself. The list tells you where your monitoring is quiet.&lt;/p&gt;

&lt;p&gt;Two of these four are worth separating honestly. Dead and rage clicks are already surfaced by mainstream tools through session replay. Building your own detector for them buys you ownership and full fidelity, not a capability you could not get otherwise. Scroll jank and sustained drag stutter are different. Those tools miss them too, because their frustration detection is click-based, so no off-the-shelf product is capturing them for you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fph2iooftg8ltiz68yok6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fph2iooftg8ltiz68yok6.png" alt="One INP interaction laid out along a timeline and split into its three phases, input delay, processing duration, and presentation delay, with the interacted element labeled, next to a panel listing the interaction types INP does not capture." width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;One INP interaction broken into input delay, processing, and presentation delay, beside the interaction types INP leaves out.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Small detectors for the four blind spots
&lt;/h2&gt;

&lt;p&gt;Each blind spot gets its own small detector, cheap and specific to the failure it watches for, running alongside INP. The freeze from the opening needs a fifth detector, off the thread it watches, in its own section below.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dead clicks and rage clicks
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;dead click&lt;/strong&gt; is the most literal version of "I clicked and nothing happened": the click lands, nothing repaints, and INP produces no entry at all. We catch it with a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver" rel="noopener noreferrer"&gt;&lt;code&gt;MutationObserver&lt;/code&gt;&lt;/a&gt; scoped to the subtree of the clicked element. Register the click, watch that subtree for a beat, and if nothing in the DOM changed, record a dead click.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Dead click detector: did the click change anything in its own subtree?&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;WATCH_MS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// illustrative watch window, not a tuned constant&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;watchForDeadClick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sessionId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MutationObserver&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;subtree&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;childList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// document.contains guards a navigation away that removed the element.&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;changed&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;recordDeadClick&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;sessionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;WATCH_MS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;watchForDeadClick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentSessionId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three legitimate responses must not read as dead clicks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A canvas repaint changes pixels without changing the DOM, so exclude those regions or watch them differently.&lt;/li&gt;
&lt;li&gt;A navigation away removes the element, which the &lt;code&gt;document.contains(target)&lt;/code&gt; guard handles.&lt;/li&gt;
&lt;li&gt;A slow-but-real update can land after the watch window closes, so keep the window generous.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Several fast clicks in the same dead spot are a &lt;strong&gt;rage click&lt;/strong&gt;, so count repeats in one place.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scroll jank and sustained drags
&lt;/h3&gt;

&lt;p&gt;Scrolling is continuous rather than a discrete interaction, so INP excludes it by design, and a heavy list can scroll badly while scoring nothing. A sustained drag is the same problem in reverse: one gesture spread across many frames. One that stutters the whole way across the screen can still leave a clean INP record behind it.&lt;/p&gt;

&lt;p&gt;We measure both the same way, with bounded bursts of sampling scoped to a real gesture, taking timestamps only. Why timestamps only, and never a layout read in that loop, is a mistake we made first and describe in the next section.&lt;/p&gt;

&lt;h3&gt;
  
  
  The merely-bad click lost to worst-N sampling
&lt;/h3&gt;

&lt;p&gt;The last blind spot is one we created ourselves. If the recorder keeps only a session's few worst interactions (worst-N sampling), it will usually miss the specific click a user is complaining about, which was merely bad rather than record-breaking. So we keep all of a session's interactions, not the worst N. The whole purpose of the recorder is to be walked back to one person, and you cannot do that with the exact interaction they noticed thrown away.&lt;/p&gt;

&lt;h2&gt;
  
  
  The measurement trap we walked into first
&lt;/h2&gt;

&lt;p&gt;Our first attempt at measuring scroll smoothness was the obvious one, and it was wrong in a way worth remembering. We ran a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame" rel="noopener noreferrer"&gt;&lt;code&gt;requestAnimationFrame&lt;/code&gt;&lt;/a&gt; loop that read layout each frame to see how much the content had moved. Reading a layout property &lt;a href="https://web.dev/articles/avoid-large-complex-layouts-and-layout-thrashing" rel="noopener noreferrer"&gt;forces the browser to synchronously recompute layout&lt;/a&gt;. Doing that every frame injected work into the exact path we were trying to observe.&lt;/p&gt;

&lt;p&gt;The monitor manufactured the jank it reported, worst in the heavy, already-slow parts of the app, precisely where an honest reading mattered most.&lt;/p&gt;

&lt;p&gt;The fix was two changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We take timestamps only in the hot path and never read layout there.&lt;/li&gt;
&lt;li&gt;We replaced the forever-running loop with bounded bursts scoped to a real gesture, measuring an actual scroll for a short window instead of paying a per-frame cost forever.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Fixed scroll sampling: timestamps only, bounded to a real gesture. No layout reads here.&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;frames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;scrolling&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sampleScroll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;frames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// cheap: no layout property is read&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scrolling&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sampleScroll&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;onScrollStart&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;frames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nx"&gt;scrolling&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sampleScroll&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;onScrollEnd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;scrolling&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Turn frame timestamps into gaps off the hot path; long gaps are dropped frames.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gaps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;frames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;frames&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="nf"&gt;recordScrollJank&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;sessionId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;currentSessionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;gaps&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The durable lesson is short: a measurement that perturbs what it measures is close to worthless.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How do you detect a frozen browser tab from a thread that isn't frozen?
&lt;/h2&gt;

&lt;p&gt;You detect a frozen browser tab by moving the detector off the main thread entirely, into a dedicated Web Worker that runs on its own event loop and keeps ticking while the main thread is wedged. Everything above measures degrees of slow. A freeze is different in kind: the main thread stops servicing work entirely and stays stopped. Any detector written the normal way runs on that same thread, so a &lt;code&gt;setInterval&lt;/code&gt; meant to notice the freeze cannot fire during the freeze it exists to notice.&lt;/p&gt;

&lt;p&gt;So we put the watchdog in a dedicated Web Worker, on its own thread. It keeps running when the main thread is stuck.&lt;/p&gt;

&lt;h3&gt;
  
  
  The heartbeat
&lt;/h3&gt;

&lt;p&gt;The mechanism is a heartbeat. On a timer inside the worker, it posts a ping to the main thread and notes the time. The main thread has a tiny handler whose only job is to post an echo back. When the echo arrives, the worker compares the round trip against how long a healthy answer should take.&lt;/p&gt;

&lt;p&gt;A late echo is the useful case. If the worker expected an answer within a frame or two and got one after, say, 1,800 milliseconds (illustrative, not a measurement from a real system), the main thread was blocked for roughly that long. The lateness of the echo is the measurement of &lt;strong&gt;blocked time&lt;/strong&gt;. We get it this way on every browser, without the Chromium-only &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/PerformanceLongTaskTiming" rel="noopener noreferrer"&gt;Long Tasks&lt;/a&gt; or &lt;a href="https://developer.chrome.com/docs/web-platform/long-animation-frames" rel="noopener noreferrer"&gt;Long Animation Frames&lt;/a&gt; APIs.&lt;/p&gt;

&lt;p&gt;Here is the worker side: the heartbeat, the blocked-time reading, and the path that fires when the echo never comes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// watchdog.worker.js runs on its own thread with its own event loop.&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;identity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;      &lt;span class="c1"&gt;// session id + context, handed over while the tab is healthy&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;pingSentAt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;       &lt;span class="c1"&gt;// 0 means the last ping was answered&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PROMPT_MS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// a healthy echo returns within a frame or two&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FREEZE_MS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// illustrative: no echo for ~5s means the tab is frozen&lt;/span&gt;

&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;identity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;identity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;echo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;roundTrip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;pingSentAt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;roundTrip&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;PROMPT_MS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blocked_time&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;roundTrip&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;pingSentAt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// answered, healthy&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pingSentAt&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;pingSentAt&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;FREEZE_MS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;freeze&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;silentFor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;pingSentAt&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;pingSentAt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// report once, then keep watching&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;pingSentAt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;pingSentAt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ping&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendBeacon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/rum&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the main thread the handler stays trivial, because if answering the ping is expensive it defeats the point. The main thread also hands the worker an identity snapshot while it is still healthy: the session id and the context needed to attribute an incident later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// On the main thread: create the worker, hand it an identity snapshot, echo its pings.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;watchdog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/watchdog.worker.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// While we are still healthy, give the worker what it needs to report on its own.&lt;/span&gt;
&lt;span class="nx"&gt;watchdog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;identity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;sessionId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;currentSessionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;startedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// The only job of this handler is to answer immediately. Keep it trivial.&lt;/span&gt;
&lt;span class="nx"&gt;watchdog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ping&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;watchdog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;echo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  When the echo never comes
&lt;/h3&gt;

&lt;p&gt;The case that matters is when the echo never comes. If the worker hears nothing for several seconds (around 5 seconds is the illustrative threshold above), it concludes the tab is frozen. It does not wait for the main thread to recover, because it may never recover.&lt;/p&gt;

&lt;p&gt;It sends the report itself, from its own thread, using the identity snapshot it was handed earlier. &lt;code&gt;navigator.sendBeacon('/rum', ...)&lt;/code&gt; works inside a worker, so the freeze report goes out while the tab is still frozen, with no help from the thread that died.&lt;/p&gt;

&lt;p&gt;This is the capability we could not get off the shelf, and the reason is structural. Mainstream error-monitoring and RUM tools run their code on the main thread, so a freeze that never ends is a report they can never send. &lt;strong&gt;Moving the watchdog off-thread&lt;/strong&gt; is the whole difference between "the tab froze and we have nothing" and an incident report that arrives during the freeze.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj77oolhku3jc83c28lzd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj77oolhku3jc83c28lzd.png" alt="Two ping-pong timelines between a Web Worker and the main thread, side by side. On the left, a healthy tab returns prompt replies. On the right, a failing tab returns late replies, with the gap labeled as measured blocked time, then goes silent, and past a threshold the worker sends a freeze report to the network on its own while the main thread stays flatlined." width="800" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The worker heartbeat, healthy on the left and failing on the right. Late replies measure blocked time; silence past a threshold triggers a freeze report the worker sends by itself.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Send the instant you know, do not batch
&lt;/h2&gt;

&lt;p&gt;Send each slow interaction the moment it crosses the threshold, rather than buffering events and flushing on a timer, because of the order the bad things happen in. Buffering in memory and flushing periodically is the usual way to ship telemetry, and for most signals that is fine. For this recorder it is a liability.&lt;/p&gt;

&lt;p&gt;The sequence is jank first, then freeze. The tab struggles, an interaction crosses into poor, and moments later the thread wedges. If those struggling-interaction events are sitting in an in-memory batch waiting for the next flush, the freeze takes the batch down with it. You lose the readings that describe the run-up to the very failure you are trying to explain.&lt;/p&gt;

&lt;p&gt;So each slow interaction leaves the tab the moment it crosses the threshold, before the tab can lose it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run it on infrastructure you already own
&lt;/h2&gt;

&lt;p&gt;You do not need a new vendor to build this. We already ran a self-hosted, open-source event analytics pipeline backed by a columnar database, the kind that is fast at counting and aggregating a single field across millions of rows. It was there for product analytics, good at swallowing a high volume of small, structured events and letting us slice them.&lt;/p&gt;

&lt;p&gt;A performance signal is just another structured event. Every measurement the recorder takes is emitted as an event carrying its own session id, the surrounding context, and a pre-computed label describing how good or bad the number is. Because the classification already happened on the client, the dashboard needs no query engine and no statistics service, just a login and a bar chart. The adoption cost is close to zero: one more event type on a system that already exists, with nothing new to buy or install.&lt;/p&gt;

&lt;p&gt;This is also what makes full fidelity affordable, which the opening scene needed. Because you own the event store, keeping 100 percent of sessions costs storage you already pay for, not a per-session premium. There is no sampling rate to tune and no on-error filter deciding which sessions survive. Every session is present.&lt;/p&gt;

&lt;p&gt;Unlike a sampled commercial replay, &lt;strong&gt;the session behind any complaint, silent failure or not, is always there when you go looking&lt;/strong&gt;. The customer writes in about yesterday, and this time the session is right where you expect it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cross-browser by default
&lt;/h3&gt;

&lt;p&gt;One rule held the design together: the load-bearing signals have to work in every major browser. INP, blocked time from the worker heartbeat, action timing, and the DOM and memory gauges all do. The genuinely useful Chromium-only APIs, Long Animation Frames and precise memory measurement, are an enrichment layer, never the foundation. If your core diagnosis works in only one engine, you are blind to every user who complained from another.&lt;/p&gt;

&lt;h2&gt;
  
  
  Record for the machine, communicate for the human
&lt;/h2&gt;

&lt;p&gt;Keep precise numbers for the engineer and pre-computed buckets for everyone else, both attached to the same event at record time. Internally the recorder keeps exact milliseconds. But when someone asks whether last quarter's work helped, milliseconds are the wrong language.&lt;/p&gt;

&lt;p&gt;So every interaction is tagged at record time as good, needs-improvement, or poor, and the dashboard mostly counts those buckets. "Poor interactions fell from 14 percent of sessions to 3 percent" (illustrative, not a real system's data) is a sentence anyone can act on. "p75 improved by 300 milliseconds" (also illustrative) is not, even when it describes the same win. The buckets travel with the raw data rather than replacing it, so an engineer can still open one poor session and read it line by line.&lt;/p&gt;

&lt;h2&gt;
  
  
  What carries over
&lt;/h2&gt;

&lt;p&gt;Three ideas outlast the browser specifics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first is the one the opening turns on: full fidelity beats sampling when you have to reproduce a specific complaint. A representative sample answers questions about the fleet, but the session one user is angry about is not a statistical question, and the only way to guarantee it is there is to keep all of them.&lt;/li&gt;
&lt;li&gt;The second is the one the freeze build turns on: a detector that shares a thread with what it watches goes down with it, so the move that makes freezes observable at all is putting the watchdog somewhere the freeze cannot reach.&lt;/li&gt;
&lt;li&gt;The third bit us hardest in practice: a measurement that perturbs what it measures buys you almost nothing, so keep the hot path to timestamps and push the expensive work onto another thread.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rest is bookkeeping that matters: our users complain in sessions, so per-session logs beat transaction percentiles, and attaching the judgment to the fact at record time lets one event serve both the engineer reproducing a bug and the person deciding what to do next.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>performance</category>
      <category>webdev</category>
      <category>monitoring</category>
    </item>
    <item>
      <title>Custom React Router Prompt</title>
      <dc:creator>Yadhunandan S</dc:creator>
      <pubDate>Sun, 13 Jun 2021 09:29:38 +0000</pubDate>
      <link>https://dev.to/yadhubuilds/custom-react-router-prompt-40io</link>
      <guid>https://dev.to/yadhubuilds/custom-react-router-prompt-40io</guid>
      <description>&lt;p&gt;How to implement the custom prompt on navigation using react-router&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;What’s the need for custom prompt ?&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Most of the react projects follow the UI &lt;a href="https://uxdesign.cc/everything-you-need-to-know-about-design-systems-54b109851969" rel="noopener noreferrer"&gt;design system&lt;/a&gt; for their components. In order to achieve the same design consistency across the app, they reuse the components. However to block the navigation in case there are some unsaved user data, default browser prompt is the most common and easy way to block the user from navigating to different routes. But the popup does not match your library component.&lt;/p&gt;

&lt;p&gt;There is no official docs explicitly mentioning how to use the custom modal instead of the default &lt;code&gt;react-router&lt;/code&gt; &lt;strong&gt;Prompt&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Solution&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;There are few simple steps to be followed in order to get the required result. Each step contains 100% working code snippets. You can use it in your projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Step 1&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We need to disable or block the default browser prompt. This can be done by passing an empty callback to the &lt;strong&gt;&lt;code&gt;getUserConfirmation&lt;/code&gt;&lt;/strong&gt; function prop of the &lt;strong&gt;BrowserRouter&lt;/strong&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;Step 2&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now let’s create a custom &lt;strong&gt;RouterPrompt&lt;/strong&gt; component using the &lt;strong&gt;&lt;code&gt;useHistory&lt;/code&gt;&lt;/strong&gt; hook from the react-router-dom and &lt;a href="https://ant.design/components/modal/" rel="noopener noreferrer"&gt;ant design&lt;/a&gt; component library for the &lt;strong&gt;Modal&lt;/strong&gt; component.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;Step 3&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s create two sample components for navigating between pages. For example, let the first component be &lt;code&gt;Dashboard.jsx&lt;/code&gt; and the second component be &lt;code&gt;Home.jsx&lt;/code&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The home component contains our custom &lt;strong&gt;RouterPrompt&lt;/strong&gt; component. The prompt is triggered on the page change and also based on the &lt;strong&gt;&lt;code&gt;when&lt;/code&gt;&lt;/strong&gt; prop. The when prop is used to conditionally trigger the prompt. For instance, if the when prop is set to &lt;strong&gt;true&lt;/strong&gt; , the prompt will be shown every time page navigates (from home route to other routes or navigate forward / back).&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;onOK&lt;/code&gt; and &lt;code&gt;onCancel&lt;/code&gt; callback props must return boolean value in order to proceed with the route.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Result&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz8hisl4zmjl9p8s6ipiv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz8hisl4zmjl9p8s6ipiv.png" alt="Result" width="770" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You can use any component library’s modal, even your own custom modal or default browser prompt. But just be careful when implementing the &lt;strong&gt;&lt;code&gt;history.block&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By following the above steps you can achieve the desired solution. The code is 100% working. You can copy the code snippets to your applications to save time.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;References&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://reactrouter.com/web/api/Hooks/usehistory" rel="noopener noreferrer"&gt;https://reactrouter.com/web/api/Hooks/usehistory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://reactrouter.com/web/api/history" rel="noopener noreferrer"&gt;https://reactrouter.com/web/api/history&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>react</category>
      <category>reactrouter</category>
      <category>javascript</category>
      <category>design</category>
    </item>
    <item>
      <title>What is Output — Webpack 5</title>
      <dc:creator>Yadhunandan S</dc:creator>
      <pubDate>Sun, 02 May 2021 15:27:20 +0000</pubDate>
      <link>https://dev.to/yadhubuilds/what-is-output-webpack-5-cho</link>
      <guid>https://dev.to/yadhubuilds/what-is-output-webpack-5-cho</guid>
      <description>&lt;p&gt;&lt;strong&gt;Before continuing the article, please refer to the below link if you have missed the introduction to webpack 5&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/yadhus/introduction-to-webpack-5-5fhm"&gt;https://dev.to/yadhus/introduction-to-webpack-5-5fhm&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/yadhus/what-is-entry-webpack-5-1cb5"&gt;https://dev.to/yadhus/what-is-entry-webpack-5-1cb5&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;What is Output&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Output is a property that tells webpack where to emit / save the bundles it creates and how to name these bundled files. By default the main output file gets stored in &lt;code&gt;./dist/main.js&lt;/code&gt; and other generated files are stored in &lt;code&gt;./dist&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Single or Multi-main entry points&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Though the &lt;a href="https://dev.to/yadhus/what-is-entry-webpack-5-1cb5"&gt;entry property&lt;/a&gt; can have one or multi paths, there can be only one output configuration specified.&lt;/p&gt;
&lt;h4&gt;
  
  
  Example:
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/home.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Output:
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dist /
 - main.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Note:
&lt;/h4&gt;

&lt;p&gt;The webpack’s default configuration for the output property looks something like this&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/home.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

 &lt;span class="c1"&gt;// default output configuration&lt;/span&gt;
 &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;[name]&lt;/code&gt; resolves to the dynamic name of the bundle. Here it resolves to &lt;code&gt;main.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you want the default configuration, it is not required to mention the output property. Webpack understands and apply it implicitly.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Object entry points&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;While webpack can have multiple different &lt;a href="https://dev.to/yadhus/what-is-entry-webpack-5-1cb5"&gt;entry points&lt;/a&gt;, only one output configuration can be specified.&lt;/p&gt;
&lt;h4&gt;
  
  
  Example:
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;adminApp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/admin.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;homeApp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/home.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt;

 &lt;span class="c1"&gt;// default output configuration &lt;/span&gt;
 &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Output:
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dist /
 - adminApp.js
 - homeApp.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Advanced&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Apart from path and filename sub properties of the Output property. There are few other sub properties that are used often in the build process (like &lt;a href="https://create-react-app.dev/" rel="noopener noreferrer"&gt;CRA&lt;/a&gt; etc.). Some of them are listed below.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;PathInfo&lt;/strong&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;adminApp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/admin.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;homeApp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/home.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt;
 &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;pathInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This tells webpack to include comments in bundles with information about the contained modules (filename comments). It also adds some info about &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Tree_shaking" rel="noopener noreferrer"&gt;tree shaking&lt;/a&gt; to the generated bundle.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;ChunkFilename&lt;/strong&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;adminApp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/admin.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;homeApp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/home.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt;
 &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;pathInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="na"&gt;chunkFilename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="na"&gt;contenthash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;contenthash:8&lt;/code&gt; generates a dynamic hash value based on the contents of the files and the ‘&lt;code&gt;:8&lt;/code&gt;’ represents the length of the hash value. If the contents of the files are not changed, then the same hash value is generated.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;chunkFilename&lt;/code&gt; determines the name of the non-initial chunk files (like lazy loaded or dynamically imported modules). These filenames need to be generated at runtime to send request for the chunks.&lt;/p&gt;

&lt;p&gt;Because of this, placeholders like &lt;code&gt;[name]&lt;/code&gt; and &lt;code&gt;[contenthash]&lt;/code&gt; need to add a mapping from chunk id (&lt;code&gt;[id]&lt;/code&gt;) to placeholder value (&lt;code&gt;[name].[contenthash:8].chunk.js&lt;/code&gt;) to the output bundle with the webpack runtime. This increases the size and may invalidate the bundle when placeholder value for any chunk changes.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;PublicPath&lt;/strong&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;adminApp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/admin.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;homeApp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/home.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt;
 &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;pathInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="na"&gt;chunkFilename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="na"&gt;contenthash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="na"&gt;publicPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://server.com/assets/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; 
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;publicPath&lt;/code&gt; is where you have uploaded the bundled files. This is an important option when using on-demand-loading or loading external resources like images, files, etc.&lt;/p&gt;

&lt;p&gt;This option specifies the public URL of the output directory when referenced in a browser. A relative URL is resolved relative to the HTML page (or &lt;code&gt;&amp;lt;base&amp;gt;&lt;/code&gt; tag). Server-relative URLs, protocol-relative URLs or absolute URLs are also possible and sometimes required, i.e. when hosting assets on a CDN.&lt;/p&gt;

&lt;p&gt;In the above code snippet, the request to the chunk file will look something like this &lt;code&gt;https://server.com/assets/1.a345ersd.chunk.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The webpack-dev-server also takes a hint from &lt;code&gt;publicPath&lt;/code&gt;, using it to determine where to serve the output files from.&lt;/p&gt;

&lt;p&gt;By default, the publicPath value is set to ‘/’.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;GlobalObject&lt;/strong&gt;
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;adminApp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/admin.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;homeApp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/home.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt;
 &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;pathInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="na"&gt;chunkFilename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="na"&gt;contenthash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="na"&gt;publicPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://server.com/assets/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;globalObject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;this&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When targeting a library, especially when &lt;code&gt;libraryTarget&lt;/code&gt; is '&lt;code&gt;umd&lt;/code&gt;', this option indicates what global object will be used to mount the library.&lt;/p&gt;

&lt;p&gt;To make &lt;a href="https://github.com/umdjs/umd" rel="noopener noreferrer"&gt;UMD&lt;/a&gt; build available on both browsers and Node.js, set &lt;code&gt;globalObject&lt;/code&gt; option to '&lt;code&gt;this&lt;/code&gt;'.&lt;/p&gt;

&lt;p&gt;Defaults to &lt;code&gt;self&lt;/code&gt; / &lt;code&gt;window&lt;/code&gt; for Web-like targets.&lt;/p&gt;
&lt;h4&gt;
  
  
  The webpack configuration file specifically to highlight output property:
&lt;/h4&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;GitHub Repo Link&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/yadhus/What-is-Output-Webpack-5" rel="noopener noreferrer"&gt;https://github.com/yadhus/What-is-Output-Webpack-5&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;References&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://webpack.js.org/configuration/output/" rel="noopener noreferrer"&gt;https://webpack.js.org/configuration/output/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://webpack.js.org/concepts/#output" rel="noopener noreferrer"&gt;https://webpack.js.org/concepts/#output&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webpack</category>
      <category>javascript</category>
      <category>react</category>
      <category>angular</category>
    </item>
    <item>
      <title>What is Entry — Webpack 5</title>
      <dc:creator>Yadhunandan S</dc:creator>
      <pubDate>Sat, 09 Jan 2021 19:38:24 +0000</pubDate>
      <link>https://dev.to/yadhubuilds/what-is-entry-webpack-5-1cb5</link>
      <guid>https://dev.to/yadhubuilds/what-is-entry-webpack-5-1cb5</guid>
      <description>&lt;p&gt;&lt;strong&gt;Before continuing the article, please refer to the below link if you have missed the introduction to webpack 5&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/yadhus/introduction-to-webpack-5-5fhm"&gt;https://dev.to/yadhus/introduction-to-webpack-5-5fhm&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is entry&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Entry is a property that indicates webpack which module(s) / file(s) it should use to &lt;em&gt;begin building&lt;/em&gt; out the internal dependency graph(s) of the project / application.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Three syntax of entry&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Single entry&lt;/li&gt;
&lt;li&gt;Multi-main entry&lt;/li&gt;
&lt;li&gt;Object entry&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Single entry&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The single entry syntax points to &lt;strong&gt;one file path&lt;/strong&gt; to start building the dependency graph of the project / application. It is a great choice when you are looking to quickly setup a webpack configuration for an application or tool with one entry point (i.e. a library)&lt;/p&gt;

&lt;h4&gt;
  
  
  Usage
&lt;/h4&gt;

&lt;p&gt;entry: String&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/index.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Multi-main entry&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The multi-main entry syntax points to &lt;strong&gt;multiple file paths&lt;/strong&gt;. Its creates &lt;strong&gt;separate dependency graphs&lt;/strong&gt; based on these paths and finally get combined or merged into a single file.&lt;/p&gt;
&lt;h4&gt;
  
  
  Usage
&lt;/h4&gt;

&lt;p&gt;entry: [String]&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
   &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/index_1.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/index_2.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Object entry&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The object entry syntax &lt;strong&gt;creates separate files for each key value pair&lt;/strong&gt; in the entry object. It allows you to customize the chunk / bundled file name (key name). This is the most scalable way of defining entry / entries in your application.&lt;/p&gt;

&lt;p&gt;This is a popular technique used to separate concerns by environment, build target, and runtime.&lt;/p&gt;
&lt;h4&gt;
  
  
  Usage
&lt;/h4&gt;

&lt;p&gt;entry: { [entryChunkName] : String }&lt;/p&gt;
&lt;h4&gt;
  
  
  Usage
&lt;/h4&gt;

&lt;p&gt;entry: { [entryChunkName] : [String] }&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;adminApp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/admin.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;homeApp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/home_1.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/home_2.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  The webpack configuration file specifically to highlight entry property:
&lt;/h4&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Note&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can pass empty object to entry when you have only entry points generated by plugins (will see more about this in detail in the upcoming articles).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;GitHub Repo Link&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/yadhus/What-is-Entry-Webpack-5" rel="noopener noreferrer"&gt;https://github.com/yadhus/What-is-Entry-Webpack-5&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Next article&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/yadhus/what-is-output-webpack-5-cho"&gt;https://dev.to/yadhus/what-is-output-webpack-5-cho&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;References&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://webpack.js.org/guides/entry-advanced/" rel="noopener noreferrer"&gt;https://webpack.js.org/guides/entry-advanced/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://webpack.js.org/concepts/#entry" rel="noopener noreferrer"&gt;https://webpack.js.org/concepts/#entry&lt;/a&gt;&lt;br&gt;
&lt;a href="https://webpack.js.org/api/" rel="noopener noreferrer"&gt;https://webpack.js.org/api/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://webpack.js.org/configuration/" rel="noopener noreferrer"&gt;https://webpack.js.org/configuration/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webpack</category>
      <category>javascript</category>
      <category>react</category>
      <category>angular</category>
    </item>
    <item>
      <title>Introduction to Webpack 5</title>
      <dc:creator>Yadhunandan S</dc:creator>
      <pubDate>Tue, 05 Jan 2021 07:05:01 +0000</pubDate>
      <link>https://dev.to/yadhubuilds/introduction-to-webpack-5-5fhm</link>
      <guid>https://dev.to/yadhubuilds/introduction-to-webpack-5-5fhm</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;What is webpack&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Webpack is a &lt;strong&gt;&lt;em&gt;static module bundler&lt;/em&gt;&lt;/strong&gt; for modern JavaScript applications. When webpack processes the application, it internally builds a dependency graph which maps every module (like node_modules, images, CSS, etc.) your project needs and generates one or more bundles.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Module Bundler&lt;/em&gt; — A tool that takes JavaScript &amp;amp; its dependencies and bundles them into a single / multiple files (to use in browser).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Dependency Graph&lt;/em&gt; — A graph that maps all the dependencies between files based on the order / hierarchy in which it is used or referenced.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Webpack builds and loads modules synchronously. It converts dependencies into modules and pulls the dependencies and modules at the right time in the right scope. Finally, it loads all these modules and dependencies into one or few files and downloads it in the browser (when requested).&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;webpack requires a configuration file to bundle your project. Webpack, by default has a default configuration once you install it (using NPM). But webpack allows you to incredibly configure it based on your project needs and requirements.&lt;/p&gt;

&lt;p&gt;The basic webpack configuration file looks something like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;To understand the webpack configuration and to get started, First you need to know the core concepts of webpack:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Entry&lt;/li&gt;
&lt;li&gt;Output&lt;/li&gt;
&lt;li&gt;Loaders&lt;/li&gt;
&lt;li&gt;Plugins&lt;/li&gt;
&lt;li&gt;Mode&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Mode&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This parameter enables webpack to identify and add built-in optimizations for the corresponding environment. The default value for the mode parameter is ‘production’.&lt;/p&gt;

&lt;p&gt;There are three modes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;production&lt;/li&gt;
&lt;li&gt;development&lt;/li&gt;
&lt;li&gt;none - does not add any default / built-in optimizations
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Entry&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;An entry is a starting / initial point for webpack to start building out its internal dependency graph. Based on this webpack will figure out other modules, libraries and assets that the entry point depends on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./path/to/my/entry/file.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Output&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The output property tells webpack where to save the bundles it creates and how to name the bundled files. This property only applies to JavaScript files not on other files like HTML, CSS etc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./path/to/my/entry/file.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
   &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Loaders&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Loaders are used to preprocess the files as you import or load them and allows you to bundle any other static resources (like .png, .img, .css, .sass, etc.).&lt;/p&gt;

&lt;p&gt;Loaders are like tasks in other build tools and provide a powerful way to handle front-end build steps. It can transform files from a different language to JavaScript or load inline images as data URLs. It even allows you to directly import CSS files from your JavaScript modules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./path/to/my/entry/file.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
   &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt;
 &lt;span class="na"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;css$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;style-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;css-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;‘module’ — property is used to denote the loaders and its configuration.&lt;/p&gt;

&lt;p&gt;‘rules’ — property is a list of objects that contain the different types of loaders. Each item (object) of the rules property contains ‘test’ and ‘use’.&lt;/p&gt;

&lt;p&gt;‘test’ — property takes a regex and executes the specified loader for the file types that match.&lt;/p&gt;

&lt;p&gt;‘use’ — property takes the loader type value that will be used for executing / transforming the specified file type(s).&lt;/p&gt;

&lt;p&gt;In the above code snippet, the rules checks for the CSS file types and transforms it (to use in browser) using the css-loader and style-loader. The css-loader interprets the ‘&lt;a class="mentioned-user" href="https://dev.to/import"&gt;@import&lt;/a&gt;’ and ‘url()’ and resolves them. The style-loader injects the CSS into the DOM. (takes the styles and creates a style tag in the HTML)&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Plugins&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Plugins provide a powerful way to tap / injects custom build into webpack’s compilation process. A plugin is able to hook into key events that are fired throughout each compilation.&lt;br&gt;
Plugins are the backbone of the webpack. Webpack itself is built on the same plugin system that you use in your webpack configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./path/to/my/entry/file.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
   &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt;
 &lt;span class="na"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;css$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;style-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;css-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt;
 &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HtmlWebpackPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
 &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;‘plugins’ — property is a list of new instances of plugins. Each plugin instance takes arguments / options which you need to pass in the new instance.&lt;/p&gt;

&lt;p&gt;In the above code snippet, plugins contain the HtmlWebpackPlugin instance which creates a new HTML file based on the template HTML file (./src/index.html) and puts it inside the output folder (./dist).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Difference between loaders and plugins&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Loaders do pre-processing transformation of any file types that we specify. Loaders work at the individual level during or before the bundle is generated. Loaders are not able to influence the actual build process.&lt;/p&gt;

&lt;p&gt;Plugins are executed after the end of the bundle generation process. Plugins can modify how bundles are created and have more control than loaders.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why webpack&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;First and most important reason for using webpack is that it gives complete control over the frontend build process and helps to build boiler plates or ready-made app for developers to start coding using the major frameworks like React, Angular and Vue.&lt;/p&gt;

&lt;p&gt;Using webpack loaders, we can use modern JavaScript syntax like arrow functions, spread operators, etc. which are then later transformed (during the bundle generation) into common JavaScript that are compatible with all the modern and old browsers.&lt;/p&gt;

&lt;p&gt;In development mode, webpack also provides ‘Hot Module Replacement’ which updates the modules without fully reloading the entire page. This saves the development time by only updating what’s changed.&lt;/p&gt;

&lt;p&gt;It is used to optimize and minimize the code, so that it loads and downloads the bundled files / chunks faster in the browser. All these process and transformations are executed in a single build process in a very short time.&lt;/p&gt;

&lt;p&gt;There are many more features and advantages of webpack which I will cover in detail in the upcoming articles.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;GitHub Repo Link&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/yadhus/Introduction-to-Webpack-5" rel="noopener noreferrer"&gt;https://github.com/yadhus/Introduction-to-Webpack-5&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Next article&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/yadhus/what-is-entry-webpack-5-1cb5"&gt;https://dev.to/yadhus/what-is-entry-webpack-5-1cb5&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;References&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://webpack.js.org/concepts/" rel="noopener noreferrer"&gt;https://webpack.js.org/concepts/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://webpack.js.org/api/" rel="noopener noreferrer"&gt;https://webpack.js.org/api/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://webpack.js.org/configuration/" rel="noopener noreferrer"&gt;https://webpack.js.org/configuration/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://stackoverflow.com/questions/37452402/webpack-loaders-vs-plugins-whats-the-difference" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/37452402/webpack-loaders-vs-plugins-whats-the-difference&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webpack</category>
      <category>javascript</category>
      <category>react</category>
      <category>angular</category>
    </item>
  </channel>
</rss>
