<?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: Shidhin</title>
    <description>The latest articles on DEV Community by Shidhin (@shidhincr).</description>
    <link>https://dev.to/shidhincr</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F114922%2F41d6e8ce-a9c5-4f6e-9ce8-97a4dbb9cadb.jpeg</url>
      <title>DEV Community: Shidhin</title>
      <link>https://dev.to/shidhincr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shidhincr"/>
    <language>en</language>
    <item>
      <title>The &lt;geolocation&gt; Element Changed How I Think About Permissions</title>
      <dc:creator>Shidhin</dc:creator>
      <pubDate>Mon, 26 Jan 2026 14:27:58 +0000</pubDate>
      <link>https://dev.to/shidhincr/the-element-changed-how-i-think-about-permissions-36nn</link>
      <guid>https://dev.to/shidhincr/the-element-changed-how-i-think-about-permissions-36nn</guid>
      <description>&lt;p&gt;I've been building web apps that need location data for years. And honestly? I've always dreaded the geolocation code. Not because the API is complicated—it's actually pretty simple—but because of everything &lt;em&gt;around&lt;/em&gt; it. The permission prompts that fire before users even know why they need to share their location. The dead-end when someone clicks "Block" by accident. The awkward dance of trying to explain "please go to your browser settings and reset permissions."&lt;/p&gt;

&lt;p&gt;Chrome 144 shipped something that made me genuinely excited: the &lt;code&gt;&amp;lt;geolocation&amp;gt;&lt;/code&gt; element. It's a declarative, HTML-first approach to location permissions, and after playing with it, I'm convinced this is how permissions should have worked all along.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Old Way Was Painful
&lt;/h2&gt;

&lt;p&gt;Let's be honest about the traditional &lt;code&gt;navigator.geolocation.getCurrentPosition()&lt;/code&gt; API. It &lt;em&gt;works&lt;/em&gt;, but it creates problems.&lt;/p&gt;

&lt;p&gt;The permission prompt fires whenever your JavaScript decides to call the function. Users see a popup before they've even clicked anything. They don't know &lt;em&gt;why&lt;/em&gt; your app wants their location, and the natural instinct is to click "Block." I've watched user testing sessions where people blocked location access reflexively, then complained the app didn't work.&lt;/p&gt;

&lt;p&gt;Once blocked, there's no recovery. Your code can't re-trigger the prompt. You're stuck showing a sad "please go to Settings &amp;gt; Privacy &amp;gt; Site Settings &amp;gt; Location" message that 95% of users will never follow.&lt;/p&gt;

&lt;p&gt;The browser also has no way to know if the request came from genuine user intent or from some sketchy script trying to harvest location data on page load.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the &lt;code&gt;&amp;lt;geolocation&amp;gt;&lt;/code&gt; Element Does Differently
&lt;/h2&gt;

&lt;p&gt;The core idea is simple: instead of &lt;em&gt;JavaScript&lt;/em&gt; triggering the permission flow, the &lt;em&gt;user&lt;/em&gt; triggers it by clicking a browser-controlled button. The browser renders a styled button with localized text (something like "Use Location" in English, "Standort verwenden" in German). When the user clicks it, they're providing an explicit signal: "Yes, I want to share my location."&lt;/p&gt;

&lt;p&gt;Let's see the most basic version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;geolocation&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;"requestLocationFallback()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Share Location&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/geolocation&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The content inside the &lt;code&gt;&amp;lt;geolocation&amp;gt;&lt;/code&gt; element is fallback for browsers that don't support it yet. In Chrome 144+, the browser replaces this with its own trusted button.&lt;/p&gt;

&lt;p&gt;Here's what happens when you wire it up with JavaScript:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;geoElement&lt;/span&gt; &lt;span class="o"&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;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;geoElement&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;geoElement&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="s2"&gt;location&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="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;pos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;geoElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&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;pos&lt;/span&gt;&lt;span class="p"&gt;)&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="s2"&gt;`Lat: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, Lng: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;geoElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&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="s2"&gt;`Error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;geoElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;The above code is pretty simple to understand. We're listening for the &lt;code&gt;location&lt;/code&gt; event on the element, then reading the &lt;code&gt;position&lt;/code&gt; attribute directly from it. No callbacks, no separate success/error handlers—just straightforward property access.&lt;/p&gt;

&lt;h2&gt;
  
  
  The JavaScript Interface
&lt;/h2&gt;

&lt;p&gt;The element exposes a clean interface that's worth understanding:&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;HTMLGeolocationElement&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;attribute&lt;/span&gt; &lt;span class="nx"&gt;GeolocationPosition&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;attribute&lt;/span&gt; &lt;span class="nx"&gt;GeolocationPositionError&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;attribute&lt;/span&gt; &lt;span class="nx"&gt;PermissionState&lt;/span&gt; &lt;span class="nx"&gt;permissionStatus&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;attribute&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="nx"&gt;autolocate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;attribute&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="nx"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;attribute&lt;/span&gt; &lt;span class="nx"&gt;EventHandler&lt;/span&gt; &lt;span class="nx"&gt;onlocation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;attribute&lt;/span&gt; &lt;span class="nx"&gt;EventHandler&lt;/span&gt; &lt;span class="nx"&gt;onpromptaction&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;attribute&lt;/span&gt; &lt;span class="nx"&gt;EventHandler&lt;/span&gt; &lt;span class="nx"&gt;onpromptdismiss&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;permissionStatus&lt;/code&gt; property is particularly useful. It tells you whether permission is &lt;code&gt;granted&lt;/code&gt;, &lt;code&gt;denied&lt;/code&gt;, or &lt;code&gt;prompt&lt;/code&gt;—so you can build UI that responds appropriately without guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Different Kinds of Location Tracking
&lt;/h2&gt;

&lt;p&gt;The element supports two modes through attributes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One-time location&lt;/strong&gt; is the default. User clicks, location fires once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;geolocation&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"geo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;Get My Location&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/geolocation&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Continuous tracking&lt;/strong&gt; uses the &lt;code&gt;watch&lt;/code&gt; attribute. It's like &lt;code&gt;watchPosition()&lt;/code&gt; but declarative:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;geolocation&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"tracker"&lt;/span&gt; &lt;span class="na"&gt;watch&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;Track Me&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/geolocation&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Auto-locate&lt;/strong&gt; is interesting. If you add the &lt;code&gt;autolocate&lt;/code&gt; attribute &lt;em&gt;and&lt;/em&gt; the user has already granted permission, the element will fetch location automatically on page load:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;geolocation&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"geo"&lt;/span&gt; &lt;span class="na"&gt;autolocate&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;Share Location&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/geolocation&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is great for apps where location is central—like a delivery tracker where returning users have already opted in.&lt;/p&gt;

&lt;h2&gt;
  
  
  A More Complete Example
&lt;/h2&gt;

&lt;p&gt;Let me show something closer to real-world usage. Here's a location card that displays coordinates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"location-card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;📍 Your Location&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"coordinates"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"coords"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Click the button to share your location
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;geolocation&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"geoElement"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;"fallbackLocation()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Share Location (Fallback)&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/geolocation&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;geoElement&lt;/span&gt; &lt;span class="o"&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;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;geoElement&lt;/span&gt;&lt;span class="dl"&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;coordsDisplay&lt;/span&gt; &lt;span class="o"&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;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;coords&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;geoElement&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="s2"&gt;location&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="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;pos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;geoElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&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;pos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;coordsDisplay&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
        Lat: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;br&amp;gt;
        Lng: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;
      `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;geoElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;coordsDisplay&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;geoElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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="c1"&gt;// Fallback for unsupported browsers&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fallbackLocation&lt;/span&gt;&lt;span class="p"&gt;()&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="nx"&gt;geolocation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getCurrentPosition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pos&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;coordsDisplay&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
          Lat: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;br&amp;gt;
          Lng: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&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;err&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;coordsDisplay&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how the fallback button inside &lt;code&gt;&amp;lt;geolocation&amp;gt;&lt;/code&gt; uses the traditional API. Progressive enhancement at its finest—old browsers get the old behavior, new browsers get the better UX.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security That's Actually Built-In
&lt;/h2&gt;

&lt;p&gt;The element has some clever security measures that I didn't have to think about (which is the point).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Visibility validation&lt;/strong&gt;: The element must be fully visible in the viewport. No hiding it behind other elements or positioning it off-screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Movement detection&lt;/strong&gt;: If you programmatically move the element, it's temporarily disabled for 500ms. This prevents clickjacking attacks where the element slides under the cursor right before a click.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Style constraints&lt;/strong&gt;: You can't make the element invisible or heavily disguise it. The browser maintains control over its appearance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trusted events only&lt;/strong&gt;: Only actual user clicks work. Synthetic JavaScript events won't trigger the permission flow.&lt;/p&gt;

&lt;p&gt;I used to write custom code to prevent some of these attacks. Now the browser handles it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detecting Support
&lt;/h2&gt;

&lt;p&gt;Since this is Chrome-only for now, you need feature detection:&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isGeolocationElementSupported&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HTMLGeolocationElement&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Or the prototype check&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkSupport&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;testElement&lt;/span&gt; &lt;span class="o"&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;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;geolocation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;testElement&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;HTMLGeolocationElement&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;Then you can conditionally render different UI or rely on the fallback content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Old vs. New: A Quick Comparison
&lt;/h2&gt;

&lt;p&gt;Here's the traditional approach with all its ceremony:&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;requestLocation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&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;permission&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;geolocation&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;permission&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;denied&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="nf"&gt;showPermissionDeniedUI&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="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;geolocation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getCurrentPosition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handleSuccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;enableHighAccuracy&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;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Permission API not supported&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;And here's the new approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;geolocation&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"geo"&lt;/span&gt; &lt;span class="na"&gt;autolocate&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;Share Location&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/geolocation&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;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;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;geo&lt;/span&gt;&lt;span class="dl"&gt;"&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="s2"&gt;location&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;e&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;handleSuccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;position&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;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Less code, better UX, built-in security. I'll take that trade every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extra Points
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;onpromptdismiss&lt;/code&gt; event fires when a user closes the permission prompt without making a choice. This lets you show contextual help instead of leaving them confused.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;lang&lt;/code&gt; attribute controls button text localization. The browser handles translation automatically, but you can override it if needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don't use &lt;code&gt;autolocate&lt;/code&gt; on first visit. It only works when permission is already granted, but the intent is for returning users—not to spam new visitors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The element is disabled inside fenced frames for security reasons. If you're building embedded widgets, keep this in mind.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;&amp;lt;geolocation&amp;gt;&lt;/code&gt; element is what I wish we'd had from the start. It turns a JavaScript-triggered, easily-blocked, no-recovery permission flow into a user-initiated, browser-trusted, properly-recoverable experience. Once other browsers adopt this pattern, geolocation in web apps will feel a lot less hostile to users—and a lot less painful for developers. :)&lt;/p&gt;

</description>
      <category>geolocation</category>
      <category>html</category>
      <category>chrome</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Ship Faster, Debug Smarter: My Take on the New Chrome DevTools AI</title>
      <dc:creator>Shidhin</dc:creator>
      <pubDate>Thu, 04 Dec 2025 13:24:56 +0000</pubDate>
      <link>https://dev.to/shidhincr/ship-faster-debug-smarter-my-take-on-the-new-chrome-devtools-ai-4h4m</link>
      <guid>https://dev.to/shidhincr/ship-faster-debug-smarter-my-take-on-the-new-chrome-devtools-ai-4h4m</guid>
      <description>&lt;p&gt;I recently had the incredible opportunity to speak at GDG Coimbatore about a shift that is fundamentally changing how we build for the web: the integration of AI directly into Chrome DevTools. We all want to "Ship Faster," but the real challenge has always been how to "Debug Smarter."&lt;/p&gt;

&lt;p&gt;If you missed the session, I wanted to write up a quick summary of the key updates. We are moving away from blindly staring at timelines and guessing, to having Gemini help us with styling, network issues, and performance without ever leaving the tab.&lt;/p&gt;

&lt;p&gt;Here is the breakdown of what I covered and what you need to know.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Reality Check: It’s Not About Your Laptop
&lt;/h2&gt;

&lt;p&gt;I started the session with a quote that I think every frontend engineer needs to tape to their monitor:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"Performance isn't about your laptop; it's about theirs."&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We often build on high-end machines with fiber internet, but the data tells a completely different story. When you look at Core Web Vitals like LCP (Largest Contentful Paint) and INP (Interaction to Next Paint), there is a massive gap between desktop and phone performance. For example, while desktop pass rates for INP might be decent, mobile users are often struggling with responsiveness.&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.amazonaws.com%2Fuploads%2Farticles%2Febc97edd5kzl8uzlgnz6.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%2Febc97edd5kzl8uzlgnz6.png" alt=" " width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we want to fix this, we have to stop debugging in a vacuum. I always recommend using the &lt;strong&gt;Throttling&lt;/strong&gt; settings in DevTools. Don't just test on "No throttling." Try mimicking a "Slow 4G" network and slowing down your CPU by 4x or 6x to really feel what your user feels.&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.amazonaws.com%2Fuploads%2Farticles%2Fapbs2km1q8whqtc1eu36.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%2Fapbs2km1q8whqtc1eu36.png" alt=" " width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Performance Panel is Evolving
&lt;/h2&gt;

&lt;p&gt;One of the biggest friction points for us developers has always been context switching—running a Lighthouse audit in one tab and then trying to map those findings to a Performance trace in another.&lt;/p&gt;

&lt;p&gt;That’s changing. The standalone "Insights" panel is actually being deprecated. Instead, Lighthouse is moving to insight-based audits directly inside the Performance panel.&lt;/p&gt;

&lt;p&gt;Now, when you record a trace, you get &lt;strong&gt;"Insights Annotations"&lt;/strong&gt; baked right in. You can drill down into specific metrics like "LCP by phase" or investigate "Layout shift culprits" immediately. It’s designed so we spend "Less Searching, More Finding."&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.amazonaws.com%2Fuploads%2Farticles%2F0mjmu7rrrq49kyasejz6.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%2F0mjmu7rrrq49kyasejz6.png" alt=" " width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter the AI: A Helper, Not a Replacement
&lt;/h2&gt;

&lt;p&gt;This is the part everyone is excited about. We now have &lt;strong&gt;"Ask AI"&lt;/strong&gt; integrated directly into the Console and other panels. It’s powered by Gemini and designed to help us navigate the parts of web development that usually require opening ten new Google tabs.&lt;/p&gt;

&lt;p&gt;Here are the three main ways I’ve been using it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Fixing Styling Bugs:&lt;/strong&gt; CSS can be a nightmare. You can now ask the AI to explain a specific element's styles or help you fix layout bugs—like finally figuring out why that one element won't center.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Analyzing Network Requests:&lt;/strong&gt; Instead of manually parsing headers, you can ask the AI to look at a failed request or explain what a specific response header implies.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Understanding Source Files:&lt;/strong&gt; Let’s be honest, it’s rare that we wrote 100% of the code on our websites. If you are looking at a minified or unfamiliar script, the AI can explain what that file is actually doing.&lt;/li&gt;
&lt;/ol&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%2Fuuxpgzvnoh8llifihad2.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%2Fuuxpgzvnoh8llifihad2.png" alt=" " width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Enable It (And a Word of Caution)
&lt;/h2&gt;

&lt;p&gt;To get these features, you generally need to head into your DevTools &lt;strong&gt;Settings&lt;/strong&gt;, go to &lt;strong&gt;Experiments&lt;/strong&gt; (or the &lt;strong&gt;AI innovations&lt;/strong&gt; tab in newer versions), and toggle on "AI assistance".&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.amazonaws.com%2Fuploads%2Farticles%2Fa2fmyexe6683tx9f4fcr.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%2Fa2fmyexe6683tx9f4fcr.png" alt=" " width="800" height="605"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, I have to end with a "Be Careful" warning.&lt;/p&gt;

&lt;p&gt;This is Generative AI. It can be wrong. The tool is experimental and might provide inaccurate info, so you should always validate the AI's suggestions with a new recording. My rule of thumb? Keep your fixes small and reversible. Also, keep in mind that your prompts and inspected page data are sent to Google, so be mindful if you are working with sensitive enterprise data.&lt;/p&gt;

&lt;p&gt;It’s an exciting time to be building for the web. If you want to dive deeper, check out the official &lt;a href="https://developer.chrome.com/docs/devtools#ai" rel="noopener noreferrer"&gt;Chrome docs on AI assistance.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tooling</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Beyond the Flame Chart: Chrome DevTools' New AI Instantly Pinpoints Your Site's Performance Issues</title>
      <dc:creator>Shidhin</dc:creator>
      <pubDate>Wed, 05 Nov 2025 16:23:14 +0000</pubDate>
      <link>https://dev.to/shidhincr/beyond-the-flame-chart-chrome-devtools-new-ai-instantly-pinpoints-your-sites-performance-issues-m3</link>
      <guid>https://dev.to/shidhincr/beyond-the-flame-chart-chrome-devtools-new-ai-instantly-pinpoints-your-sites-performance-issues-m3</guid>
      <description>&lt;p&gt;If you're a web developer, you know the ritual. Your site feels slow, so you open the Chrome DevTools "Performance" panel, hit "record," and brace yourself.&lt;/p&gt;

&lt;p&gt;What you get is a powerful, but incredibly dense, "wall of data." A complex, multi-colored flame chart, a dense network waterfall, and a dozen metrics you have to cross-reference. For many, this is where the debugging process stalls. Is the problem a Long Task? A render-blocking resource? A late-discovered LCP element? Interpreting this data correctly is a specialized skill.&lt;/p&gt;

&lt;p&gt;But what if you didn't have to? What if you could have an expert performance engineer look over your shoulder, analyze that entire trace in seconds, and just tell you what to fix?&lt;/p&gt;

&lt;p&gt;That's exactly what Google is now building directly into Chrome.&lt;/p&gt;

&lt;h3&gt;
  
  
  Meet Your New "AI Assistance"
&lt;/h3&gt;

&lt;p&gt;Buried within the latest DevTools is a new feature that fundamentally changes this workflow. Instead of manually scrubbing the timeline and deciphering the chart, you can now simply ask for help.&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.amazonaws.com%2Fuploads%2Farticles%2Fok3x6ur8s0a5skajqluw.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%2Fok3x6ur8s0a5skajqluw.png" alt="AI Assistance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's the new workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Run Your Trace:&lt;/strong&gt; You start by recording a Performance trace just as you always have, capturing the page load or interaction you want to debug.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Open "Debug with AI":&lt;/strong&gt; Once the trace is complete, you go to the main three-dot menu in the corner of DevTools. There's a new option: &lt;strong&gt;"Debug with AI."&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Ask the Right Questions:&lt;/strong&gt; This opens a new "AI assistance" panel directly beside your trace. This panel is context-aware; it "sees" your performance data and provides suggested prompts to get you started, such as:

&lt;ul&gt;
&lt;li&gt;"What performance issues exist with my page?"&lt;/li&gt;
&lt;li&gt;"What can I do to reduce the LCP time for this page load?"&lt;/li&gt;
&lt;li&gt;"Why is LCP discovery time important?"&lt;/li&gt;
&lt;li&gt;"How can I prevent layout shifts on this page?"&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  From "Wall of Data" to Actionable Insights
&lt;/h3&gt;

&lt;p&gt;This is where the magic happens. When you select a prompt like &lt;strong&gt;"What performance issues exist with my page?"&lt;/strong&gt;, the AI doesn't give you a generic checklist. It performs a specific analysis of &lt;em&gt;your&lt;/em&gt; trace and delivers a prioritized, human-readable report.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/I9aNacMzD9M"&gt;
  &lt;/iframe&gt;


&lt;br&gt;
Based on a recent trace, here is the kind of powerful, specific feedback this AI can provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LCP Render Delay (602 ms):&lt;/strong&gt; It doesn't not just say "LCP is slow." It identifies the &lt;em&gt;exact&lt;/em&gt; problem: "A significant portion of your Largest Contentful Paint (LCP) time is spent in the render delay phase. This indicates that the LCP element was ready to be painted but was &lt;strong&gt;blocked by other rendering work&lt;/strong&gt;." This immediately narrows your focus.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Image Delivery (3.7 MB wasted):&lt;/strong&gt; It provides a specific, quantifiable problem: "There are &lt;strong&gt;unoptimized images&lt;/strong&gt; on your page, leading to &lt;strong&gt;3.7 MB of wasted data transfer&lt;/strong&gt;." This is a direct instruction to go and compress your images.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long Tasks on Main thread:&lt;/strong&gt; It connects the dots to user interaction metrics. It will identify "several long tasks" and explain that these "can &lt;strong&gt;block the browser from responding to user input&lt;/strong&gt;, negatively affecting Interaction to Next Paint (INP)."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Render-Blocking Resources:&lt;/strong&gt; It flags the classic bottleneck of "resources that are &lt;strong&gt;blocking the page's initial render&lt;/strong&gt;," another clear-cut problem to solve.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why This is a Game-Changer
&lt;/h3&gt;

&lt;p&gt;This feature isn't just a gimmick; it represents a fundamental shift in developer tooling.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It Lowers the Barrier to Entry:&lt;/strong&gt; Junior developers or those who don't specialize in performance can now get the same high-level analysis that would previously have required a seasoned expert.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It Saves Massive Amounts of Time:&lt;/strong&gt; For senior developers, this AI acts as an incredibly fast assistant. It performs the initial 10-15 minutes of data triage in about two seconds, letting you jump straight to implementing the fix.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It Shifts Your Focus:&lt;/strong&gt; You can spend less time trying to &lt;em&gt;interpret data&lt;/em&gt; and more time &lt;em&gt;solving problems&lt;/em&gt;. The tool even encourages this by providing follow-up prompts, like "Tell me more about the LCP render delay," allowing you to drill down interactively.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the future of developer tooling: not a replacement for your skills, but a powerful augment that handles the tedious work, letting you focus on what matters—building a faster, better web experience.&lt;/p&gt;

</description>
      <category>tooling</category>
      <category>ai</category>
      <category>performance</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Using the fetchLater() API</title>
      <dc:creator>Shidhin</dc:creator>
      <pubDate>Thu, 26 Jun 2025 14:22:08 +0000</pubDate>
      <link>https://dev.to/shidhincr/using-the-fetchlater-api-2omm</link>
      <guid>https://dev.to/shidhincr/using-the-fetchlater-api-2omm</guid>
      <description>&lt;h2&gt;
  
  
  Using the fetchLater() API: Reliable Beaconing for the Modern Web
&lt;/h2&gt;

&lt;p&gt;Chrome 135, released in April 2025, introduces a powerful new addition to web developers' toolkit: the &lt;code&gt;fetchLater()&lt;/code&gt; API. This feature solves a long-standing challenge of reliably sending data to servers when a user leaves a page. In this post, we'll explore what the API offers, why it matters, and how to start using it in your applications today.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with Page Unload Beaconing
&lt;/h2&gt;

&lt;p&gt;Web developers often need to send critical data back to servers when users leave a page. Analytics services, performance metrics, and user interaction tracking all rely on this capability. Traditionally, developers have used a combination of approaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Listening for &lt;code&gt;beforeunload&lt;/code&gt;, &lt;code&gt;pagehide&lt;/code&gt;, or &lt;code&gt;visibilitychange&lt;/code&gt; events&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;navigator.sendBeacon()&lt;/code&gt; or &lt;code&gt;fetch()&lt;/code&gt; with the &lt;code&gt;keepalive&lt;/code&gt; option&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, these methods face reliability issues, especially on mobile devices where events may not fire consistently. Even with the best practices, developers could only achieve around 82% reliability for unload beaconing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter fetchLater()
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;fetchLater()&lt;/code&gt; API provides a cleaner, more reliable solution. It allows you to queue up requests that will be sent either:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When the page is unloaded (tab closed, navigation away, etc.)&lt;/li&gt;
&lt;li&gt;After a specified timeout&lt;/li&gt;
&lt;li&gt;When the browser decides it's time to send it&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Basic Usage
&lt;/h2&gt;

&lt;p&gt;The API syntax is designed to feel familiar to developers who use &lt;code&gt;fetch()&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="c1"&gt;// Basic usage - will send when page unloads&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetchLater&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/analytics-endpoint&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;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;body&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="na"&gt;sessionData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;collectSessionData&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;// Check if the request has been sent&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="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;activated&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// false initially, true after sending&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding a Timeout
&lt;/h2&gt;

&lt;p&gt;You can specify an &lt;code&gt;activateAfter&lt;/code&gt; option (in milliseconds) to ensure the request is sent after a certain time, even if the page hasn't been unloaded:&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;// Send after 1 minute OR when page unloads (whichever comes first)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;oneMinute&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;fetchLater&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/analytics-endpoint&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;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;body&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="na"&gt;sessionData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;collectSessionData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;activateAfter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;oneMinute&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Updating Data Before Sending
&lt;/h2&gt;

&lt;p&gt;One of the most powerful features is the ability to update the queued request before it's sent. This is perfect for analytics that accumulate data over time:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;analyticsData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;pageViews&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="na"&gt;interactions&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;controller&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;AbortController&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;fetchLaterResult&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;queueAnalyticsBeacon&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Abort any existing request&lt;/span&gt;
  &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;controller&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;AbortController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Queue a new request with the latest data&lt;/span&gt;
  &lt;span class="nx"&gt;fetchLaterResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetchLater&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/analytics-endpoint&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;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&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;analyticsData&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;activateAfter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="c1"&gt;// 1 hour&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Initial queue&lt;/span&gt;
&lt;span class="nf"&gt;queueAnalyticsBeacon&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Update when user interacts&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;recordInteraction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;interactionType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;analyticsData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interactions&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="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;interactionType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;timestamp&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="c1"&gt;// Update the queued beacon&lt;/span&gt;
  &lt;span class="nf"&gt;queueAnalyticsBeacon&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;
  
  
  Real-World Example: Web Vitals Reporting
&lt;/h2&gt;

&lt;p&gt;Here's how you might use &lt;code&gt;fetchLater()&lt;/code&gt; to send Core Web Vitals data:&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;onCLS&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="nx"&gt;onLCP&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&lt;/span&gt;&lt;span class="dl"&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;metrics&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;Set&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;controller&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;fetchLaterResult&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;updateMetrics&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="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Clear already-sent metrics if request was activated&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;fetchLaterResult&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;activated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Add the new/updated metric&lt;/span&gt;
  &lt;span class="nx"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&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="c1"&gt;// Prepare the data payload&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&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="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="c1"&gt;// Abort any existing fetchLater() and queue a new one&lt;/span&gt;
  &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;controller&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;AbortController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;fetchLaterResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetchLater&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/vitals-analytics&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;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;activateAfter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="c1"&gt;// 1 hour timeout for regular sending&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Register the web vitals callbacks&lt;/span&gt;
&lt;span class="nf"&gt;onCLS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updateMetrics&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;updateMetrics&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;onLCP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updateMetrics&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Error Handling
&lt;/h2&gt;

&lt;p&gt;It's good practice to handle potential errors, especially quota limitations:&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;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fetchLater&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/analytics-endpoint&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;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&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;analyticsData&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="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;e&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;QuotaExceededError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Handle quota exceeded&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;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Analytics beacon quota exceeded&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Handle other errors&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error queueing analytics beacon:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&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;
  
  
  Understanding Quotas and Limitations
&lt;/h2&gt;

&lt;p&gt;To prevent abuse, browsers enforce limits on &lt;code&gt;fetchLater()&lt;/code&gt; usage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Total bandwidth for a top-level document is capped at 640KB&lt;/li&gt;
&lt;li&gt;Each reporting origin is limited to 64KB&lt;/li&gt;
&lt;li&gt;All pending requests are flushed when a document enters the browser's back/forward cache&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Browser Support
&lt;/h2&gt;

&lt;p&gt;As of May 2025:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chrome: Supported since version 135 (April 2025)&lt;/li&gt;
&lt;li&gt;Firefox: Under consideration&lt;/li&gt;
&lt;li&gt;Safari: Not yet implemented&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For browsers that don't support &lt;code&gt;fetchLater()&lt;/code&gt;, you can implement a fallback using the traditional approach:&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sendAnalytics&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetchLater&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;function&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="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;fetchLater&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/analytics&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;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;body&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;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;return&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="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&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;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetchLater failed, falling back to sendBeacon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&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;// Fallback to sendBeacon&lt;/span&gt;
  &lt;span class="k"&gt;return&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;/analytics&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;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Register traditional unload handlers as fallback&lt;/span&gt;
&lt;span class="nb"&gt;window&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;pagehide&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;sendAnalytics&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;analyticsData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nb"&gt;window&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;visibilitychange&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="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="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;visibilityState&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hidden&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="nf"&gt;sendAnalytics&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;analyticsData&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;
  
  
  Demo
&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%2Fd1ngc1pqp389o6k87zwb.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%2Fd1ngc1pqp389o6k87zwb.png" alt=" " width="800" height="703"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have built a simple Demo page for the fetchLater API here: &lt;a href="https://www.undefinednull.com/fetch-later-demo/" rel="noopener noreferrer"&gt;https://www.undefinednull.com/fetch-later-demo/&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;The &lt;code&gt;fetchLater()&lt;/code&gt; API represents a significant improvement for web developers who need reliable beaconing. It simplifies code, improves reliability, and provides a more declarative approach to handling page unload data transmission.&lt;/p&gt;

&lt;p&gt;By adopting this API (with appropriate fallbacks), developers can ensure their analytics, metrics, and other critical data have the best chance of making it back to servers, regardless of how users exit their web applications.&lt;/p&gt;

&lt;p&gt;For more details, check the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/fetchLater_API" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; and consider experimenting with the API in your applications today.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Harnessing AI to Debug and Optimize Web Performance: A Guide to Chrome DevTools AI Assistance</title>
      <dc:creator>Shidhin</dc:creator>
      <pubDate>Mon, 28 Apr 2025 16:21:09 +0000</pubDate>
      <link>https://dev.to/shidhincr/harnessing-ai-to-debug-and-optimize-web-performance-a-guide-to-chrome-devtools-ai-assistance-5h1p</link>
      <guid>https://dev.to/shidhincr/harnessing-ai-to-debug-and-optimize-web-performance-a-guide-to-chrome-devtools-ai-assistance-5h1p</guid>
      <description>&lt;p&gt;In the ever-evolving landscape of web development, staying on top of performance issues and debugging challenges can be time-consuming and complex. Google Chrome has introduced an exciting experimental feature in DevTools that can transform how developers approach these tasks: AI assistance. This powerful addition brings the capabilities of Google's Gemini AI directly into your development workflow, helping you understand, debug, and optimize your web applications more efficiently.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Chrome DevTools AI Assistance?
&lt;/h2&gt;

&lt;p&gt;AI assistance in Chrome DevTools is an experimental feature available in Chrome Canary (version 131 and later) that integrates Gemini AI directly into your browser's development environment. Instead of spending hours deciphering cryptic error messages or manually analyzing performance bottlenecks, you can now chat with an AI assistant that has context about your webpage and can provide targeted insights and solutions.&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.amazonaws.com%2Fuploads%2Farticles%2Fbglmvdiptf59k7k8k7vo.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%2Fbglmvdiptf59k7k8k7vo.png" alt="AI Assistance" width="800" height="208"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The AI assistant can help with various aspects of web development:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Styling analysis&lt;/strong&gt;: Understand why elements are displayed in specific ways and how they interact with each other&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network request debugging&lt;/strong&gt;: Analyze the origin, timing, and potential issues with network requests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Source code examination&lt;/strong&gt;: Get insights into the purpose and functionality of loaded files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance optimization&lt;/strong&gt;: Identify and address performance bottlenecks in your application&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started with AI Assistance
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Requirements
&lt;/h3&gt;

&lt;p&gt;Before diving in, ensure you meet these requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're at least 18 years old and in a supported location&lt;/li&gt;
&lt;li&gt;You're using the latest version of Chrome (Canary for full feature access)&lt;/li&gt;
&lt;li&gt;You're signed into Chrome with your Google account&lt;/li&gt;
&lt;li&gt;You have English (US) selected in DevTools settings&lt;/li&gt;
&lt;li&gt;You've enabled AI Innovations in DevTools settings&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Opening the AI Assistance Panel
&lt;/h3&gt;

&lt;p&gt;There are several ways to access the AI assistance panel:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;From specific panels&lt;/strong&gt;: Right-click on an element, network request, or performance activity and select "Ask AI"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Using the Command Menu&lt;/strong&gt;: Press Ctrl+Shift+P (or Cmd+Shift+P on Mac), type "AI", and select "Show AI assistance"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;From the More Tools menu&lt;/strong&gt;: Click on More options (⋮) &amp;gt; More tools &amp;gt; AI assistance&lt;/li&gt;
&lt;/ol&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%2F5qgjtf87ko476c8gflvp.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%2F5qgjtf87ko476c8gflvp.png" alt=" " width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Use AI Assistance for Debugging and Optimization
&lt;/h2&gt;

&lt;p&gt;Let's explore how to leverage this powerful feature for different aspects of web development:&lt;/p&gt;

&lt;h3&gt;
  
  
  Debugging CSS and Styling Issues
&lt;/h3&gt;

&lt;p&gt;When confronting styling challenges, AI assistance can be a game-changer:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open your webpage in Chrome&lt;/li&gt;
&lt;li&gt;Right-click on the problematic element in the Elements panel&lt;/li&gt;
&lt;li&gt;Select "Ask AI" from the context menu&lt;/li&gt;
&lt;li&gt;Ask questions like:

&lt;ul&gt;
&lt;li&gt;"Why is this element overlapping with the header?"&lt;/li&gt;
&lt;li&gt;"How can I fix the responsive behavior of this component?"&lt;/li&gt;
&lt;li&gt;"Why isn't my flexbox layout working as expected?"&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&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%2Ff2ue686erfoxmjlfi1jc.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%2Ff2ue686erfoxmjlfi1jc.png" alt=" " width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The AI will analyze the context, including CSS inheritance, conflicting styles, and layout interactions, providing explanations and potential solutions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimizing Network Performance
&lt;/h3&gt;

&lt;p&gt;For network-related issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to the Network panel in DevTools&lt;/li&gt;
&lt;li&gt;Record network activity while loading your page&lt;/li&gt;
&lt;li&gt;Right-click on a slow or problematic request&lt;/li&gt;
&lt;li&gt;Select "Ask AI"&lt;/li&gt;
&lt;li&gt;Ask specific questions like:

&lt;ul&gt;
&lt;li&gt;"Why is this request taking so long?"&lt;/li&gt;
&lt;li&gt;"How can I optimize this API call?"&lt;/li&gt;
&lt;li&gt;"What's causing these multiple similar requests?"&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&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%2Fgshvaie5qol6xl51dmx4.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%2Fgshvaie5qol6xl51dmx4.png" alt=" " width="658" height="657"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The AI will analyze request headers, timing, and the request initiator chain to give you insights and optimization suggestions.&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.amazonaws.com%2Fuploads%2Farticles%2Fsc5znndtyiuno6ha7il1.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%2Fsc5znndtyiuno6ha7il1.png" alt=" " width="750" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Analyzing Runtime Performance
&lt;/h3&gt;

&lt;p&gt;Performance bottlenecks can be particularly challenging to identify. Here's how AI assistance can help:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the Performance panel&lt;/li&gt;
&lt;li&gt;Record a performance profile while interacting with your site&lt;/li&gt;
&lt;li&gt;Right-click on activities that appear to be problematic&lt;/li&gt;
&lt;li&gt;Select "Ask AI"&lt;/li&gt;
&lt;li&gt;Ask questions like:

&lt;ul&gt;
&lt;li&gt;"What's causing this long task?"&lt;/li&gt;
&lt;li&gt;"How can I reduce the time spent on JavaScript execution?"&lt;/li&gt;
&lt;li&gt;"Why are there so many layout recalculations?"&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&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%2Fdbhwr1q1zzysqiq4vu8o.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%2Fdbhwr1q1zzysqiq4vu8o.png" alt=" " width="800" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The AI analyzes the call tree and timings to identify optimization opportunities and explain the root causes of performance issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examining Source Code
&lt;/h3&gt;

&lt;p&gt;Understanding unfamiliar code is much easier with AI assistance:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to the Sources panel&lt;/li&gt;
&lt;li&gt;Open the file you want to understand&lt;/li&gt;
&lt;li&gt;Right-click on specific sections of code&lt;/li&gt;
&lt;li&gt;Ask the AI questions like:

&lt;ul&gt;
&lt;li&gt;"What is this function doing?"&lt;/li&gt;
&lt;li&gt;"How does this code affect the page rendering?"&lt;/li&gt;
&lt;li&gt;"What could be improved in this code segment?"&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&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%2F8aeeqymoq8sk2e9oop62.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%2F8aeeqymoq8sk2e9oop62.png" alt=" " width="789" height="854"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for Effective AI Assistance
&lt;/h2&gt;

&lt;p&gt;To get the most out of Chrome DevTools AI assistance, consider these tips:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Ask Specific Questions
&lt;/h3&gt;

&lt;p&gt;The more specific your questions, the more targeted and useful the AI's responses will be. Instead of asking "Why is my page slow?" try "What's causing the long task at the 2-second mark in my performance profile?"&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Provide Context
&lt;/h3&gt;

&lt;p&gt;Ensure you've selected the relevant element, request, or performance activity before asking questions. The AI uses this context to provide accurate answers.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Follow Up with Clarifications
&lt;/h3&gt;

&lt;p&gt;If the initial answer doesn't fully address your question, ask follow-up questions to drill deeper. The AI maintains conversation history and builds on previous interactions.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Combine AI Insights with Your Expertise
&lt;/h3&gt;

&lt;p&gt;AI assistance is a powerful tool, but it works best when combined with your development knowledge. Use AI suggestions as a starting point, then apply your understanding of your specific codebase and requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Provide Feedback
&lt;/h3&gt;

&lt;p&gt;Since this is an experimental feature, your feedback is valuable. Use the thumbs up/down buttons to rate answers and help improve the system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Optimization Scenarios
&lt;/h2&gt;

&lt;p&gt;Let's explore some practical scenarios where AI assistance can significantly streamline your workflow in the future:&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario 1: Fixing Layout Shifts
&lt;/h3&gt;

&lt;p&gt;Cumulative Layout Shift (CLS) issues can be frustrating for users. AI assistance can help pinpoint the cause:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Record a performance profile capturing the layout shift&lt;/li&gt;
&lt;li&gt;Right-click on the relevant layout recalculation activity&lt;/li&gt;
&lt;li&gt;Ask: "What's causing this layout shift and how can I fix it?"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The AI might identify that images without defined dimensions are causing the shift and suggest adding width and height attributes to prevent the browser from recalculating layout during image loading.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario 2: Reducing JavaScript Bundle Size
&lt;/h3&gt;

&lt;p&gt;If your page load time is slow due to large JavaScript bundles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use the Coverage panel to identify unused JavaScript&lt;/li&gt;
&lt;li&gt;Right-click on a specific JavaScript file with low usage&lt;/li&gt;
&lt;li&gt;Ask: "How can I optimize this JavaScript to reduce bundle size?"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The AI might suggest techniques like code splitting, tree shaking, or lazy loading specific components.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario 3: Optimizing Render Blocking Resources
&lt;/h3&gt;

&lt;p&gt;For pages with render-blocking resources:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Network panel, right-click on a render-blocking CSS or JavaScript file&lt;/li&gt;
&lt;li&gt;Ask: "How can I prevent this resource from blocking rendering?"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The AI could recommend using &lt;code&gt;async&lt;/code&gt; or &lt;code&gt;defer&lt;/code&gt; attributes for scripts, inlining critical CSS, or using resource hints like &lt;code&gt;preload&lt;/code&gt; and &lt;code&gt;preconnect&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations and Considerations
&lt;/h2&gt;

&lt;p&gt;While the AI assistance feature is powerful, it's important to be aware of its limitations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Experimental Status&lt;/strong&gt;: As an experimental feature, it may not always provide perfect answers and is subject to change.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data Usage&lt;/strong&gt;: The feature sends contextual data about your webpage to Google's servers for analysis. Sensitive information in headers is automatically redacted, but be cautious with proprietary code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Potential Inaccuracies&lt;/strong&gt;: Like all AI systems, it may occasionally generate incorrect or misleading information. Always verify critical suggestions before implementation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Language Limitations&lt;/strong&gt;: Currently, the feature is optimized for English (US) and may not work as effectively in other languages.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Chrome DevTools AI assistance represents a significant leap forward in how developers can approach debugging and performance optimization. By bringing AI capabilities directly into the browser development environment, it helps bridge the gap between identifying problems and implementing solutions.&lt;/p&gt;

&lt;p&gt;As web applications grow increasingly complex, tools that can analyze and explain intricate interactions become invaluable. AI assistance in Chrome DevTools doesn't replace developer expertise, but it does augment it in powerful ways, helping you work more efficiently and make informed decisions about optimizing your web applications.&lt;/p&gt;

&lt;p&gt;While still experimental, this feature offers a glimpse into the future of development tools where AI partners with developers to solve challenges and create better web experiences. As you incorporate AI assistance into your workflow, remember to provide feedback to help improve the system and shape the future of AI-powered development tools.&lt;/p&gt;

&lt;p&gt;Start exploring this powerful feature in Chrome Canary today, and experience a new dimension of productivity in your web development process.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Inspecting Speculation rules with Chrome Devtools</title>
      <dc:creator>Shidhin</dc:creator>
      <pubDate>Thu, 20 Mar 2025 16:29:40 +0000</pubDate>
      <link>https://dev.to/shidhincr/inspecting-speculation-rules-with-chrome-devtools-29c9</link>
      <guid>https://dev.to/shidhincr/inspecting-speculation-rules-with-chrome-devtools-29c9</guid>
      <description>&lt;p&gt;[WIP]&lt;/p&gt;

&lt;p&gt;Come back later ...&lt;/p&gt;

</description>
      <category>tooling</category>
    </item>
    <item>
      <title>Faster navigations with Speculations rules api</title>
      <dc:creator>Shidhin</dc:creator>
      <pubDate>Mon, 10 Mar 2025 17:49:40 +0000</pubDate>
      <link>https://dev.to/shidhincr/faster-navigations-with-speculations-rules-api-48n3</link>
      <guid>https://dev.to/shidhincr/faster-navigations-with-speculations-rules-api-48n3</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/shidhincr" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F114922%2F41d6e8ce-a9c5-4f6e-9ce8-97a4dbb9cadb.jpeg" alt="shidhincr"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/shidhincr/speculation-rules-api-a-new-era-of-faster-web-browsing-5hhk" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Speculation Rules API: A New Era of Faster Web Browsing&lt;/h2&gt;
      &lt;h3&gt;Shidhin ・ Mar 9 '25&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#speculationrulesapi&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#instantnavigation&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#prefetchprerender&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webperf&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>speculationrulesapi</category>
      <category>instantnavigation</category>
      <category>prefetchprerender</category>
      <category>webperf</category>
    </item>
    <item>
      <title>Speculation Rules API: A New Era of Faster Web Browsing</title>
      <dc:creator>Shidhin</dc:creator>
      <pubDate>Sun, 09 Mar 2025 13:22:19 +0000</pubDate>
      <link>https://dev.to/shidhincr/speculation-rules-api-a-new-era-of-faster-web-browsing-5hhk</link>
      <guid>https://dev.to/shidhincr/speculation-rules-api-a-new-era-of-faster-web-browsing-5hhk</guid>
      <description>&lt;p&gt;Imagine using the internet and seeing web pages load immediately, almost like magic. No more waiting or loading screens. This exciting idea is now possible thanks to a new feature called speculation rules. In this blog, we'll learn what speculation rules are, how they work, and see some practical examples you can use in your own projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Speculation rules API
&lt;/h2&gt;

&lt;p&gt;The Speculation rules API is a new web api to improve the navigation speed in multi-page applications. It basically prefetch or prerender the desired pages upon user-interaction or after pageload. By doing prefetching or prerendering, the navigation speed between multiple pages will be significantly reduced. &lt;/p&gt;

&lt;p&gt;Speculation rules give your browser hints about what pages to load next. Imagine hovering over a link, and the browser already starts loading that page in the background, even before you click. This dramatically speeds up browsing and removes frustrating waiting times.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does it work?
&lt;/h2&gt;

&lt;p&gt;With speculation rules, browsers can to predict (speculate) which page you're likely to visit next to enhance your experience. This prediction is based on factors like where your mouse is hovering or the links present on the current page. By anticipating your next move, the browser can load pages more efficiently, reducing wait times.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prefetching vs. Prerendering&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are two primary methods browsers use to prepare the next page:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prefetching&lt;/strong&gt;: This approach involves the browser downloading the basic blueprint of the page—the HTML content—but not rendering it. It's a lighter method that uses fewer resources, ensuring that when you navigate to the page, it loads faster than if it hadn't been prefetched.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prerendering&lt;/strong&gt;: In this method, the browser goes a step further by downloading all resources, such as images and fonts, and fully rendering the page in a hidden tab. This means that when you click the link, the page appears instantly, providing a seamless experience. However, prerendering consumes more resources compared to prefetching.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Setting the Rules with JSON&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Website developers can guide browsers on which pages to prefetch or prerender using the Speculation Rules API, defined in JSON format. This code can be embedded directly into the webpage or delivered via HTTP headers from the web server. The JSON structure specifies the URLs to target and the conditions under which the browser should act. For instance, developers can set the "eagerness" parameter to control how proactively the browser should prefetch or prerender pages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;immediate&lt;/strong&gt;: The browser starts prefetching or prerendering as soon as it encounters the rule.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;eager&lt;/strong&gt;: Similar to immediate, but may be adjusted in future implementations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;moderate&lt;/strong&gt;: The browser waits until there's a reasonable indication, such as a brief hover over a link, before acting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;conservative&lt;/strong&gt;: The browser waits until you actually click or tap on a link before initiating the prefetch or prerender.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By fine-tuning these settings, developers can optimize resource usage and enhance user experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example of Speculation Rules in JSON&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's how developers can define speculation rules using JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"speculationrules"&lt;/span&gt;&lt;span class="nt"&gt;&amp;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;prerender&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;where&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href_matches&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;/*&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;eagerness&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;moderate&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prefetch&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;urls&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next.html&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;next2.html&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;requires&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;anonymous-client-ip-when-cross-origin&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;referrer_policy&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;no-referrer&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;prerender&lt;/strong&gt; rule instructs the browser to prerender any same-origin link on the page upon hover, with a moderate eagerness setting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;prefetch&lt;/strong&gt; rule tells the browser to prefetch "next.html" and "next2.html", requires anonymization for cross-origin requests, and sets the referrer policy to "no-referrer".&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By implementing these rules, developers can significantly improve page load times and provide a smoother browsing experience for users.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about the existing &lt;code&gt;&amp;lt;link preload&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;link prefetch&amp;gt;&lt;/code&gt; and
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;link prerender&amp;gt;&lt;/code&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fu2mmjw334rky9cy70e96.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%2Fu2mmjw334rky9cy70e96.png" alt=" " width="719" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Speculation Rules API introduces a more advanced and flexible approach to resource loading, enhancing the capabilities of traditional methods like &lt;code&gt;&amp;lt;link rel="preload"&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;link rel="prefetch"&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;link rel="prerender"&amp;gt;&lt;/code&gt;. Here's how it improves upon these older mechanisms:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;link rel="preload"&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: &lt;code&gt;&amp;lt;link rel="preload"&amp;gt;&lt;/code&gt; is utilized to load resources essential for the current page, such as fonts, images, and scripts, ensuring they're available when needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Limitation&lt;/strong&gt;: It focuses solely on the current page's resources and doesn't anticipate the user's next navigation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Speculation Rules Advantage&lt;/strong&gt;: The Speculation Rules API extends this concept by allowing developers to specify resources for subsequent pages the user is likely to visit, enhancing the overall navigation experience.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;link rel="prefetch"&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Functionality&lt;/strong&gt;: The traditional &lt;code&gt;&amp;lt;link rel="prefetch"&amp;gt;&lt;/code&gt; hint allows browsers to prefetch resources to the HTTP cache, potentially improving load times for future navigations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Challenges&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cache-Control Limitations&lt;/strong&gt;: Prefetched resources can be blocked by &lt;code&gt;Cache-Control&lt;/code&gt; headers, limiting their effectiveness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Site Restrictions&lt;/strong&gt;: Cross-site prefetching is often restricted due to security and privacy concerns.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Speculation Rules Enhancement&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;In-Memory Caching&lt;/strong&gt;: Speculation Rules utilize a per-document in-memory cache, ensuring prefetched documents are processed similarly to regular navigations but aren't rendered until needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Site Prefetching&lt;/strong&gt;: This API supports cross-site prefetching, offering more flexibility compared to the older &lt;code&gt;&amp;lt;link rel="prefetch"&amp;gt;&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bypassing Cache-Control&lt;/strong&gt;: Speculation Rules are not hindered by &lt;code&gt;Cache-Control&lt;/code&gt; headers, making them more reliable for prefetching purposes.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;link rel="prerender"&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Background&lt;/strong&gt;: The legacy &lt;code&gt;&amp;lt;link rel="prerender"&amp;gt;&lt;/code&gt; was deprecated in favor of NoState Prefetch, which fetched resources without fully rendering the page or executing JavaScript.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Speculation Rules Superiority&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Full Prerendering&lt;/strong&gt;: The Speculation Rules API enables developers to trigger complete prerendering of pages, including the execution of JavaScript and loading of subresources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Performance&lt;/strong&gt;: This comprehensive prerendering ensures that when a user navigates to the prerendered page, it loads instantly, providing a seamless experience.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Speculation Rules API Overview&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Target Audience&lt;/strong&gt;: The API is particularly beneficial for multi-page applications (MPAs), allowing developers to specify which documents should be prefetched or prerendered based on user behavior and site structure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Expressive Syntax&lt;/strong&gt;: It offers a more configurable and expressive syntax, enabling precise control over resource loading strategies to optimize performance.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By leveraging the Speculation Rules API, developers can implement more efficient and user-centric resource loading strategies, surpassing the capabilities of traditional methods like &lt;code&gt;&amp;lt;link rel="preload"&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;link rel="prefetch"&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;link rel="prerender"&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;The Speculation Rules API offers a structured approach to enhance web performance by enabling browsers to anticipate and load resources for pages users are likely to visit next. This proactive loading can significantly reduce perceived load times and improve user experience. Here's how to implement speculation rules in your HTML:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Embedding a &lt;code&gt;&amp;lt;script type="speculationrules"&amp;gt;&lt;/code&gt; Element&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To define speculation rules, you embed a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; element with the attribute &lt;code&gt;type="speculationrules"&lt;/code&gt; directly within your HTML document. This script contains JSON-formatted rules that instruct the browser on prefetching or prerendering behaviors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Speculation Rules Example&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"speculationrules"&lt;/span&gt;&lt;span class="nt"&gt;&amp;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;prerender&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;source&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;list&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;urls&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/next-page.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;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Welcome to My Website&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/next-page.html"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Go to Next Page&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the browser is instructed to prerender &lt;code&gt;/next-page.html&lt;/code&gt;, preparing it in the background so that navigation to it is instantaneous.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Defining Rules in JSON Format&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Within the &lt;code&gt;&amp;lt;script type="speculationrules"&amp;gt;&lt;/code&gt; element, rules are defined using JSON. Each rule specifies the action (&lt;code&gt;prefetch&lt;/code&gt; or &lt;code&gt;prerender&lt;/code&gt;), the source of the URLs, and the list of URLs to be processed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prefetch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"list"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"urls"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"/about.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/contact.html"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prerender"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"list"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"urls"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"/dashboard.html"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the browser is instructed to prefetch &lt;code&gt;/about.html&lt;/code&gt; and &lt;code&gt;/contact.html&lt;/code&gt;, and to prerender &lt;code&gt;/dashboard.html&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Specifying Pages to Prefetch or Prerender&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;urls&lt;/code&gt; array within each rule specifies which pages the browser should prefetch or prerender. These URLs should be chosen based on user navigation patterns to optimize performance effectively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Setting Conditions for Triggering Prefetching or Prerendering&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Developers can control when prefetching or prerendering occurs by setting the &lt;code&gt;eagerness&lt;/code&gt; property within each rule. This property determines how proactively the browser should load the specified resources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Eagerness Levels:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;immediate&lt;/strong&gt;: The browser starts prefetching or prerendering as soon as it processes the rule.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;eager&lt;/strong&gt;: Similar to &lt;code&gt;immediate&lt;/code&gt;, but allows the browser some discretion based on resource availability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;moderate&lt;/strong&gt;: The browser waits until there's a reasonable indication of user interest, such as hovering over a link.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;conservative&lt;/strong&gt;: The browser waits until the user initiates navigation, such as clicking a link.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example with Eagerness Setting:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"speculationrules"&lt;/span&gt;&lt;span class="nt"&gt;&amp;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;prerender&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;source&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;list&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;urls&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/promo.html&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;eagerness&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;moderate&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, the browser will prerender &lt;code&gt;/promo.html&lt;/code&gt; when it detects moderate user interest, such as a brief hover over a related link.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Additional Considerations:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Source Specification&lt;/strong&gt;: The &lt;code&gt;source&lt;/code&gt; property indicates how the URLs are determined. For instance, &lt;code&gt;"source": "list"&lt;/code&gt; means the URLs are explicitly listed, while other methods can derive URLs based on patterns or user behavior.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Browser Support&lt;/strong&gt;: As of now, the Speculation Rules API is supported in Chromium-based browsers like Chrome, Edge, and Opera. It's advisable to implement fallback mechanisms for browsers that do not support this API.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By thoughtfully implementing the Speculation Rules API, developers can significantly enhance the responsiveness of their websites, leading to a smoother and more engaging user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about the Browser Support
&lt;/h2&gt;

&lt;p&gt;As of now, the Speculation Rules API is supported in Chromium-based browsers, including Chrome, Edge, and Opera. However, it is not yet available in Firefox or Safari. Despite this limited support, implementing the Speculation Rules API is safe because browsers that do not recognize it will simply ignore the &lt;code&gt;&amp;lt;script type="speculationrules"&amp;gt;&lt;/code&gt; element without causing any issues.​&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Supported Browsers: Chrome, Edge, Opera (Chromium-based browsers).​
Unsupported Browsers: Firefox, Safari.​&lt;/li&gt;
&lt;li&gt;Market Coverage: Chromium-based browsers account for approximately 70% of the global browser market. ​&lt;/li&gt;
&lt;li&gt;Backward Compatibility: Non-supporting browsers will ignore the Speculation Rules API without any adverse effects. ​&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Debugging in Chrome browser
&lt;/h2&gt;

&lt;p&gt;To debug Speculation Rules in Chrome, use Chrome DevTools.&lt;/p&gt;

&lt;p&gt;Here’s how:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Open DevTools:&lt;/strong&gt; Open Chrome DevTools before loading the page containing the speculation rules. This ensures speculations are captured correctly.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Navigate to the Speculative Loads Tab:&lt;/strong&gt; Go to the &lt;strong&gt;Application&lt;/strong&gt; panel, then &lt;strong&gt;Background Services&lt;/strong&gt;, and select the &lt;strong&gt;Speculative loads&lt;/strong&gt; tab. Then choose the &lt;strong&gt;Speculations pane&lt;/strong&gt;. If nothing appears, ensure you're on the correct page and DevTools was loaded before navigation; reload the page if necessary.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Inspect Speculations:&lt;/strong&gt; In the Speculations tab, you can view the URLs being prefetched or prerendered. Click on a line to see details if a page fails to prerender, including reasons for failure, such as incompatible JavaScript APIs.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Check Speculative Loading Status:&lt;/strong&gt; To confirm whether a page was prerendered or prefetched, inspect the Application panel to see the &lt;strong&gt;Speculative loading status&lt;/strong&gt; for the current page.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Monitor Network Activity:&lt;/strong&gt; The &lt;strong&gt;Network track&lt;/strong&gt; in the &lt;strong&gt;Performance Panel&lt;/strong&gt; shows network activity related to prerendered resources without switching DevTools context.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Sort by Status:&lt;/strong&gt; Sort the Speculations pane by the &lt;strong&gt;Status&lt;/strong&gt; column to identify pages that are prerendering as you hover over them. Clicking on them will show a quicker Largest Contentful Paint (LCP) time compared to non-prerendered pages.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Examine Chrome's Address Bar Predictions:&lt;/strong&gt; To view Chrome's predictions for URLs, go to the &lt;code&gt;chrome://predictors&lt;/code&gt; page. Green lines indicate sufficient confidence to trigger prerendering.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Use the Console to Test Prerendering:&lt;/strong&gt; After a page is activated, open DevTools and type &lt;code&gt;performance.getEntriesByType('navigation').activationStart&lt;/code&gt; in the console. A non-zero value indicates the page was prerendered.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Simulate Different Network Conditions:&lt;/strong&gt; Use the throttling options in the Network tab to simulate different network speeds and see how speculation rules perform under various conditions.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Feature Detection&lt;/strong&gt; Use feature detection code to determine if the browser supports speculation rules. If the browser doesn't support speculation rules, implement older technologies such as &lt;code&gt;&amp;lt;link rel="prefetch"&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&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%2Ftoxhqxhwg8lkeyop6u9b.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%2Ftoxhqxhwg8lkeyop6u9b.png" alt=" " width="800" height="817"&gt;&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fpepiho9rqcgk8uvx0bcy.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%2Fpepiho9rqcgk8uvx0bcy.png" alt=" " width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Applications of the Speculation Rules API
&lt;/h2&gt;

&lt;p&gt;E-commerce platforms greatly benefit from the Speculation Rules API. On these platforms, users regularly browse through various product pages, category listings, and search results. By applying prefetching or prerendering to these pages, the shopping experience becomes smoother and quicker. This immediate responsiveness not only improves customer satisfaction but can also lead to higher conversion rates, as shoppers are less likely to abandon the site due to slow loading times.&lt;/p&gt;

&lt;p&gt;Blogs featuring multiple articles or content spread across multiple pages can similarly enhance user experience using this API. By prefetching or prerendering subsequent articles or pagination pages, readers experience seamless navigation. This approach encourages users to explore more content effortlessly, significantly improving their engagement and satisfaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advantages of Implementing Speculation Rules API
&lt;/h2&gt;

&lt;p&gt;A key advantage of using the Speculation Rules API is significantly reducing the perceived load times by preloading resources in advance. Prefetching resources or fully prerendering pages enables nearly instantaneous page transitions when navigating through the website, creating a smoother, more responsive browsing experience. Such improvements are crucial for retaining user interest and increasing their satisfaction.&lt;/p&gt;

&lt;p&gt;Enhanced performance resulting from prefetching and prerendering also has positive effects on user engagement metrics, such as reduced bounce rates and prolonged sessions. The smoother and more responsive user experience encourages visitors to explore additional content, increasing the likelihood of conversions and repeat visits. Additionally, these improvements in page performance can positively impact search engine optimization (SEO), helping websites rank better in search results.&lt;/p&gt;

&lt;p&gt;The Speculation Rules API also ensures efficient use of resources by allowing browsers to initiate prefetching only when sufficient resources, such as memory and network bandwidth, are available. Developers can fine-tune when resources are preloaded using eagerness settings (immediate, eager, moderate, conservative), ensuring effective utilization without wasteful preloading.&lt;/p&gt;

&lt;p&gt;Moreover, improvements in caching mechanisms mean that prefetched or prerendered resources are stored efficiently and reused when required. Even if speculated pages are not immediately accessed, these resources provide future benefits, further improving overall site performance and responsiveness.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Considerations for Implementing Speculation Rules API
&lt;/h2&gt;

&lt;p&gt;When implementing the Speculation Rules API, it's important to understand both the API and your website's specific needs. Ensure you avoid applying rules to sensitive routes such as logout, language-switching, or shopping cart actions to prevent unintended consequences.&lt;/p&gt;

&lt;p&gt;Regularly monitoring and adjusting your preloading rules is crucial. Analyze user behavior using tools like Google Analytics and Real User Monitoring (RUM) to identify optimal preloading strategies. Adjust rules based on insights to balance effective resource use with performance gains.&lt;/p&gt;

&lt;p&gt;Lastly, be aware of the potential increased server load due to prefetching and prerendering. This can impact server resources, bandwidth, and costs. Use caching wisely and update client-side scripts carefully, particularly for personalized content, to ensure optimal and efficient performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In summary, the Speculation Rules API is a powerful tool for enhancing web performance, primarily in multi-page applications (MPAs), by proactively prefetching or prerendering potential next pages. It allows the browser to start loading a subsequent page before a user even clicks a link, making navigation feel nearly instantaneous. By strategically implementing this API, developers can significantly improve user experience and potentially boost Core Web Vitals&lt;/p&gt;

</description>
      <category>speculationrulesapi</category>
      <category>instantnavigation</category>
      <category>prefetchprerender</category>
      <category>webperf</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Shidhin</dc:creator>
      <pubDate>Sun, 09 Mar 2025 13:08:02 +0000</pubDate>
      <link>https://dev.to/shidhincr/-1a3b</link>
      <guid>https://dev.to/shidhincr/-1a3b</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/shidhincr" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F114922%2F41d6e8ce-a9c5-4f6e-9ce8-97a4dbb9cadb.jpeg" alt="shidhincr"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/shidhincr/local-live-core-web-vital-metrics-in-the-devtools-2hlc" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Live core web vitals (local metrics) in browser devtools&lt;/h2&gt;
      &lt;h3&gt;Shidhin ・ Dec 22 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#devtools&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#corewebvitals&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#inp&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>devtools</category>
      <category>corewebvitals</category>
      <category>inp</category>
    </item>
    <item>
      <title>Core Web Vitals</title>
      <dc:creator>Shidhin</dc:creator>
      <pubDate>Sun, 09 Mar 2025 13:06:33 +0000</pubDate>
      <link>https://dev.to/shidhincr/-4998</link>
      <guid>https://dev.to/shidhincr/-4998</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/shidhincr" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F114922%2F41d6e8ce-a9c5-4f6e-9ce8-97a4dbb9cadb.jpeg" alt="shidhincr"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/shidhincr/perf-audit-namshis-mobile-website-using-live-core-web-vitals-1j3" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Performance Audit: Analyzing Namshi’s Mobile Website with Live Core Web Vitals&lt;/h2&gt;
      &lt;h3&gt;Shidhin ・ Dec 27 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#devtools&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#corewebvitals&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#performance&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>devtools</category>
      <category>corewebvitals</category>
      <category>performance</category>
    </item>
    <item>
      <title>Performance Audit: Analyzing Namshi’s Mobile Website with Live Core Web Vitals</title>
      <dc:creator>Shidhin</dc:creator>
      <pubDate>Fri, 27 Dec 2024 13:13:40 +0000</pubDate>
      <link>https://dev.to/shidhincr/perf-audit-namshis-mobile-website-using-live-core-web-vitals-1j3</link>
      <guid>https://dev.to/shidhincr/perf-audit-namshis-mobile-website-using-live-core-web-vitals-1j3</guid>
      <description>&lt;p&gt;If you’re new to Live Core Web Vitals, check out my previous post:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="/shidhincr" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F114922%2F41d6e8ce-a9c5-4f6e-9ce8-97a4dbb9cadb.jpeg" alt="shidhincr"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/shidhincr/local-live-core-web-vital-metrics-in-the-devtools-2hlc" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Live core web vitals (local metrics) in browser devtools&lt;/h2&gt;
      &lt;h3&gt;Shidhin ・ Dec 22 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#devtools&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#corewebvitals&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#inp&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  What Are We Going to Do?
&lt;/h2&gt;

&lt;p&gt;Namshi is one of the largest e-commerce websites in the UAE. Having worked at Namshi before, I was curious to test the Core Web Vitals scores of their mobile website and evaluate the user experience.&lt;/p&gt;

&lt;p&gt;I started with their most visited webpage:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.namshi.com/uae-en/fashion/women-fashion/" rel="noopener noreferrer"&gt;Namshi: Women's Fashion&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fpi5noscwo3aj26f9rbva.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%2Fpi5noscwo3aj26f9rbva.png" alt="Namshi web vitals" width="800" height="793"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using a high-speed Wi-Fi network and an M3 Pro MacBook, I conducted the test without any network or CPU throttling. The LCP (Largest Contentful Paint) score was 2.84 seconds, indicating room for improvement. The LCP metric primarily points to the banner image in the carousel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Suggestions for improvements:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use smaller placeholder images for banners.&lt;/li&gt;
&lt;li&gt;Preload banner images(using link preload directive).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As I interacted with the page, the other metrics appeared satisfactory.&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.amazonaws.com%2Fuploads%2Farticles%2Fs942kh1u6mj881w99q4j.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%2Fs942kh1u6mj881w99q4j.png" alt="Namshi web vitals" width="800" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding slowness
&lt;/h2&gt;

&lt;p&gt;Namshi’s website heavily relies on modal components for features like Sort, Filter, and Search. While most modals opened and closed quickly, I noticed occasional slowness patterns. The INP (Interaction to Next Paint) score fluctuated between 60-100ms, which is generally acceptable.&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.amazonaws.com%2Fuploads%2Farticles%2Fvkbnw1jkpzha64gypvxg.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%2Fvkbnw1jkpzha64gypvxg.png" alt="Namshi web vitals" width="800" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, I discovered main-thread blocking code when toggling the “New Arrivals” modal and attempting to close it. This directly impacted the INP score. You can see the behavior in the video below:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/prFrqpwH_TM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Worse Version?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, I found an even worse scenario where the INP score turned completely RED.&lt;/p&gt;

&lt;p&gt;This occurred when I opened the “Filter” modal, applied some filters, and then clicked “Reset Filters”. The page froze momentarily, resulting in a poor user experience.&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.amazonaws.com%2Fuploads%2Farticles%2Fhc2pzlrd9iwhzftjnzkc.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%2Fhc2pzlrd9iwhzftjnzkc.png" alt="Namshi web vitals" width="800" height="748"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Suggestions for improvements:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid blocking the main thread during user interactions, especially while applying filters.&lt;/li&gt;
&lt;li&gt;Use Web Workers for computationally intensive tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Another Observation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/PxdoNdmKlWo"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;By recording a Performance Profile, the issue was clearly visible in the flame chart. This method is invaluable for identifying and addressing performance bottlenecks.&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.amazonaws.com%2Fuploads%2Farticles%2F6cavs2y9hhsmykut0x9k.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%2F6cavs2y9hhsmykut0x9k.png" alt="Recording flame chart" width="592" height="1231"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>devtools</category>
      <category>corewebvitals</category>
      <category>performance</category>
    </item>
    <item>
      <title>Live core web vitals (local metrics) in browser devtools</title>
      <dc:creator>Shidhin</dc:creator>
      <pubDate>Sun, 22 Dec 2024 17:43:03 +0000</pubDate>
      <link>https://dev.to/shidhincr/local-live-core-web-vital-metrics-in-the-devtools-2hlc</link>
      <guid>https://dev.to/shidhincr/local-live-core-web-vital-metrics-in-the-devtools-2hlc</guid>
      <description>&lt;p&gt;Local metrics are the new addition to the performance panel in Chrome DevTools. They provide real-time data on the performance of your website, enabling you to monitor and analyze the website's performance metrics as you interact with it. This feature is really useful for developers who want to understand how their website performs in real-world scenarios and identify performance bottlenecks quickly.&lt;/p&gt;

&lt;p&gt;Local metrics also known as live metrics, include the following key performance indicators:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LCP (Largest Contentful Paint)&lt;/li&gt;
&lt;li&gt;CLS (Cumulative Layout Shift)&lt;/li&gt;
&lt;li&gt;INP (Interaction to next paint)&lt;/li&gt;
&lt;/ul&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%2Folvvqwko1dwepm637k58.jpg" 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%2Folvvqwko1dwepm637k58.jpg" alt=" " width="800" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What's the advantage of using local metrics?
&lt;/h3&gt;

&lt;p&gt;Local metrics provide real-time data on the website's performance, allowing you to monitor the performance metrics as you interact with the website. This avoids the need to deploy the website to a staging environment or use third-party tools to analyze the performance metrics. This also helps to catch performance issues early in the development process.&lt;/p&gt;

&lt;p&gt;Let's understand each section in the local metrics panel&lt;/p&gt;

&lt;h4&gt;
  
  
  LCP (Largest Contentful Paint)
&lt;/h4&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%2F7v7q1jkdsc4oyl19m6n0.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%2F7v7q1jkdsc4oyl19m6n0.png" alt=" " width="800" height="545"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Largest Contentful Paint (LCP) metric measures the time taken for the largest content element to render on the screen. It is an important metric as it indicates when the main content of the page is visible to the user. A good LCP score is usually less than 2.5 seconds.&lt;/p&gt;

&lt;p&gt;The LCP panel shows the following data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LCP value: The time taken for the largest content element to render on the screen.&lt;/li&gt;
&lt;li&gt;Element: The largest content element on the page. Here in the example, it is an image.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  CLS (Cumulative Layout Shift)
&lt;/h4&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%2Fwsaxdpc96fob37n2r2k5.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%2Fwsaxdpc96fob37n2r2k5.png" alt=" " width="800" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Cumulative Layout Shift (CLS) metric measures the visual stability of the page. It quantifies how much the elements on the page shift around during the loading process. A good CLS score is usually less than 0.1.&lt;/p&gt;

&lt;p&gt;The CLS panel shows the following data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CLS value: The cumulative layout shift value.&lt;/li&gt;
&lt;li&gt;Worst shifts: The elements that caused the maximum layout shift.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can click on the "Shifts" link to see the detailed information about the layout shifts on the page.&lt;br&gt;
These values are "Live" and will update as you interact with the page.&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.amazonaws.com%2Fuploads%2Farticles%2Fnc0lidvbppej9ethqppb.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%2Fnc0lidvbppej9ethqppb.png" alt=" " width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  INP (Interaction to next paint)
&lt;/h4&gt;

&lt;p&gt;The INP is a new metric introduced in Chrome DevTools that measures the time taken for the first interaction to the next paint. It helps you understand how quickly the page responds to user interactions. A good INP score is usually less than 100 milliseconds. This helps to identify slow interactions and optimize them for better performance.&lt;/p&gt;

&lt;p&gt;You can see in the previous images that the INP value is blank. This is because the INP value is calcualted only when there is an interaction on the page. You can interact with the page and see the INP value update in real-time.&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.amazonaws.com%2Fuploads%2Farticles%2F9gjbbzsfwc3xz06apa4h.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%2F9gjbbzsfwc3xz06apa4h.png" alt=" " width="800" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above screenshot, the INP value got updated as soon as I clicked on the search field. The INP metric shows the value in milliseconds and the element that was interacted with. Here the interaction was a click event, hence the event type is "pointer".&lt;/p&gt;

&lt;p&gt;The green color indicates that the INP score so far is good. If the score is bad, it will be highlighted in red. There is also orange color which indicates that the score is moderate.&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.amazonaws.com%2Fuploads%2Farticles%2Fatnnuisfr42waxjt8r5n.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%2Fatnnuisfr42waxjt8r5n.png" alt=" " width="800" height="209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;INP value is also live and will update as you interact with the page. Here you can see that the INP tag is pointing to the largest value.&lt;/p&gt;

&lt;h4&gt;
  
  
  Field data
&lt;/h4&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%2Fjsa4szaa7mceso2tfckw.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%2Fjsa4szaa7mceso2tfckw.png" alt=" " width="370" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Field data is another important section in the local metrics panel. It provides real-world data on the performance of your website. Field data is collected from real users who visit your website. This data helps you understand how your website performs in the real world and identify performance bottlenecks that need to be addressed.&lt;/p&gt;

&lt;p&gt;When this is enabled, you can see the field data for the performance metrics like LCP, CLS, and INP. This helps you compare the lab data with the field data and identify any discrepancies.&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.amazonaws.com%2Fuploads%2Farticles%2Fzv7zpgcsc3pw6pudylxx.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%2Fzv7zpgcsc3pw6pudylxx.png" alt=" " width="800" height="153"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here you can see that the field data reports the 75th percentile value for the performance metrics. In this example, the values are collected for "Desktop" users. However, you can change the device type to "Mobile" to see the field data for mobile users.&lt;/p&gt;

&lt;h4&gt;
  
  
  Environment Settings
&lt;/h4&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%2Fhu8ungaq3uhteypzrzvc.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%2Fhu8ungaq3uhteypzrzvc.png" alt=" " width="369" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Environment settings allow you to simulate different network conditions and CPU throttling. This helps you understand how your website performs under different network conditions and device capabilities. You can choose between different network profiles like "Offline", "3G", "Slow 4G", and "Fast 4G". You can also throttle the CPU to simulate different device capabilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this is important?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most of the time, we test the website in a controlled environment with a stable network connection and high-end devices. However, in the real world, users may have different network conditions and devices. By simulating different network conditions and CPU throttling, you can understand how your website performs in the real world and optimize it for better performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding slow interactions
&lt;/h2&gt;

&lt;p&gt;First use the INP to flag the interactions that are slow. This will be highlighted in either red or orange. Once you identify the slow interactions, use the record feature in the performance panel to record the interactions and analyze the performance bottlenecks.&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.amazonaws.com%2Fuploads%2Farticles%2Fo5wg69avgpaxex7awwn4.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%2Fo5wg69avgpaxex7awwn4.png" alt=" " width="800" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While recording, you repeat the same interactions that were slow and reported by INP. Now, you can pin-point the exact performance bottlenecks that are causing the slow interactions. You can analyze the performance bottlenecks using the flame chart, network panel, and other performance tools in Chrome DevTools.&lt;/p&gt;

&lt;p&gt;Let's see what the recording unfolds:&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.amazonaws.com%2Fuploads%2Farticles%2Fsquo0h8soiszzeqdkr11.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%2Fsquo0h8soiszzeqdkr11.png" alt=" " width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also click on the "INP by phase" link to see the breakdown of the INP metric. This will help you understand which phase of the interaction is slow and needs optimization. With this, you can spot if the interaction is slow due to JavaScript execution, rendering, or any other performance bottlenecks.&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.amazonaws.com%2Fuploads%2Farticles%2F4s96n3tucufm5snefc7y.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%2F4s96n3tucufm5snefc7y.png" alt=" " width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  A Final look at the Flame chart
&lt;/h4&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%2Fvw8eqnjyu4kgyhoeb7wp.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%2Fvw8eqnjyu4kgyhoeb7wp.png" alt=" " width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here when expanding the flame chart, you can see the detailed breakdown of the performance bottlenecks. You can see the time taken for each task and identify the bottlenecks that are causing the slow interactions. This will help you optimize the performance bottlenecks and improve the overall performance of the website.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Local metrics are a powerful tool that provides real-time data on the performance of your website. It helps you monitor the performance metrics as you interact with the website and identify performance bottlenecks quickly. By using local metrics, you can optimize the performance of your website and provide a better user experience to your visitors.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>devtools</category>
      <category>corewebvitals</category>
      <category>inp</category>
    </item>
  </channel>
</rss>
