<?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: Jakub Andrzejewski</title>
    <description>The latest articles on DEV Community by Jakub Andrzejewski (@jacobandrewsky).</description>
    <link>https://dev.to/jacobandrewsky</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F652576%2F71679021-521f-4d3b-b57f-af2d4ad055d9.png</url>
      <title>DEV Community: Jakub Andrzejewski</title>
      <link>https://dev.to/jacobandrewsky</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jacobandrewsky"/>
    <language>en</language>
    <item>
      <title>Preserve Component State in Vue with KeepAlive</title>
      <dc:creator>Jakub Andrzejewski</dc:creator>
      <pubDate>Mon, 10 Aug 2026 08:15:21 +0000</pubDate>
      <link>https://dev.to/jacobandrewsky/preserve-component-state-in-vue-with-keepalive-58i1</link>
      <guid>https://dev.to/jacobandrewsky/preserve-component-state-in-vue-with-keepalive-58i1</guid>
      <description>&lt;p&gt;When building Vue applications, we often switch between different components like tabs, multi-step forms, dynamic components, or event different views inside the same page.&lt;/p&gt;

&lt;p&gt;By default, when Vue removes a component from the DOM, its component instance is also unmounted. When you render it again, Vue creates a completely new instance.&lt;/p&gt;

&lt;p&gt;This means that things like local state, form input, or component state can be lost.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;&lt;code&gt;&amp;lt;KeepAlive&amp;gt;&lt;/code&gt;&lt;/strong&gt; becomes incredibly useful. Vue's &lt;code&gt;KeepAlive&lt;/code&gt; component allows you to &lt;strong&gt;cache inactive component instances&lt;/strong&gt; instead of destroying them.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What &lt;code&gt;KeepAlive&lt;/code&gt; is&lt;/li&gt;
&lt;li&gt;What problem it solves&lt;/li&gt;
&lt;li&gt;How to use it with dynamic components&lt;/li&gt;
&lt;li&gt;How to control which components are cached&lt;/li&gt;
&lt;li&gt;How &lt;code&gt;onActivated&lt;/code&gt; and &lt;code&gt;onDeactivated&lt;/code&gt; work&lt;/li&gt;
&lt;li&gt;Common mistakes and best practices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 What Is Vue KeepAlive?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;KeepAlive&amp;gt;&lt;/code&gt; is a built-in Vue component that allows you to cache component instances when they are switched out.&lt;/p&gt;

&lt;p&gt;Consider a simple dynamic component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&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;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Profile&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;./Profile.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Settings&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;./Settings.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Profile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&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="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"currentComponent = Profile"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Profile
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"currentComponent = Settings"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Settings
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;:is=&lt;/span&gt;&lt;span class="s"&gt;"currentComponent"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you switch from &lt;code&gt;Profile&lt;/code&gt; to &lt;code&gt;Settings&lt;/code&gt;, the &lt;code&gt;Profile&lt;/code&gt; component is unmounted.&lt;/p&gt;

&lt;p&gt;When you switch back, Vue creates a new &lt;code&gt;Profile&lt;/code&gt; instance.&lt;/p&gt;

&lt;p&gt;Now let's add &lt;code&gt;KeepAlive&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;KeepAlive&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;:is=&lt;/span&gt;&lt;span class="s"&gt;"currentComponent"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/KeepAlive&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now Vue keeps the inactive component instance alive.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Profile
  ↓
Unmount
  ↓
Destroy state
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Profile
  ↓
Deactivated
  ↓
Cached
  ↓
Activated again
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component state is preserved.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 What Problem Does KeepAlive Solve?
&lt;/h2&gt;

&lt;p&gt;Imagine you have a tabbed interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Profile | Settings | Billing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the Profile tab, the user fills out a form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Name: John
Email: john@example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then they switch to Settings.&lt;/p&gt;

&lt;p&gt;Without &lt;code&gt;KeepAlive&lt;/code&gt;, the Profile component can be unmounted.&lt;/p&gt;

&lt;p&gt;When they return:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Name:
Email:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The form has been reset.&lt;/p&gt;

&lt;p&gt;That's a terrible user experience.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;KeepAlive&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Profile
  ↓
User enters data
  ↓
Switch to Settings
  ↓
Profile is cached
  ↓
Return to Profile
  ↓
Form state is preserved
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is one of the most common use cases for &lt;code&gt;KeepAlive&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Using KeepAlive with Dynamic Components
&lt;/h2&gt;

&lt;p&gt;The most common pattern is wrapping a dynamic component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;KeepAlive&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;:is=&lt;/span&gt;&lt;span class="s"&gt;"currentComponent"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/KeepAlive&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&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;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Dashboard&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;./Dashboard.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Analytics&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;./Analytics.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Dashboard&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;nav&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"currentComponent = Dashboard"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Dashboard
    &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"currentComponent = Analytics"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Analytics
    &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;KeepAlive&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;:is=&lt;/span&gt;&lt;span class="s"&gt;"currentComponent"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/KeepAlive&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now both components can preserve their internal state when switching between them.&lt;/p&gt;

&lt;p&gt;This works especially well for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tabs&lt;/li&gt;
&lt;li&gt;dashboards&lt;/li&gt;
&lt;li&gt;editors&lt;/li&gt;
&lt;li&gt;multi-step forms&lt;/li&gt;
&lt;li&gt;complex filters&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🟢 KeepAlive and Lifecycle Hooks
&lt;/h2&gt;

&lt;p&gt;When using &lt;code&gt;KeepAlive&lt;/code&gt;, the normal lifecycle changes slightly.&lt;/p&gt;

&lt;p&gt;A cached component is not unmounted when it becomes inactive.&lt;/p&gt;

&lt;p&gt;Instead, Vue provides two special lifecycle hooks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;onActivated&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;onDeactivated&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;onActivated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;onDeactivated&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;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nf"&gt;onActivated&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Component is active&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;onDeactivated&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Component is inactive&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="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can be useful when you need to perform actions whenever the component becomes visible or hidden.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;refresh data&lt;/li&gt;
&lt;li&gt;restart an animation&lt;/li&gt;
&lt;li&gt;pause a timer&lt;/li&gt;
&lt;li&gt;reconnect to a resource&lt;/li&gt;
&lt;li&gt;update UI state&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🟢 KeepAlive vs &lt;code&gt;onMounted&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;One important thing to understand is that &lt;code&gt;onMounted()&lt;/code&gt; doesn't run every time a cached component becomes visible.&lt;/p&gt;

&lt;p&gt;Consider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;onMounted&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mounted&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;onActivated&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;activated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lifecycle looks roughly like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;First visit
↓
onMounted()
↓
onActivated()

Switch away
↓
onDeactivated()

Return
↓
onActivated()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component remains mounted while it is cached.&lt;/p&gt;

&lt;p&gt;This distinction is important when working with data fetching or subscriptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Controlling Which Components Are Cached
&lt;/h2&gt;

&lt;p&gt;You don't always want to cache everything.&lt;/p&gt;

&lt;p&gt;Vue allows you to control the cache using &lt;code&gt;include&lt;/code&gt; and &lt;code&gt;exclude&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;KeepAlive&lt;/span&gt; &lt;span class="na"&gt;include=&lt;/span&gt;&lt;span class="s"&gt;"Profile,Settings"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;:is=&lt;/span&gt;&lt;span class="s"&gt;"currentComponent"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/KeepAlive&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only components matching those names will be cached.&lt;/p&gt;

&lt;p&gt;You can also exclude components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;KeepAlive&lt;/span&gt; &lt;span class="na"&gt;exclude=&lt;/span&gt;&lt;span class="s"&gt;"HeavyChart"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;:is=&lt;/span&gt;&lt;span class="s"&gt;"currentComponent"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/KeepAlive&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is useful when some components are expensive to keep in memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Limiting the Cache with &lt;code&gt;max&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;KeepAlive&lt;/code&gt; also supports a &lt;code&gt;max&lt;/code&gt; prop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;KeepAlive&lt;/span&gt; &lt;span class="na"&gt;:max=&lt;/span&gt;&lt;span class="s"&gt;"5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;:is=&lt;/span&gt;&lt;span class="s"&gt;"currentComponent"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/KeepAlive&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This limits the number of component instances kept in the cache.&lt;/p&gt;

&lt;p&gt;When the limit is reached, Vue removes the least recently used cached component.&lt;/p&gt;

&lt;p&gt;This is particularly useful for applications where users can navigate through many dynamic views.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 KeepAlive Isn't Always the Right Choice
&lt;/h2&gt;

&lt;p&gt;Caching components sounds great, but it comes with a cost.&lt;/p&gt;

&lt;p&gt;A cached component still exists in memory.&lt;/p&gt;

&lt;p&gt;If you cache many complex components, you can increase memory usage.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;100 cached dashboards
+
large charts
+
large reactive state
=
potentially expensive memory usage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's why &lt;code&gt;KeepAlive&lt;/code&gt; should be used intentionally.&lt;/p&gt;

&lt;p&gt;Ask yourself:&lt;/p&gt;

&lt;p&gt;👉 "Does preserving this component's state provide enough value to justify keeping it in memory?"&lt;/p&gt;

&lt;p&gt;If the answer is no, regular mounting and unmounting may be better.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;KeepAlive&lt;/code&gt; when preserving component state improves UX&lt;/li&gt;
&lt;li&gt;Prefer it for tabs, editors, forms, and complex dynamic views&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;include&lt;/code&gt; and &lt;code&gt;exclude&lt;/code&gt; when only some components should be cached&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;max&lt;/code&gt; when users can create many cached component instances&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;onActivated&lt;/code&gt; for logic that should run whenever a cached component becomes active&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;onDeactivated&lt;/code&gt; to pause timers, subscriptions, or other ongoing work&lt;/li&gt;
&lt;li&gt;Be careful when caching memory-heavy components&lt;/li&gt;
&lt;li&gt;Don't use &lt;code&gt;KeepAlive&lt;/code&gt; everywhere just because it is available&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📖 Learn more
&lt;/h2&gt;

&lt;p&gt;If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this &lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&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%2Fj7hlfz848ut2d9ly8i8q.png" alt="Vue School Link" width="799" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Advance skills
&lt;/h2&gt;

&lt;p&gt;A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success.&lt;/p&gt;

&lt;p&gt;Check out Certificates.dev by clicking this &lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&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%2F9iledpqv69huancwg283.png" alt="Certificates.dev Link" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more!&lt;/p&gt;

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

&lt;p&gt;Vue's &lt;code&gt;KeepAlive&lt;/code&gt; is a powerful built-in component for preserving state between dynamic component switches.&lt;/p&gt;

&lt;p&gt;In this article, you learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What &lt;code&gt;KeepAlive&lt;/code&gt; is&lt;/li&gt;
&lt;li&gt;How it preserves component instances&lt;/li&gt;
&lt;li&gt;How to use it with dynamic components&lt;/li&gt;
&lt;li&gt;How &lt;code&gt;onActivated&lt;/code&gt; and &lt;code&gt;onDeactivated&lt;/code&gt; work&lt;/li&gt;
&lt;li&gt;How to control caching with &lt;code&gt;include&lt;/code&gt;, &lt;code&gt;exclude&lt;/code&gt;, and &lt;code&gt;max&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;When caching components can become a performance concern&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;KeepAlive&lt;/code&gt; is especially useful when users expect their state to remain intact while navigating between views.&lt;/p&gt;

&lt;p&gt;Use it intentionally, cache the components that benefit from it, and avoid keeping large numbers of memory-heavy components alive unnecessarily.&lt;/p&gt;

&lt;p&gt;Take care!&lt;br&gt;
And happy coding as always 🖥️&lt;/p&gt;

</description>
      <category>performance</category>
      <category>vue</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to set Content Security Policy with a Meta Tag?</title>
      <dc:creator>Jakub Andrzejewski</dc:creator>
      <pubDate>Mon, 03 Aug 2026 08:41:49 +0000</pubDate>
      <link>https://dev.to/jacobandrewsky/how-to-set-content-security-policy-with-a-meta-tag-5gfm</link>
      <guid>https://dev.to/jacobandrewsky/how-to-set-content-security-policy-with-a-meta-tag-5gfm</guid>
      <description>&lt;p&gt;When developers start implementing a &lt;strong&gt;Content Security Policy (CSP)&lt;/strong&gt;, they usually configure it through HTTP response headers.&lt;/p&gt;

&lt;p&gt;But then a common question comes up:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Can I define CSP using a &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag instead?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The answer is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Yes—but with some important limitations.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While using a meta tag can be convenient during development or on static websites, it doesn't provide the same level of protection as HTTP headers.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What a CSP meta tag is&lt;/li&gt;
&lt;li&gt;How it works&lt;/li&gt;
&lt;li&gt;Its limitations&lt;/li&gt;
&lt;li&gt;When you should (and shouldn't) use it&lt;/li&gt;
&lt;li&gt;Best practices for securing your application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 What Is a CSP Meta Tag?
&lt;/h2&gt;

&lt;p&gt;Instead of sending the Content Security Policy as an HTTP response header, you can define it directly inside your HTML document using a &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; element.&lt;/p&gt;

&lt;p&gt;Example:&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;meta&lt;/span&gt;
  &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"Content-Security-Policy"&lt;/span&gt;
  &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"
    default-src 'self';
    script-src 'self';
    style-src 'self';
  "&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser reads this tag while parsing the document and applies the specified policy.&lt;/p&gt;

&lt;p&gt;From that point onward, the CSP rules are enforced. Normally, CSP is configured by the server.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Content-Security-Policy:
default-src 'self';
script-src 'self';
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, sometimes you don't control the server configuration.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;static websites&lt;/li&gt;
&lt;li&gt;prototypes&lt;/li&gt;
&lt;li&gt;documentation sites&lt;/li&gt;
&lt;li&gt;GitHub Pages&lt;/li&gt;
&lt;li&gt;simple demos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In these cases, a meta tag allows you to add a basic CSP without modifying server headers.&lt;/p&gt;

&lt;p&gt;It's a convenient alternative when HTTP headers aren't available.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 How to Use a CSP Meta Tag
&lt;/h2&gt;

&lt;p&gt;A typical configuration looks like this:&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;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt;
    &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"Content-Security-Policy"&lt;/span&gt;
    &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"
      default-src 'self';
      img-src 'self' https:;
      script-src 'self';
      style-src 'self';
    "&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part is:&lt;/p&gt;

&lt;p&gt;👉 The meta tag should appear &lt;strong&gt;as early as possible inside the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Anything loaded before the browser encounters the CSP tag won't be protected by that policy.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 What Are the Limitations?
&lt;/h2&gt;

&lt;p&gt;This is where many developers get caught off guard.&lt;/p&gt;

&lt;p&gt;Although the syntax is very similar, &lt;strong&gt;meta-based CSP is not equivalent to an HTTP CSP header&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ It Doesn't Protect Early Requests
&lt;/h3&gt;

&lt;p&gt;The browser only applies the policy &lt;strong&gt;after&lt;/strong&gt; parsing the meta tag.&lt;/p&gt;

&lt;p&gt;That means resources loaded before it may bypass the policy.&lt;/p&gt;

&lt;p&gt;This is one of the main reasons HTTP headers are preferred.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Some Directives Are Not Supported
&lt;/h3&gt;

&lt;p&gt;Certain CSP directives only work when delivered as HTTP headers.&lt;/p&gt;

&lt;p&gt;For example, directives such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;report-uri&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;report-to&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;frame-ancestors&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sandbox&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;are ignored when specified in a meta tag.&lt;/p&gt;

&lt;p&gt;This means you lose features like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;violation reporting&lt;/li&gt;
&lt;li&gt;clickjacking protection&lt;/li&gt;
&lt;li&gt;advanced security controls&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Cannot Replace Server Security
&lt;/h3&gt;

&lt;p&gt;A meta tag is parsed as part of the HTML document.&lt;/p&gt;

&lt;p&gt;An HTTP header is processed &lt;strong&gt;before the page content&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Because of this, response headers always provide stronger protection.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 When Should You Use a Meta CSP?
&lt;/h2&gt;

&lt;p&gt;Using a meta tag can still be useful in several scenarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Static websites
&lt;/h3&gt;

&lt;p&gt;When server configuration isn't available.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Local development
&lt;/h3&gt;

&lt;p&gt;Testing CSP rules before deploying them to production.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Documentation sites
&lt;/h3&gt;

&lt;p&gt;Platforms like GitHub Pages often don't allow custom response headers.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Internal prototypes
&lt;/h3&gt;

&lt;p&gt;For demos and internal tools where basic protection is sufficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Meta Tag vs HTTP Header
&lt;/h2&gt;

&lt;p&gt;Let's compare both approaches.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Meta Tag&lt;/th&gt;
&lt;th&gt;HTTP Header&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Easy to add&lt;/td&gt;
&lt;td&gt;Requires server configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Good for static sites&lt;/td&gt;
&lt;td&gt;Recommended for production&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Applied after HTML parsing&lt;/td&gt;
&lt;td&gt;Applied before rendering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Limited directive support&lt;/td&gt;
&lt;td&gt;Full CSP support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No reporting directives&lt;/td&gt;
&lt;td&gt;Supports reporting and advanced policies&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For most production applications, the HTTP header is the clear winner.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prefer HTTP response headers for production&lt;/li&gt;
&lt;li&gt;Use meta CSP only when server headers aren't available&lt;/li&gt;
&lt;li&gt;Place the meta tag at the top of the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Don't rely on meta CSP for advanced security features&lt;/li&gt;
&lt;li&gt;Test your policy before deploying&lt;/li&gt;
&lt;li&gt;Start with Report-Only mode when using HTTP headers&lt;/li&gt;
&lt;li&gt;Keep your CSP as restrictive as your application allows&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📖 Learn more
&lt;/h2&gt;

&lt;p&gt;If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this &lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&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%2Fj7hlfz848ut2d9ly8i8q.png" alt="Vue School Link" width="799" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Advance skills
&lt;/h2&gt;

&lt;p&gt;A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success.&lt;/p&gt;

&lt;p&gt;Check out Certificates.dev by clicking this &lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&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%2F9iledpqv69huancwg283.png" alt="Certificates.dev Link" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more!&lt;/p&gt;

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

&lt;p&gt;A Content Security Policy can be defined using either an HTTP response header or a &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag—but they are &lt;strong&gt;not equivalent&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, you learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What a CSP meta tag is&lt;/li&gt;
&lt;li&gt;How to configure it&lt;/li&gt;
&lt;li&gt;What limitations it has&lt;/li&gt;
&lt;li&gt;When it's appropriate to use it&lt;/li&gt;
&lt;li&gt;Why HTTP headers remain the recommended approach for production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A meta-based CSP is a useful option for static websites, prototypes, and environments where you can't configure server headers. However, for production applications that require strong security guarantees, always prefer delivering your Content Security Policy through HTTP response headers.&lt;/p&gt;

&lt;p&gt;Take care!&lt;br&gt;
And happy coding as always 🖥️&lt;/p&gt;

</description>
      <category>html</category>
      <category>security</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Improve Performance by Loading Videos Only When They're Needed</title>
      <dc:creator>Jakub Andrzejewski</dc:creator>
      <pubDate>Mon, 13 Jul 2026 06:37:16 +0000</pubDate>
      <link>https://dev.to/jacobandrewsky/improve-performance-by-loading-videos-only-when-theyre-needed-245o</link>
      <guid>https://dev.to/jacobandrewsky/improve-performance-by-loading-videos-only-when-theyre-needed-245o</guid>
      <description>&lt;p&gt;Videos are one of the heaviest assets you can add to a web page.&lt;/p&gt;

&lt;p&gt;Loading videos too early can significantly impact your application's performance. The good news is that modern browsers are starting to support &lt;strong&gt;lazy loading for video elements&lt;/strong&gt;, allowing you to defer loading until users are likely to watch them.&lt;/p&gt;

&lt;p&gt;However, there's one important thing to know:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;This feature is not yet part of the Baseline web platform&lt;/strong&gt;, so browser support is still limited.&lt;/p&gt;

&lt;p&gt;At the time of writing, lazy loading for &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; elements is supported in &lt;strong&gt;Chromium-based browsers&lt;/strong&gt; such as &lt;strong&gt;Google Chrome&lt;/strong&gt;, &lt;strong&gt;Microsoft Edge&lt;/strong&gt;, and &lt;strong&gt;Opera&lt;/strong&gt;, while browsers like &lt;strong&gt;Firefox&lt;/strong&gt; and &lt;strong&gt;Safari&lt;/strong&gt; do not yet support it natively.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What lazy loading videos is&lt;/li&gt;
&lt;li&gt;Why it's important for web performance&lt;/li&gt;
&lt;li&gt;How to implement it&lt;/li&gt;
&lt;li&gt;Browser support considerations&lt;/li&gt;
&lt;li&gt;Best practices for optimizing video loading&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 What Is Lazy Loading for Videos?
&lt;/h2&gt;

&lt;p&gt;Lazy loading means delaying the loading of a resource until it's actually needed.&lt;/p&gt;

&lt;p&gt;Instead of downloading every video immediately during page load, the browser waits until the video is close to entering the viewport.&lt;/p&gt;

&lt;p&gt;This helps reduce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;initial network requests&lt;/li&gt;
&lt;li&gt;bandwidth usage&lt;/li&gt;
&lt;li&gt;page load time&lt;/li&gt;
&lt;li&gt;memory consumption&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Especially on pages with multiple videos, the difference can be significant.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 What Problem Does It Solve?
&lt;/h2&gt;

&lt;p&gt;Imagine an e-commerce page with several product videos.&lt;/p&gt;

&lt;p&gt;Without lazy loading:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;every video starts downloading immediately&lt;/li&gt;
&lt;li&gt;bandwidth is consumed even for videos users never watch&lt;/li&gt;
&lt;li&gt;page rendering may become slower&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This negatively impacts; Largest Contentful Paint (LCP), Time to Interactive (TTI), and overall user experience.&lt;/p&gt;

&lt;p&gt;Most visitors won't watch every video on the page. So why load them all? Lazy loading ensures videos are fetched only when they're actually needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 How to Lazy Load a Video
&lt;/h2&gt;

&lt;p&gt;The easiest approach is using the &lt;code&gt;loading="lazy"&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;Example:&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;video&lt;/span&gt;
  &lt;span class="na"&gt;controls&lt;/span&gt;
  &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;
  &lt;span class="na"&gt;poster=&lt;/span&gt;&lt;span class="s"&gt;"/preview.jpg"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt;
    &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/video.mp4"&lt;/span&gt;
    &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"video/mp4"&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/video&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the browser can defer loading the video until it's approaches the viewport.&lt;/p&gt;

&lt;p&gt;Combined with a &lt;code&gt;poster&lt;/code&gt; image, users still see a nice preview before playback begins.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Why Use a Poster Image?
&lt;/h2&gt;

&lt;p&gt;A poster acts as a placeholder while the video hasn't loaded yet.&lt;/p&gt;

&lt;p&gt;Example:&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;video&lt;/span&gt;
  &lt;span class="na"&gt;controls&lt;/span&gt;
  &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;
  &lt;span class="na"&gt;poster=&lt;/span&gt;&lt;span class="s"&gt;"/thumbnail.jpg"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt;
    &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/demo.mp4"&lt;/span&gt;
    &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"video/mp4"&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/video&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;faster visual rendering&lt;/li&gt;
&lt;li&gt;improved perceived performance&lt;/li&gt;
&lt;li&gt;lower initial network usage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Users immediately understand there's a video without downloading the entire file.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Loading Videos Only After User Interaction
&lt;/h2&gt;

&lt;p&gt;For videos below the fold, you can optimize even further.&lt;/p&gt;

&lt;p&gt;Instead of immediately defining the video source:&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;video&lt;/span&gt; &lt;span class="na"&gt;controls&lt;/span&gt; &lt;span class="na"&gt;poster=&lt;/span&gt;&lt;span class="s"&gt;"/thumbnail.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/video&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can dynamically add the &lt;code&gt;&amp;lt;source&amp;gt;&lt;/code&gt; element after:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the user clicks Play&lt;/li&gt;
&lt;li&gt;the video becomes visible&lt;/li&gt;
&lt;li&gt;an Intersection Observer fires&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives you complete control over when large video files start downloading.&lt;/p&gt;

&lt;p&gt;It's a great fallback for browsers that don't yet support native lazy loading.&lt;/p&gt;

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

&lt;p&gt;Since native video lazy loading isn't yet Baseline, it's important to understand browser compatibility.&lt;/p&gt;

&lt;p&gt;Currently, native support is available in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Google Chrome&lt;/li&gt;
&lt;li&gt;✅ Microsoft Edge&lt;/li&gt;
&lt;li&gt;✅ Opera&lt;/li&gt;
&lt;li&gt;✅ Other Chromium-based browsers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Support is currently unavailable in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Firefox&lt;/li&gt;
&lt;li&gt;❌ Safari&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For maximum compatibility, consider progressive enhancement.&lt;/p&gt;

&lt;p&gt;Browsers that support the feature benefit automatically, while older browsers still function correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Lazy load videos whenever they aren't immediately visible&lt;/li&gt;
&lt;li&gt;Always provide a lightweight poster image&lt;/li&gt;
&lt;li&gt;Compress videos before publishing&lt;/li&gt;
&lt;li&gt;Use modern video formats when possible&lt;/li&gt;
&lt;li&gt;Consider Intersection Observer for unsupported browsers&lt;/li&gt;
&lt;li&gt;Test browser compatibility before relying on native lazy loading&lt;/li&gt;
&lt;li&gt;Measure improvements using Lighthouse and Core Web Vitals&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📖 Learn more
&lt;/h2&gt;

&lt;p&gt;If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this &lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&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%2Fj7hlfz848ut2d9ly8i8q.png" alt="Vue School Link" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Advance skills
&lt;/h2&gt;

&lt;p&gt;A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success.&lt;/p&gt;

&lt;p&gt;Check out Certificates.dev by clicking this &lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&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%2F9iledpqv69huancwg283.png" alt="Certificates.dev Link" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more!&lt;/p&gt;

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

&lt;p&gt;Lazy loading videos is an effective way to improve performance by reducing unnecessary network requests and delaying large downloads until they're actually needed.&lt;/p&gt;

&lt;p&gt;Although native support isn't yet available across all browsers, it's already a valuable progressive enhancement for Chromium-based browsers. Combined with poster images and fallback techniques like Intersection Observer, it can significantly improve the loading experience of media-rich web applications.&lt;/p&gt;

&lt;p&gt;Take care!&lt;br&gt;
And happy coding as always 🖥️&lt;/p&gt;

</description>
      <category>performance</category>
      <category>html</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Enforce Better Vue Architecture with ESLint</title>
      <dc:creator>Jakub Andrzejewski</dc:creator>
      <pubDate>Mon, 06 Jul 2026 08:38:53 +0000</pubDate>
      <link>https://dev.to/jacobandrewsky/enforce-better-vue-architecture-with-eslint-3fb0</link>
      <guid>https://dev.to/jacobandrewsky/enforce-better-vue-architecture-with-eslint-3fb0</guid>
      <description>&lt;p&gt;As Vue applications grow, keeping the codebase clean becomes increasingly challenging. At first, everyone follows the same conventions. But over time, you start noticing things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;inconsistent component structure&lt;/li&gt;
&lt;li&gt;multiple ways of solving the same problem&lt;/li&gt;
&lt;li&gt;different Composition API patterns&lt;/li&gt;
&lt;li&gt;imports scattered everywhere&lt;/li&gt;
&lt;li&gt;code that's difficult to review and maintain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where &lt;strong&gt;ESLint&lt;/strong&gt; becomes much more than a tool for formatting—it becomes a way to enforce your project's architecture and design patterns.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why ESLint is more than a linter&lt;/li&gt;
&lt;li&gt;How it helps maintain a consistent architecture&lt;/li&gt;
&lt;li&gt;Useful Vue-specific rules&lt;/li&gt;
&lt;li&gt;Examples of enforcing project-wide patterns&lt;/li&gt;
&lt;li&gt;Best practices for scaling Vue applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 ESLint Is More Than a Code Formatter
&lt;/h2&gt;

&lt;p&gt;Many developers think ESLint is only used to catch things like; unused variables, missing semicolons, incorrect formatting. While that's true, ESLint can do much more.&lt;/p&gt;

&lt;p&gt;With the right configuration, it can enforce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;coding conventions&lt;/li&gt;
&lt;li&gt;project architecture&lt;/li&gt;
&lt;li&gt;Vue best practices&lt;/li&gt;
&lt;li&gt;Composition API patterns&lt;/li&gt;
&lt;li&gt;import organization&lt;/li&gt;
&lt;li&gt;component structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of relying on code reviews to catch inconsistencies, ESLint prevents them before the code is even merged.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 What Problem Does It Solve?
&lt;/h2&gt;

&lt;p&gt;Imagine a team of five developers.&lt;/p&gt;

&lt;p&gt;One component looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
...
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
...
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Someone uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Someone else always prefers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;watchEffect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some developers use relative imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Others use aliases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;/components/&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;None of these are necessarily wrong... but together they create inconsistency across the project. ESLint helps eliminate these differences by enforcing one agreed-upon way of writing code.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Enforcing Vue Block Order
&lt;/h2&gt;

&lt;p&gt;One of the simplest examples is keeping Vue Single File Components organized. Using the &lt;code&gt;vue/block-order&lt;/code&gt; rule, you can define the exact order of blocks.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  ...
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt; &lt;span class="na"&gt;scoped&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🟢 Enforcing Composition API Patterns
&lt;/h2&gt;

&lt;p&gt;One of the biggest advantages of ESLint is enforcing how developers use Vue APIs.&lt;/p&gt;

&lt;p&gt;For example, you might decide that your project should always use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Composition API&lt;/li&gt;
&lt;li&gt;&lt;code&gt;defineProps&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;defineEmits&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And avoid Options API or inconsistent component definitions. This ensures new components follow the same architecture from day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Restricting Specific APIs
&lt;/h2&gt;

&lt;p&gt;Sometimes you want to discourage certain patterns altogether. For example, you may decide:&lt;/p&gt;

&lt;p&gt;❌ Avoid &lt;code&gt;watch()&lt;/code&gt; unless absolutely necessary.&lt;/p&gt;

&lt;p&gt;Prefer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;watchEffect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ESLint can restrict the use of specific APIs and encourage better alternatives. This keeps reactive logic predictable and easier to maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Enforcing Import Conventions
&lt;/h2&gt;

&lt;p&gt;Large Vue projects often suffer from inconsistent imports.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Button&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;../../../components/Button.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;vs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Button&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;~/components/Button.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ESLint can enforce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;path aliases&lt;/li&gt;
&lt;li&gt;import ordering&lt;/li&gt;
&lt;li&gt;grouped imports&lt;/li&gt;
&lt;li&gt;no duplicate imports&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is cleaner and more consistent code.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Preventing Architectural Violations
&lt;/h2&gt;

&lt;p&gt;ESLint can also help enforce architectural boundaries. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Components shouldn't access API clients directly.&lt;/li&gt;
&lt;li&gt;Feature modules shouldn't import from other features.&lt;/li&gt;
&lt;li&gt;UI components shouldn't depend on business logic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using rules such as &lt;code&gt;no-restricted-imports&lt;/code&gt;, you can prevent these patterns entirely.&lt;/p&gt;

&lt;p&gt;Example:&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-restricted-imports&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="s1"&gt;error&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;patterns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/api/*&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;Now components can't accidentally bypass your intended architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Creating Custom Rules for Your Team
&lt;/h2&gt;

&lt;p&gt;One of ESLint's greatest strengths is extensibility.&lt;/p&gt;

&lt;p&gt;Beyond built-in rules, you can create custom rules—or use plugins—to enforce project-specific conventions.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;composables must start with &lt;code&gt;use&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;stores must live in a dedicated folder&lt;/li&gt;
&lt;li&gt;feature modules cannot import each other&lt;/li&gt;
&lt;li&gt;utility functions must remain pure&lt;/li&gt;
&lt;li&gt;internal design system components must be used instead of native HTML elements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As your project grows, these automated checks become far more reliable than relying solely on code reviews.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Why This Matters in Large Vue Applications
&lt;/h2&gt;

&lt;p&gt;Small projects can survive without strict rules. Large projects usually can't. Consistency helps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;onboard new developers faster&lt;/li&gt;
&lt;li&gt;simplify code reviews&lt;/li&gt;
&lt;li&gt;reduce technical debt&lt;/li&gt;
&lt;li&gt;prevent architectural drift&lt;/li&gt;
&lt;li&gt;improve long-term maintainability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of debating coding style in every pull request ESLint enforces it automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Treat ESLint as an architecture tool—not just a linter&lt;/li&gt;
&lt;li&gt;Enable Vue-specific rules from &lt;code&gt;eslint-plugin-vue&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Agree on project conventions early&lt;/li&gt;
&lt;li&gt;Enforce Composition API patterns consistently&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;no-restricted-imports&lt;/code&gt; to protect architectural boundaries&lt;/li&gt;
&lt;li&gt;Automate linting in CI/CD pipelines&lt;/li&gt;
&lt;li&gt;Keep rules practical—avoid overcomplicating your configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📖 Learn more
&lt;/h2&gt;

&lt;p&gt;If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this &lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&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%2Fj7hlfz848ut2d9ly8i8q.png" alt="Vue School Link" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Advance skills
&lt;/h2&gt;

&lt;p&gt;A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success.&lt;/p&gt;

&lt;p&gt;Check out Certificates.dev by clicking this &lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&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%2F9iledpqv69huancwg283.png" alt="Certificates.dev Link" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more!&lt;/p&gt;

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

&lt;p&gt;ESLint is much more than a tool for catching syntax errors or enforcing formatting.&lt;/p&gt;

&lt;p&gt;As Vue applications grow, consistency becomes just as important as functionality.&lt;/p&gt;

&lt;p&gt;By using ESLint to enforce architectural decisions, you ensure that every new piece of code follows the same standards—making your project easier to understand, review, and maintain for years to come.&lt;/p&gt;

&lt;p&gt;Take care!&lt;br&gt;
And happy coding as always 🖥️&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>vue</category>
      <category>eslint</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Fix Web Performance Issues Faster with Modern Web Guidance and Chrome DevTools for AI Agents</title>
      <dc:creator>Jakub Andrzejewski</dc:creator>
      <pubDate>Mon, 29 Jun 2026 05:22:27 +0000</pubDate>
      <link>https://dev.to/jacobandrewsky/fix-web-performance-issues-faster-with-modern-web-guidance-and-chrome-devtools-for-ai-agents-2e7e</link>
      <guid>https://dev.to/jacobandrewsky/fix-web-performance-issues-faster-with-modern-web-guidance-and-chrome-devtools-for-ai-agents-2e7e</guid>
      <description>&lt;p&gt;Performance optimization has always been one of the hardest parts of web development. You run Lighthouse, record a Performance trace, identify a long task... And then comes the difficult part:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;How do you actually fix it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Traditionally, developers had to spend hours searching documentation, comparing best practices, and figuring out which optimization applied to their situation.&lt;/p&gt;

&lt;p&gt;Google is trying to simplify this workflow with two new resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Modern Web Guidance&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Chrome DevTools for AI Agents&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, they make it easier for both developers and AI coding assistants to identify and fix common performance issues.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What Modern Web Guidance is&lt;/li&gt;
&lt;li&gt;What Chrome DevTools for AI Agents does&lt;/li&gt;
&lt;li&gt;How they work together&lt;/li&gt;
&lt;li&gt;Real-world performance issues they help solve&lt;/li&gt;
&lt;li&gt;Best practices for integrating them into your workflow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 What Is Modern Web Guidance?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.chrome.com/docs/modern-web-guidance0" rel="noopener noreferrer"&gt;Modern Web Guidance&lt;/a&gt; is a collection of best practices published by the Chrome team.&lt;/p&gt;

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

&lt;p&gt;Instead of generic advice like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Optimize your JavaScript."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It provides practical guidance for modern web applications covering topics such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rendering performance&lt;/li&gt;
&lt;li&gt;Core Web Vitals&lt;/li&gt;
&lt;li&gt;JavaScript optimization&lt;/li&gt;
&lt;li&gt;CSS best practices&lt;/li&gt;
&lt;li&gt;loading strategies&lt;/li&gt;
&lt;li&gt;images and fonts&lt;/li&gt;
&lt;li&gt;networking&lt;/li&gt;
&lt;li&gt;accessibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it as a centralized knowledge base for building fast web applications. Instead of searching through dozens of blog posts, you can rely on guidance maintained by the team behind Chrome.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 What Is Chrome DevTools for AI Agents?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.chrome.com/docs/devtools/agents" rel="noopener noreferrer"&gt;Chrome DevTools for AI Agents&lt;/a&gt; exposes browser debugging information in a way that AI coding assistants can understand.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7s82d6ompy84f6du61nh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7s82d6ompy84f6du61nh.png" alt="Chrome DevTools for AI Agents Showcase" width="800" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of simply analyzing source code, an AI agent can inspect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performance traces&lt;/li&gt;
&lt;li&gt;Network requests&lt;/li&gt;
&lt;li&gt;Console messages&lt;/li&gt;
&lt;li&gt;Rendering behavior&lt;/li&gt;
&lt;li&gt;Layout shifts&lt;/li&gt;
&lt;li&gt;Core Web Vitals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows AI assistants to reason about &lt;strong&gt;runtime behavior&lt;/strong&gt;, not just static code.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 How It Works Together
&lt;/h2&gt;

&lt;p&gt;Imagine your application has poor Interaction to Next Paint (INP).&lt;/p&gt;

&lt;p&gt;The workflow becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Performance trace
↓
AI Agent analyzes DevTools data
↓
Identifies bottleneck
↓
Matches issue with Modern Web Guidance
↓
Suggests concrete improvements
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🟢 Example: Finding a Long JavaScript Task
&lt;/h2&gt;

&lt;p&gt;Suppose DevTools records a long task blocking the main thread. Instead of only showing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Main thread blocked for 420ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An AI agent can help explain why the task is expensive, which code caused it, and which optimization patterns apply.&lt;/p&gt;

&lt;p&gt;For example; split large computations, lazy load modules, or reduce synchronous work. This dramatically shortens the debugging process.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Example: Fixing Layout Shifts
&lt;/h2&gt;

&lt;p&gt;Another common issue is &lt;strong&gt;Cumulative Layout Shift (CLS)&lt;/strong&gt;. DevTools can identify layout shifts.&lt;/p&gt;

&lt;p&gt;Modern Web Guidance recommends solutions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reserving space for images&lt;/li&gt;
&lt;li&gt;using skeleton loaders&lt;/li&gt;
&lt;li&gt;avoiding unexpected DOM insertions&lt;/li&gt;
&lt;li&gt;defining image dimensions&lt;/li&gt;
&lt;li&gt;preventing late-loading UI elements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of guessing, developers receive recommendations aligned with current web performance best practices.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Always profile before optimizing&lt;/li&gt;
&lt;li&gt;Use Chrome DevTools to collect real performance data&lt;/li&gt;
&lt;li&gt;Follow Modern Web Guidance instead of outdated optimization advice&lt;/li&gt;
&lt;li&gt;Focus on Core Web Vitals that impact real users&lt;/li&gt;
&lt;li&gt;Verify AI suggestions before applying them&lt;/li&gt;
&lt;li&gt;Measure improvements after every optimization&lt;/li&gt;
&lt;li&gt;Treat AI as a debugging assistant—not a replacement for understanding performance fundamentals&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📖 Learn more
&lt;/h2&gt;

&lt;p&gt;If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this &lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&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%2Fj7hlfz848ut2d9ly8i8q.png" alt="Vue School Link" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Advance skills
&lt;/h2&gt;

&lt;p&gt;A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success.&lt;/p&gt;

&lt;p&gt;Check out Certificates.dev by clicking this &lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&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%2F9iledpqv69huancwg283.png" alt="Certificates.dev Link" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more!&lt;/p&gt;

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

&lt;p&gt;Modern Web Guidance and Chrome DevTools for AI Agents represent an exciting step forward in web performance optimization.&lt;/p&gt;

&lt;p&gt;In this article, you learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What Modern Web Guidance is&lt;/li&gt;
&lt;li&gt;How Chrome DevTools for AI Agents works&lt;/li&gt;
&lt;li&gt;How they complement each other&lt;/li&gt;
&lt;li&gt;How they help identify and fix common performance issues&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Take care!&lt;br&gt;
And happy coding as always 🖥️&lt;/p&gt;

</description>
      <category>performance</category>
      <category>webperf</category>
      <category>ai</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>10 Vue Performance Mistakes I Still See in Production Apps</title>
      <dc:creator>Jakub Andrzejewski</dc:creator>
      <pubDate>Mon, 15 Jun 2026 07:08:48 +0000</pubDate>
      <link>https://dev.to/jacobandrewsky/10-vue-performance-mistakes-i-still-see-in-production-apps-52a1</link>
      <guid>https://dev.to/jacobandrewsky/10-vue-performance-mistakes-i-still-see-in-production-apps-52a1</guid>
      <description>&lt;p&gt;Performance has become one of the most important aspects of modern frontend development. Users expect websites to be fast and Google rewards fast websites.&lt;/p&gt;

&lt;p&gt;And yet... even experienced Vue developers still introduce performance issues that can significantly impact user experience.&lt;/p&gt;

&lt;p&gt;The tricky part? Most applications work perfectly fine during development.&lt;/p&gt;

&lt;p&gt;Problems usually appear later:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;larger datasets&lt;/li&gt;
&lt;li&gt;slower devices&lt;/li&gt;
&lt;li&gt;poor network conditions&lt;/li&gt;
&lt;li&gt;increased application complexity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, we'll look at &lt;strong&gt;10 common Vue performance mistakes&lt;/strong&gt; I still see in production applications and how to fix them.&lt;/p&gt;

&lt;p&gt;Let's dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 Why Vue Performance Matters
&lt;/h2&gt;

&lt;p&gt;Vue is already a highly optimized framework.&lt;/p&gt;

&lt;p&gt;However, even the best framework cannot compensate for inefficient application code.&lt;/p&gt;

&lt;p&gt;Poor performance can lead to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;slow page loads&lt;/li&gt;
&lt;li&gt;delayed interactions&lt;/li&gt;
&lt;li&gt;poor Core Web Vitals scores&lt;/li&gt;
&lt;li&gt;increased battery usage&lt;/li&gt;
&lt;li&gt;frustrated users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The good news?&lt;/p&gt;

&lt;p&gt;Most performance issues can be fixed with relatively small changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Mistake #1: Using Deep Watchers Everywhere
&lt;/h2&gt;

&lt;p&gt;A common mistake is enabling deep watchers on large objects.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;userData&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;saveDraft&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;deep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deep watchers force Vue to traverse the entire object tree.&lt;/p&gt;

&lt;p&gt;For large datasets this can become very expensive.&lt;/p&gt;

&lt;p&gt;Instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;watch specific properties&lt;/li&gt;
&lt;li&gt;split large objects&lt;/li&gt;
&lt;li&gt;use computed values when possible&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🟢 Mistake #2: Making Everything Reactive
&lt;/h2&gt;

&lt;p&gt;Not every piece of data needs reactivity.&lt;/p&gt;

&lt;p&gt;I often see code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hugeDataset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;largeArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the data rarely changes, Vue still needs to create reactive proxies.&lt;/p&gt;

&lt;p&gt;For large collections this introduces unnecessary overhead.&lt;/p&gt;

&lt;p&gt;A better approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hugeDataset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shallowRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;largeArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or even:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hugeDataset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;markRaw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;largeArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;when reactivity isn't needed at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Mistake #3: Creating New Objects Inside Computed Properties
&lt;/h2&gt;

&lt;p&gt;Consider this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;
&lt;span class="p"&gt;}))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A brand-new object is created every time the computed runs.&lt;/p&gt;

&lt;p&gt;This can trigger unnecessary component updates.&lt;/p&gt;

&lt;p&gt;Instead, prefer returning primitives when possible or memoizing expensive transformations.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Mistake #4: Using v-if Instead of v-show for Frequently Toggled Elements
&lt;/h2&gt;

&lt;p&gt;Many developers use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"isOpen"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Content
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But if the element is shown and hidden frequently, Vue must repeatedly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mount&lt;/li&gt;
&lt;li&gt;render&lt;/li&gt;
&lt;li&gt;destroy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A better option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-show=&lt;/span&gt;&lt;span class="s"&gt;"isOpen"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Content
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simply toggles CSS visibility.&lt;/p&gt;

&lt;p&gt;For frequently toggled UI elements, it's usually much faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Mistake #5: Rendering Huge Lists Without Virtualization
&lt;/h2&gt;

&lt;p&gt;Rendering thousands of DOM nodes is expensive.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
  &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"user in users"&lt;/span&gt;
  &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"user.id"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  {{ user.name }}
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This might work with 100 items.&lt;/p&gt;

&lt;p&gt;It won't feel great with 10,000.&lt;/p&gt;

&lt;p&gt;Instead consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;virtual scrolling&lt;/li&gt;
&lt;li&gt;pagination&lt;/li&gt;
&lt;li&gt;infinite loading&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Libraries like Vue Virtual Scroller can dramatically improve performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Mistake #6: Lazy Loading Nothing
&lt;/h2&gt;

&lt;p&gt;Many applications ship their entire codebase on the first page load.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;UserSettings&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;./UserSettings.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This increases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;bundle size&lt;/li&gt;
&lt;li&gt;download time&lt;/li&gt;
&lt;li&gt;parse time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserSettings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defineAsyncComponent&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="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./UserSettings.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Users only download code when it's actually needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Mistake #7: Fetching Data Sequentially
&lt;/h2&gt;

&lt;p&gt;A surprisingly common issue:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchUsers&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;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchPosts&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;comments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchComments&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each request waits for the previous one.&lt;/p&gt;

&lt;p&gt;A faster approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;]&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;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nf"&gt;fetchUsers&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;fetchPosts&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;fetchComments&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can reduce loading times significantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Mistake #8: Forgetting About Image Optimization
&lt;/h2&gt;

&lt;p&gt;Images are often the largest assets on a page.&lt;/p&gt;

&lt;p&gt;Yet many applications still serve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;oversized images&lt;/li&gt;
&lt;li&gt;uncompressed formats&lt;/li&gt;
&lt;li&gt;images outside the viewport&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Vue and Nuxt applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use WebP or AVIF&lt;/li&gt;
&lt;li&gt;lazy load images&lt;/li&gt;
&lt;li&gt;generate responsive sizes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Image optimization frequently provides the biggest performance wins.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Mistake #9: Ignoring Component Re-Renders
&lt;/h2&gt;

&lt;p&gt;A component may render far more often than expected.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ExpensiveChart&lt;/span&gt;
  &lt;span class="na"&gt;:data=&lt;/span&gt;&lt;span class="s"&gt;"chartData"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;chartData&lt;/code&gt; changes reference on every update, the chart keeps re-rendering.&lt;/p&gt;

&lt;p&gt;Common solutions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stabilize references&lt;/li&gt;
&lt;li&gt;use shallowRef&lt;/li&gt;
&lt;li&gt;avoid unnecessary reactive updates&lt;/li&gt;
&lt;li&gt;profile components with Vue DevTools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Small changes here can have a huge impact.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Mistake #10: Never Measuring Performance
&lt;/h2&gt;

&lt;p&gt;The biggest mistake?&lt;/p&gt;

&lt;p&gt;Not measuring anything.&lt;/p&gt;

&lt;p&gt;Many teams optimize blindly.&lt;/p&gt;

&lt;p&gt;Instead, regularly check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lighthouse&lt;/li&gt;
&lt;li&gt;Core Web Vitals&lt;/li&gt;
&lt;li&gt;Vue DevTools&lt;/li&gt;
&lt;li&gt;Chrome Performance Panel&lt;/li&gt;
&lt;li&gt;Network waterfalls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Performance work should be data-driven.&lt;/p&gt;

&lt;p&gt;You can't improve what you don't measure.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Performance Checklist
&lt;/h2&gt;

&lt;p&gt;Before shipping a Vue application, ask yourself:&lt;/p&gt;

&lt;p&gt;✅ Am I using deep watchers only when necessary?&lt;/p&gt;

&lt;p&gt;✅ Do all objects really need reactivity?&lt;/p&gt;

&lt;p&gt;✅ Are large lists virtualized?&lt;/p&gt;

&lt;p&gt;✅ Are routes and components lazy loaded?&lt;/p&gt;

&lt;p&gt;✅ Are API requests running in parallel?&lt;/p&gt;

&lt;p&gt;✅ Are images optimized?&lt;/p&gt;

&lt;p&gt;✅ Have I measured actual performance?&lt;/p&gt;

&lt;p&gt;If any answer is "no", there may be easy performance wins available.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use shallowRef for large datasets&lt;/li&gt;
&lt;li&gt;Avoid deep watchers whenever possible&lt;/li&gt;
&lt;li&gt;Lazy load routes and heavy components&lt;/li&gt;
&lt;li&gt;Virtualize large lists&lt;/li&gt;
&lt;li&gt;Optimize images aggressively&lt;/li&gt;
&lt;li&gt;Profile real-world user flows&lt;/li&gt;
&lt;li&gt;Monitor Core Web Vitals&lt;/li&gt;
&lt;li&gt;Measure before and after every optimization&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📖 Learn more
&lt;/h2&gt;

&lt;p&gt;If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this &lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&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%2Fj7hlfz848ut2d9ly8i8q.png" alt="Vue School Link" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Advance skills
&lt;/h2&gt;

&lt;p&gt;A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success.&lt;/p&gt;

&lt;p&gt;Check out Certificates.dev by clicking this &lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&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%2F9iledpqv69huancwg283.png" alt="Certificates.dev Link" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more!&lt;/p&gt;

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

&lt;p&gt;Vue is fast by default.&lt;/p&gt;

&lt;p&gt;But performance problems often come from how we use the framework rather than the framework itself.&lt;/p&gt;

&lt;p&gt;In this article, you learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;10 common Vue performance mistakes&lt;/li&gt;
&lt;li&gt;Why they impact real-world applications&lt;/li&gt;
&lt;li&gt;How to identify them&lt;/li&gt;
&lt;li&gt;Practical ways to fix them&lt;/li&gt;
&lt;li&gt;Best practices for building faster Vue apps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many of these issues are easy to overlook during development but become expensive at scale.&lt;/p&gt;

&lt;p&gt;By avoiding these mistakes and measuring performance regularly, you can build applications that feel fast, responsive, and enjoyable to use.&lt;/p&gt;

&lt;p&gt;Take care!&lt;br&gt;
And happy coding as always 🖥️&lt;/p&gt;

</description>
      <category>vue</category>
      <category>performance</category>
      <category>javascript</category>
      <category>html</category>
    </item>
    <item>
      <title>Frontend Observability in Vue Apps with OpenTelemetry</title>
      <dc:creator>Jakub Andrzejewski</dc:creator>
      <pubDate>Mon, 08 Jun 2026 08:59:35 +0000</pubDate>
      <link>https://dev.to/jacobandrewsky/frontend-observability-in-vue-apps-with-opentelemetry-3fb0</link>
      <guid>https://dev.to/jacobandrewsky/frontend-observability-in-vue-apps-with-opentelemetry-3fb0</guid>
      <description>&lt;p&gt;As frontend applications become more complex, debugging production issues becomes increasingly difficult.&lt;/p&gt;

&lt;p&gt;A user reports: "The page feels slow." or: "The dashboard sometimes freezes."&lt;/p&gt;

&lt;p&gt;But when you check your logs... everything looks fine.&lt;/p&gt;

&lt;p&gt;The problem is that traditional frontend monitoring often tells you &lt;strong&gt;what failed&lt;/strong&gt;, but not &lt;strong&gt;why it happened&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;observability&lt;/strong&gt; comes in. And one of the most popular tools for modern observability is &lt;strong&gt;OpenTelemetry&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What frontend observability is&lt;/li&gt;
&lt;li&gt;How it differs from traditional monitoring&lt;/li&gt;
&lt;li&gt;Why OpenTelemetry is becoming the industry standard&lt;/li&gt;
&lt;li&gt;How to add OpenTelemetry to a Vue application&lt;/li&gt;
&lt;li&gt;Best practices for collecting useful telemetry&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 What Is Frontend Observability?
&lt;/h2&gt;

&lt;p&gt;Observability is the ability to understand what's happening inside your application by collecting telemetry data.&lt;/p&gt;

&lt;p&gt;Typically, this includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;traces&lt;/li&gt;
&lt;li&gt;metrics&lt;/li&gt;
&lt;li&gt;logs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike traditional monitoring, observability helps answer questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why is this page slow?&lt;/li&gt;
&lt;li&gt;Which API request caused the delay?&lt;/li&gt;
&lt;li&gt;What happened before the error occurred?&lt;/li&gt;
&lt;li&gt;Which users are affected?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of simply knowing that something failed...&lt;/p&gt;

&lt;p&gt;👉 You can understand the entire chain of events that led to the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Why Is Frontend Observability Important?
&lt;/h2&gt;

&lt;p&gt;Most teams invest heavily in backend observability.&lt;/p&gt;

&lt;p&gt;They track:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;database queries&lt;/li&gt;
&lt;li&gt;API latency&lt;/li&gt;
&lt;li&gt;server errors&lt;/li&gt;
&lt;li&gt;infrastructure metrics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But users interact with the frontend.&lt;/p&gt;

&lt;p&gt;And many issues happen before the request even reaches the backend.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;slow component rendering&lt;/li&gt;
&lt;li&gt;blocked main thread&lt;/li&gt;
&lt;li&gt;failed network requests&lt;/li&gt;
&lt;li&gt;routing issues&lt;/li&gt;
&lt;li&gt;third-party script delays&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without frontend observability these problems are often invisible.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 What Is OpenTelemetry?
&lt;/h2&gt;

&lt;p&gt;OpenTelemetry (often called OTel) is an open-source observability framework used to collect and export telemetry data.&lt;/p&gt;

&lt;p&gt;It provides a standard way to collect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;traces&lt;/li&gt;
&lt;li&gt;metrics&lt;/li&gt;
&lt;li&gt;logs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And send them to tools such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Grafana&lt;/li&gt;
&lt;li&gt;Jaeger&lt;/li&gt;
&lt;li&gt;Datadog&lt;/li&gt;
&lt;li&gt;New Relic&lt;/li&gt;
&lt;li&gt;Honeycomb&lt;/li&gt;
&lt;li&gt;Elastic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The biggest advantage? Vendor-neutral instrumentation.&lt;/p&gt;

&lt;p&gt;You can change observability providers without rewriting your instrumentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 How OpenTelemetry Helps Vue Applications
&lt;/h2&gt;

&lt;p&gt;Imagine a user loads a dashboard.&lt;/p&gt;

&lt;p&gt;Several things happen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Route change
↓
Component mounts
↓
API request starts
↓
Data is fetched
↓
UI renders
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Normally these events are disconnected.&lt;/p&gt;

&lt;p&gt;With OpenTelemetry you can trace the entire flow.&lt;/p&gt;

&lt;p&gt;This helps answer questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which API call slowed down the page?&lt;/li&gt;
&lt;li&gt;How long did rendering take?&lt;/li&gt;
&lt;li&gt;Which routes are causing performance issues?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🟢 Setting Up OpenTelemetry in Vue
&lt;/h2&gt;

&lt;p&gt;Let's look at a simplified setup.&lt;/p&gt;

&lt;p&gt;Install the required packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  @opentelemetry/api &lt;span class="se"&gt;\&lt;/span&gt;
  @opentelemetry/sdk-trace-web &lt;span class="se"&gt;\&lt;/span&gt;
  @opentelemetry/instrumentation-fetch &lt;span class="se"&gt;\&lt;/span&gt;
  @opentelemetry/instrumentation-xml-http-request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Basic initialization
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;WebTracerProvider&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;@opentelemetry/sdk-trace-web&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;provider&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;WebTracerProvider&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a tracer that can collect telemetry from the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Creating Custom Traces
&lt;/h2&gt;

&lt;p&gt;One of the most powerful features is custom tracing.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;trace&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;@opentelemetry/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tracer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTracer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue-app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside a component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;span&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startSpan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;load-users&lt;/span&gt;&lt;span class="dl"&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="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchUsers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&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;Now you'll see exactly how long that operation took.&lt;/p&gt;

&lt;p&gt;This becomes extremely useful when debugging production issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Tracking Route Performance
&lt;/h2&gt;

&lt;p&gt;Vue Router is another excellent place to add tracing.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;to&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;next&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;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mark&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;navigation-start&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;afterEach&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;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;measure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;navigation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;navigation-start&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Combined with OpenTelemetry exporters, this can help identify slow routes and navigation bottlenecks.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Monitoring API Requests
&lt;/h2&gt;

&lt;p&gt;Many performance problems originate from network calls.&lt;/p&gt;

&lt;p&gt;OpenTelemetry provides automatic instrumentation for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetch API&lt;/li&gt;
&lt;li&gt;XMLHttpRequest&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;registerInstrumentations&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;instrumentations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FetchInstrumentation&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;Now requests can automatically generate traces.&lt;/p&gt;

&lt;p&gt;You can see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;request duration&lt;/li&gt;
&lt;li&gt;failures&lt;/li&gt;
&lt;li&gt;dependencies between actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;without manually instrumenting every API call.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Instrument critical user flows first&lt;/li&gt;
&lt;li&gt;Trace important API requests&lt;/li&gt;
&lt;li&gt;Avoid collecting unnecessary telemetry&lt;/li&gt;
&lt;li&gt;Sample traces in high-traffic applications&lt;/li&gt;
&lt;li&gt;Correlate frontend traces with backend traces&lt;/li&gt;
&lt;li&gt;Monitor route transitions and rendering bottlenecks&lt;/li&gt;
&lt;li&gt;Focus on actionable insights rather than collecting everything&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📖 Learn more
&lt;/h2&gt;

&lt;p&gt;If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this &lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&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%2Fj7hlfz848ut2d9ly8i8q.png" alt="Vue School Link" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Advance skills
&lt;/h2&gt;

&lt;p&gt;A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success.&lt;/p&gt;

&lt;p&gt;Check out Certificates.dev by clicking this &lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&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%2F9iledpqv69huancwg283.png" alt="Certificates.dev Link" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more!&lt;/p&gt;

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

&lt;p&gt;Frontend observability helps you understand not just what went wrong, but why it happened.&lt;/p&gt;

&lt;p&gt;As applications grow in complexity, logs and error tracking alone are often no longer enough.&lt;/p&gt;

&lt;p&gt;OpenTelemetry gives you deeper visibility into your Vue application, helping you identify bottlenecks, improve performance, and deliver a better user experience.&lt;/p&gt;

&lt;p&gt;Take care!&lt;br&gt;
And happy coding as always 🖥️&lt;/p&gt;

</description>
      <category>performance</category>
      <category>automation</category>
      <category>architecture</category>
      <category>vue</category>
    </item>
    <item>
      <title>State-Driven Animations in Vue: Create Smooth UI Transitions with Reactive State</title>
      <dc:creator>Jakub Andrzejewski</dc:creator>
      <pubDate>Mon, 01 Jun 2026 09:54:37 +0000</pubDate>
      <link>https://dev.to/jacobandrewsky/state-driven-animations-in-vue-create-smooth-ui-transitions-with-reactive-state-d3i</link>
      <guid>https://dev.to/jacobandrewsky/state-driven-animations-in-vue-create-smooth-ui-transitions-with-reactive-state-d3i</guid>
      <description>&lt;p&gt;Animations can make an application feel faster, smoother, and more polished. However, many developers think animations are only useful for things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;page transitions&lt;/li&gt;
&lt;li&gt;modals&lt;/li&gt;
&lt;li&gt;enter/leave effects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But Vue provides another powerful pattern - State-driven animations. Instead of animating when elements are added or removed from the DOM, you animate changes in reactive state. This allows you to create rich interactive experiences while keeping your code declarative and easy to maintain.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What state-driven animations are&lt;/li&gt;
&lt;li&gt;How they differ from regular Vue transitions&lt;/li&gt;
&lt;li&gt;What problems they solve&lt;/li&gt;
&lt;li&gt;How to implement them in Vue&lt;/li&gt;
&lt;li&gt;Best practices for creating smooth UI interactions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 What Are State-Driven Animations?
&lt;/h2&gt;

&lt;p&gt;Most Vue developers are familiar with the &lt;code&gt;&amp;lt;Transition&amp;gt;&lt;/code&gt; component.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Transition&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Modal&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"isOpen"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Transition&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This animates an element when it enters or leaves the DOM.&lt;/p&gt;

&lt;p&gt;But what if the element already exists and only its state changes? For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a progress bar grows&lt;/li&gt;
&lt;li&gt;a card expands&lt;/li&gt;
&lt;li&gt;a chart updates&lt;/li&gt;
&lt;li&gt;a panel changes size&lt;/li&gt;
&lt;li&gt;a value changes position&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where &lt;strong&gt;state-driven animations&lt;/strong&gt; shine.&lt;/p&gt;

&lt;p&gt;Instead of animating DOM insertion or removal, you animate changes caused by reactive state.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 What Problem Do State-Driven Animations Solve?
&lt;/h2&gt;

&lt;p&gt;Without animations, state changes can feel abrupt.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;:style=&lt;/span&gt;&lt;span class="s"&gt;"{ width: progress + '%' }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;progress&lt;/code&gt; changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The width instantly jumps.&lt;/p&gt;

&lt;p&gt;This works technically... but it doesn't feel great.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 A Simple Example
&lt;/h2&gt;

&lt;p&gt;Let's create an animated progress bar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;progress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&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;increase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&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="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"increase"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Increase Progress
  &lt;span class="nt"&gt;&amp;lt;/button&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;"progress-container"&lt;/span&gt;&lt;span class="nt"&gt;&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;"progress-bar"&lt;/span&gt;
      &lt;span class="na"&gt;:style=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;{ width: `${progress}%` }"
    /&amp;gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.progress-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#eee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.progress-bar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#42b883&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="m"&gt;0.3s&lt;/span&gt; &lt;span class="n"&gt;ease&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;Now whenever &lt;code&gt;progress&lt;/code&gt; changes, the bar animates smoothly.&lt;/p&gt;

&lt;p&gt;The animation is entirely driven by reactive state.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Animating Multiple Properties
&lt;/h2&gt;

&lt;p&gt;State-driven animations are not limited to width.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&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;"card"&lt;/span&gt;
  &lt;span class="na"&gt;:style=&lt;/span&gt;&lt;span class="s"&gt;"{
    transform: expanded
      ? 'scale(1.1)'
      : 'scale(1)',
    opacity: expanded
      ? 1
      : 0.7
  }"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;transform&lt;/span&gt; &lt;span class="m"&gt;0.3s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;opacity&lt;/span&gt; &lt;span class="m"&gt;0.3s&lt;/span&gt; &lt;span class="n"&gt;ease&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;Now changing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;expanded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;animates &lt;code&gt;scale&lt;/code&gt; and &lt;code&gt;opacity&lt;/code&gt; at the same time.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Using Vue Reactivity with Animations
&lt;/h2&gt;

&lt;p&gt;One of the biggest advantages is that animations stay connected to Vue's reactivity system.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isActive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&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="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"isActive = !isActive"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Toggle
  &lt;span class="nt"&gt;&amp;lt;/button&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;"box"&lt;/span&gt;
    &lt;span class="na"&gt;:class=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;{ active: isActive }"
  /&amp;gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="m"&gt;0.4s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.box.active&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;180deg&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;Vue handles state.&lt;/p&gt;

&lt;p&gt;CSS handles animation.&lt;/p&gt;

&lt;p&gt;The result is clean and maintainable.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Keep animations subtle and purposeful&lt;/li&gt;
&lt;li&gt;Prefer CSS transitions for simple effects&lt;/li&gt;
&lt;li&gt;Avoid animating expensive properties when possible&lt;/li&gt;
&lt;li&gt;Use transforms instead of layout-changing properties when appropriate&lt;/li&gt;
&lt;li&gt;Don't animate everything&lt;/li&gt;
&lt;li&gt;Keep durations short (typically 200–400ms)&lt;/li&gt;
&lt;li&gt;Use animations to communicate state changes, not distract users&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📖 Learn more
&lt;/h2&gt;

&lt;p&gt;If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this &lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&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%2Fj7hlfz848ut2d9ly8i8q.png" alt="Vue School Link" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Advance skills
&lt;/h2&gt;

&lt;p&gt;A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success.&lt;/p&gt;

&lt;p&gt;Check out Certificates.dev by clicking this &lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&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%2F9iledpqv69huancwg283.png" alt="Certificates.dev Link" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more!&lt;/p&gt;

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

&lt;p&gt;State-driven animations are a powerful way to create smooth and engaging user experiences in Vue.&lt;/p&gt;

&lt;p&gt;While &lt;code&gt;&amp;lt;Transition&amp;gt;&lt;/code&gt; is perfect for entering and leaving elements, state-driven animations excel when existing elements need to react smoothly to changing data.&lt;/p&gt;

&lt;p&gt;Used thoughtfully, they can make your applications feel significantly more responsive and professional.&lt;/p&gt;

&lt;p&gt;Take care!&lt;br&gt;
And happy coding as always 🖥️&lt;/p&gt;

</description>
      <category>vue</category>
      <category>css</category>
      <category>animation</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Avoid Cross Module Dependencies with Dependency Cruiser</title>
      <dc:creator>Jakub Andrzejewski</dc:creator>
      <pubDate>Mon, 25 May 2026 06:27:43 +0000</pubDate>
      <link>https://dev.to/jacobandrewsky/avoid-cross-module-dependencies-with-dependency-cruiser-3b0b</link>
      <guid>https://dev.to/jacobandrewsky/avoid-cross-module-dependencies-with-dependency-cruiser-3b0b</guid>
      <description>&lt;p&gt;As applications grow, maintaining a clean architecture becomes increasingly difficult.&lt;/p&gt;

&lt;p&gt;At first, everything feels manageable but after a few months (or years), projects often become full of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;circular dependencies&lt;/li&gt;
&lt;li&gt;deeply coupled modules&lt;/li&gt;
&lt;li&gt;messy import paths&lt;/li&gt;
&lt;li&gt;forbidden cross-layer imports&lt;/li&gt;
&lt;li&gt;architectural chaos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The worst part is that these problems usually grow silently over time.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;dependency-cruiser&lt;/strong&gt; becomes incredibly useful. It helps you visualize and enforce rules for your project dependencies before things become unmaintainable.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What dependency-cruiser is&lt;/li&gt;
&lt;li&gt;What problems it solves&lt;/li&gt;
&lt;li&gt;How to set it up&lt;/li&gt;
&lt;li&gt;Practical examples&lt;/li&gt;
&lt;li&gt;How to enforce architectural boundaries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 What Is dependency-cruiser?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/sverweij/dependency-cruiser" rel="noopener noreferrer"&gt;dependency-cruiser&lt;/a&gt; is a powerful tool for analyzing and validating dependencies in JavaScript and TypeScript projects.&lt;/p&gt;

&lt;p&gt;It scans your project imports and helps you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;detect circular dependencies&lt;/li&gt;
&lt;li&gt;enforce architecture rules&lt;/li&gt;
&lt;li&gt;visualize dependency graphs&lt;/li&gt;
&lt;li&gt;identify unused modules&lt;/li&gt;
&lt;li&gt;prevent bad import patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it like:&lt;/p&gt;

&lt;p&gt;👉 “ESLint for your project architecture.”&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 What Problem Does dependency-cruiser Solve?
&lt;/h2&gt;

&lt;p&gt;In large applications, dependencies can quickly become messy.&lt;/p&gt;

&lt;p&gt;Example problems:&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Circular dependencies
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A → B → C → A
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These can cause:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;runtime issues&lt;/li&gt;
&lt;li&gt;undefined values&lt;/li&gt;
&lt;li&gt;difficult debugging&lt;/li&gt;
&lt;li&gt;unpredictable behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Layer violations
&lt;/h3&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;components → api → components
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ui → backend → ui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This breaks separation of concerns.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Shared modules becoming dumping grounds
&lt;/h3&gt;

&lt;p&gt;You often end up with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/utils
/shared
/helpers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;containing everything.&lt;/p&gt;

&lt;p&gt;Over time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dependencies become tangled&lt;/li&gt;
&lt;li&gt;architecture loses structure&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ dependency-cruiser helps enforce boundaries
&lt;/h3&gt;

&lt;p&gt;You can define rules like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“UI cannot import backend”&lt;/li&gt;
&lt;li&gt;“Feature modules cannot depend on each other”&lt;/li&gt;
&lt;li&gt;“No circular dependencies allowed”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And automatically validate them in CI.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Installing dependency-cruiser
&lt;/h2&gt;

&lt;p&gt;Setup is very simple.&lt;/p&gt;

&lt;p&gt;Install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; dependency-cruiser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🟢 Generating Your First Dependency Graph
&lt;/h2&gt;

&lt;p&gt;One of the coolest features is visualization.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx depcruise src &lt;span class="nt"&gt;--include-only&lt;/span&gt; &lt;span class="s2"&gt;"^src"&lt;/span&gt; &lt;span class="nt"&gt;--output-type&lt;/span&gt; dot | dot &lt;span class="nt"&gt;-T&lt;/span&gt; svg &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; dependency-graph.svg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This generates a visual graph of your project dependencies.&lt;/p&gt;

&lt;p&gt;You can quickly spot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;circular dependencies&lt;/li&gt;
&lt;li&gt;overly connected modules&lt;/li&gt;
&lt;li&gt;problematic architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In large projects, this is incredibly eye-opening.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Creating Rules
&lt;/h2&gt;

&lt;p&gt;The real power comes from architecture validation.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;forbidden&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-circular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;severity&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&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
      &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;circular&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now dependency-cruiser will fail whenever circular dependencies appear.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Real-World Example: Enforcing Layered Architecture
&lt;/h2&gt;

&lt;p&gt;Imagine this structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
├── components/
├── features/
├── api/
├── utils/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may want:&lt;/p&gt;

&lt;p&gt;👉 &lt;code&gt;components&lt;/code&gt; should never import from &lt;code&gt;api&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Rule example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;forbidden&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-components-to-api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^src/components&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^src/api&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now architecture rules become automated.&lt;/p&gt;

&lt;p&gt;This is extremely valuable for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;large teams&lt;/li&gt;
&lt;li&gt;enterprise projects&lt;/li&gt;
&lt;li&gt;monorepos&lt;/li&gt;
&lt;li&gt;long-term maintainability&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🟢 Using dependency-cruiser with Vue Projects
&lt;/h2&gt;

&lt;p&gt;dependency-cruiser works great with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vue&lt;/li&gt;
&lt;li&gt;Nuxt&lt;/li&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;Angular&lt;/li&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;TypeScript monorepos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Vue apps, it’s especially useful when managing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;composables&lt;/li&gt;
&lt;li&gt;feature modules&lt;/li&gt;
&lt;li&gt;shared UI components&lt;/li&gt;
&lt;li&gt;store architecture&lt;/li&gt;
&lt;li&gt;layered frontend structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example issue it can prevent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;components → composables → components
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which can become very difficult to maintain later.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 CI Integration
&lt;/h2&gt;

&lt;p&gt;One of the best things about dependency-cruiser:&lt;/p&gt;

&lt;p&gt;👉 It can run automatically in CI/CD pipelines.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx depcruise src &lt;span class="nt"&gt;--validate&lt;/span&gt; .dependency-cruiser.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now pull requests fail when architecture rules are violated.&lt;/p&gt;

&lt;p&gt;This prevents technical debt from growing silently.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Common Mistakes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Creating overly strict rules too early
&lt;/h3&gt;

&lt;p&gt;Start simple.&lt;/p&gt;

&lt;p&gt;Too many restrictions can frustrate teams.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Ignoring the reports
&lt;/h3&gt;

&lt;p&gt;The tool is only useful if rules are actually enforced.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Not visualizing dependencies
&lt;/h3&gt;

&lt;p&gt;Graphs often reveal architecture problems immediately.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Allowing shared folders to grow uncontrollably
&lt;/h3&gt;

&lt;p&gt;dependency-cruiser helps expose this early.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Start with circular dependency detection&lt;/li&gt;
&lt;li&gt;Gradually add architectural rules&lt;/li&gt;
&lt;li&gt;Integrate validation into CI&lt;/li&gt;
&lt;li&gt;Use dependency graphs regularly&lt;/li&gt;
&lt;li&gt;Keep rules aligned with real architecture decisions&lt;/li&gt;
&lt;li&gt;Avoid massive shared utility folders&lt;/li&gt;
&lt;li&gt;Use the tool proactively — not only after problems appear&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📖 Learn more
&lt;/h2&gt;

&lt;p&gt;If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this &lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&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%2Fj7hlfz848ut2d9ly8i8q.png" alt="Vue School Link" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Advance skills
&lt;/h2&gt;

&lt;p&gt;A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success.&lt;/p&gt;

&lt;p&gt;Check out Certificates.dev by clicking this &lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&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%2F9iledpqv69huancwg283.png" alt="Certificates.dev Link" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more!&lt;/p&gt;

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

&lt;p&gt;dependency-cruiser is an incredibly valuable tool for keeping project architecture healthy as applications grow.&lt;/p&gt;

&lt;p&gt;Good architecture rarely happens accidentally.&lt;/p&gt;

&lt;p&gt;Tools like dependency-cruiser help teams maintain structure, reduce technical debt, and prevent dependency chaos before it becomes a serious problem.&lt;/p&gt;

&lt;p&gt;Take care!&lt;br&gt;
And happy coding as always 🖥️&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>frontend</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Avoid Unnecessary Re-renders in Vue with `v-memo`</title>
      <dc:creator>Jakub Andrzejewski</dc:creator>
      <pubDate>Mon, 18 May 2026 09:21:34 +0000</pubDate>
      <link>https://dev.to/jacobandrewsky/avoid-unnecessary-re-renders-in-vue-with-v-memo-49bo</link>
      <guid>https://dev.to/jacobandrewsky/avoid-unnecessary-re-renders-in-vue-with-v-memo-49bo</guid>
      <description>&lt;p&gt;When building Vue applications, performance usually feels great by default - Vue’s reactivity system is incredibly efficient.&lt;/p&gt;

&lt;p&gt;But as applications grow larger, you may eventually run into situations where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;components re-render too often&lt;/li&gt;
&lt;li&gt;large lists become expensive&lt;/li&gt;
&lt;li&gt;UI updates feel sluggish&lt;/li&gt;
&lt;li&gt;unnecessary computations happen repeatedly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where &lt;strong&gt;memoization&lt;/strong&gt; becomes useful. And in Vue, one of the easiest ways to optimize rendering is with &lt;code&gt;v-memo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What memoization is&lt;/li&gt;
&lt;li&gt;What problem it solves&lt;/li&gt;
&lt;li&gt;How &lt;code&gt;v-memo&lt;/code&gt; works in Vue&lt;/li&gt;
&lt;li&gt;Real-world examples&lt;/li&gt;
&lt;li&gt;Best practices and common mistakes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 What Is Memoization?
&lt;/h2&gt;

&lt;p&gt;Memoization is an optimization technique where results are &lt;strong&gt;cached&lt;/strong&gt; and reused instead of recalculating them again.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;recomputing&lt;/li&gt;
&lt;li&gt;re-rendering&lt;/li&gt;
&lt;li&gt;recalculating&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You simply use the cached version.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 What Problem Does Memoization Solve?
&lt;/h2&gt;

&lt;p&gt;In reactive applications, updates can trigger many re-renders even when most data has not changed for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parent component updates&lt;/li&gt;
&lt;li&gt;Entire list re-renders&lt;/li&gt;
&lt;li&gt;Hundreds of child components update unnecessarily&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This can hurt performance, responsiveness, and even battery usage on mobile devices.&lt;/p&gt;

&lt;p&gt;Without memoization every update causes new rendering work - even for unchanged content.&lt;/p&gt;

&lt;p&gt;With memoization Vue can skip rendering when dependencies stay the same which reduces DOM operations, Virtual DOM diffing, and in general component work.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 What Is &lt;code&gt;v-memo&lt;/code&gt; in Vue?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;v-memo&lt;/code&gt; is a Vue directive that memoizes part of a template.&lt;/p&gt;

&lt;p&gt;Basic example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-memo=&lt;/span&gt;&lt;span class="s"&gt;"[value]"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  {{ expensiveContent }}
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vue will only re-render this block when &lt;code&gt;value&lt;/code&gt; changes. Otherwise Vue reuses the previous rendered result.&lt;/p&gt;

&lt;p&gt;Let’s imagine a large user list.&lt;/p&gt;

&lt;p&gt;Without &lt;code&gt;v-memo&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&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="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&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="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"counter++"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
    &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"user in users"&lt;/span&gt;
    &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"user.id"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every counter update re-renders the whole list even though users never changed.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;v-memo&lt;/code&gt; we can:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&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="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&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="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"counter++"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
    &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"user in users"&lt;/span&gt;
    &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"user.id"&lt;/span&gt;
    &lt;span class="na"&gt;v-memo=&lt;/span&gt;&lt;span class="s"&gt;"[user.id]"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now counter updates still happen but unchanged list items are skipped. This becomes extremely valuable for large lists, dashboards, or tables.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 When NOT to Use It
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;v-memo&lt;/code&gt; is not needed everywhere as Vue is already highly optimized.&lt;/p&gt;

&lt;p&gt;Avoid using it for tiny components, static content, or premature optimization as overusing memoization can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reduce readability&lt;/li&gt;
&lt;li&gt;make debugging harder&lt;/li&gt;
&lt;li&gt;introduce stale UI bugs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🧪 Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;v-memo&lt;/code&gt; only for measurable bottlenecks&lt;/li&gt;
&lt;li&gt;Great for large dynamic lists&lt;/li&gt;
&lt;li&gt;Keep dependency arrays minimal&lt;/li&gt;
&lt;li&gt;Avoid premature optimization&lt;/li&gt;
&lt;li&gt;Profile performance before optimizing&lt;/li&gt;
&lt;li&gt;Combine with virtual scrolling for huge datasets&lt;/li&gt;
&lt;li&gt;Prefer stable keys and predictable state updates&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📖 Learn more
&lt;/h2&gt;

&lt;p&gt;If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this &lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&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%2Fj7hlfz848ut2d9ly8i8q.png" alt="Vue School Link" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Advance skills
&lt;/h2&gt;

&lt;p&gt;A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success.&lt;/p&gt;

&lt;p&gt;Check out Certificates.dev by clicking this &lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&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%2F9iledpqv69huancwg283.png" alt="Certificates.dev Link" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more!&lt;/p&gt;

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

&lt;p&gt;Memoization is a powerful optimization technique that helps avoid unnecessary work.&lt;/p&gt;

&lt;p&gt;In this article, you learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What memoization is&lt;/li&gt;
&lt;li&gt;What problem it solves&lt;/li&gt;
&lt;li&gt;How Vue’s &lt;code&gt;v-memo&lt;/code&gt; works&lt;/li&gt;
&lt;li&gt;Practical examples for lists and components&lt;/li&gt;
&lt;li&gt;When to use it — and when not to&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Take care!&lt;br&gt;
And happy coding as always 🖥️&lt;/p&gt;

</description>
      <category>performance</category>
      <category>vue</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Why Loaders Matter for Performance</title>
      <dc:creator>Jakub Andrzejewski</dc:creator>
      <pubDate>Mon, 11 May 2026 09:29:43 +0000</pubDate>
      <link>https://dev.to/jacobandrewsky/why-loaders-matter-for-performance-4b8a</link>
      <guid>https://dev.to/jacobandrewsky/why-loaders-matter-for-performance-4b8a</guid>
      <description>&lt;p&gt;When developers think about performance optimization, they usually focus on things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lazy loading&lt;/li&gt;
&lt;li&gt;caching&lt;/li&gt;
&lt;li&gt;image optimization&lt;/li&gt;
&lt;li&gt;bundle size&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And while those things absolutely matter there’s another area that heavily impacts user experience -&amp;gt; Loading states and layout stability.&lt;/p&gt;

&lt;p&gt;A badly implemented loading experience can make an app feel slow, jumpy, or frustrating to use. This is strongly connected to an important Core Web Vital metric Cumulative Layout Shift (CLS).&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What CLS is&lt;/li&gt;
&lt;li&gt;Why loaders are critical for perceived performance&lt;/li&gt;
&lt;li&gt;How poor loading states hurt UX&lt;/li&gt;
&lt;li&gt;Practical examples in Vue&lt;/li&gt;
&lt;li&gt;Best practices for stable layouts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 What Is Cumulative Layout Shift (CLS)?
&lt;/h2&gt;

&lt;p&gt;CLS measures how much elements unexpectedly move during page loading.&lt;/p&gt;

&lt;p&gt;Example of bad CLS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Text suddenly jumps down&lt;/li&gt;
&lt;li&gt;Buttons move while you try to click&lt;/li&gt;
&lt;li&gt;Images appear late and push content around&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’ve all experienced websites like this:&lt;/p&gt;

&lt;p&gt;👉 You try to click something… and suddenly the layout shifts. Extremely annoying.&lt;/p&gt;

&lt;p&gt;Why does this happen? Usually because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;content loads asynchronously&lt;/li&gt;
&lt;li&gt;elements have no reserved space&lt;/li&gt;
&lt;li&gt;loaders are missing&lt;/li&gt;
&lt;li&gt;images don’t define dimensions&lt;/li&gt;
&lt;li&gt;components suddenly appear&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why does CLS matter? Because it affects user experience, accessibility, or mobile usability (and obviously Google Core Web Vitals). Even if your app is technically fast poor layout stability can make it feel slow.&lt;/p&gt;

&lt;p&gt;👉 Users care more about &lt;strong&gt;perceived performance&lt;/strong&gt; than actual milliseconds.&lt;/p&gt;

&lt;p&gt;A good loader communicates progress, prevents layout jumping, and makes apps feel responsive&lt;/p&gt;

&lt;p&gt;A bad or missing loader creates uncertainty. Users start thinking:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Did the app freeze?”&lt;/li&gt;
&lt;li&gt;“Is something broken?”&lt;/li&gt;
&lt;li&gt;“Why is everything moving?”&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🟢 Implementing proper loaders in Vue
&lt;/h2&gt;

&lt;p&gt;Let's take a look at the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&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;loading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &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;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchUsers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"loading"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"skeleton-list"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
      &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"n in 5"&lt;/span&gt;
      &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"n"&lt;/span&gt;
      &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"skeleton-card"&lt;/span&gt;
    &lt;span class="nt"&gt;/&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;UserCard&lt;/span&gt;
    &lt;span class="na"&gt;v-else&lt;/span&gt;
    &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"user in users"&lt;/span&gt;
    &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"user.id"&lt;/span&gt;
    &lt;span class="na"&gt;:user=&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt; &lt;span class="na"&gt;scoped&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nc"&gt;.skeleton-card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;120px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&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;/&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We fetch users, but when the fetch is in progress we display the same hard coded number of loaders/skeletons. When the users are loaded there is no layout shift as it occupies the same space improving perceived performance and User Experience.&lt;/p&gt;

&lt;p&gt;If we don't know how many results there will be, we have to assume some number but it is still better than not having skeletons at all :)&lt;/p&gt;

&lt;p&gt;Many apps still use simple spinners or text/icon loaders like:&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&amp;gt;&lt;/span&gt;Loading...&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But modern UX usually prefers Skeleton loaders because they mimic final layout, reduce layout shift, and improve perceived speed.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prefer skeleton loaders over tiny spinners&lt;/li&gt;
&lt;li&gt;Reserve space before content loads&lt;/li&gt;
&lt;li&gt;Keep loading and final layouts similar&lt;/li&gt;
&lt;li&gt;Always define image dimensions&lt;/li&gt;
&lt;li&gt;Avoid injecting large content suddenly&lt;/li&gt;
&lt;li&gt;Test CLS using Lighthouse or Core Web Vitals tools&lt;/li&gt;
&lt;li&gt;Think about perceived performance — not just raw speed&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📖 Learn more
&lt;/h2&gt;

&lt;p&gt;If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this &lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&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%2Fj7hlfz848ut2d9ly8i8q.png" alt="Vue School Link" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Advance skills
&lt;/h2&gt;

&lt;p&gt;A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success.&lt;/p&gt;

&lt;p&gt;Check out Certificates.dev by clicking this &lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&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%2F9iledpqv69huancwg283.png" alt="Certificates.dev Link" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more!&lt;/p&gt;

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

&lt;p&gt;Loaders are much more important than most developers realize.&lt;/p&gt;

&lt;p&gt;In this article, you learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What Cumulative Layout Shift (CLS) is&lt;/li&gt;
&lt;li&gt;Why poor loading states hurt UX&lt;/li&gt;
&lt;li&gt;How skeleton loaders improve perceived performance&lt;/li&gt;
&lt;li&gt;How to avoid layout jumping in Vue and other frameworks&lt;/li&gt;
&lt;li&gt;Best practices for stable, responsive interfaces&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fast apps are great.&lt;/p&gt;

&lt;p&gt;But apps that &lt;strong&gt;feel smooth and stable&lt;/strong&gt; are what users truly remember.&lt;/p&gt;

&lt;p&gt;Take care!&lt;br&gt;
And happy coding as always 🖥️&lt;/p&gt;

</description>
      <category>vue</category>
      <category>performance</category>
      <category>tutorial</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to Safely Allow Inline Scripts Without Breaking Security with CSP Nonce</title>
      <dc:creator>Jakub Andrzejewski</dc:creator>
      <pubDate>Mon, 27 Apr 2026 06:46:57 +0000</pubDate>
      <link>https://dev.to/jacobandrewsky/how-to-safely-allow-inline-scripts-without-breaking-security-with-csp-nonce-3a2j</link>
      <guid>https://dev.to/jacobandrewsky/how-to-safely-allow-inline-scripts-without-breaking-security-with-csp-nonce-3a2j</guid>
      <description>&lt;p&gt;When building modern web applications, security is not optional. One of the most important protections you can add is a &lt;strong&gt;Content Security Policy (CSP)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But here’s the catch:&lt;/p&gt;

&lt;p&gt;👉 CSP often &lt;strong&gt;blocks inline scripts and styles&lt;/strong&gt; — which can break your app.&lt;/p&gt;

&lt;p&gt;So how do you keep your app secure &lt;strong&gt;without disabling useful features&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;That’s where &lt;strong&gt;CSP nonce&lt;/strong&gt; comes in - it allows you to safely execute inline code &lt;strong&gt;without opening security holes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What CSP nonce is&lt;/li&gt;
&lt;li&gt;What problem it solves&lt;/li&gt;
&lt;li&gt;How to implement it&lt;/li&gt;
&lt;li&gt;How it works automatically in Nuxt with &lt;code&gt;nuxt-security&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Best practices and common pitfalls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 What Is CSP Nonce?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;nonce&lt;/strong&gt; (short for &lt;em&gt;number used once&lt;/em&gt;) is a &lt;strong&gt;unique, random value generated for each request&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is used in CSP to explicitly allow trusted inline scripts or styles.&lt;/p&gt;

&lt;p&gt;Example:&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;nonce=&lt;/span&gt;&lt;span class="s"&gt;"abc123"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Secure inline script&lt;/span&gt;&lt;span class="dl"&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;And in your HTTP headers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Content-Security-Policy: script-src 'nonce-abc123'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser will only execute scripts that have a matching nonce.&lt;/p&gt;

&lt;p&gt;CSP nonce is a &lt;strong&gt;whitelist mechanism&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only scripts with the correct nonce are allowed&lt;/li&gt;
&lt;li&gt;Everything else is blocked&lt;/li&gt;
&lt;li&gt;The nonce changes on every request&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes it extremely effective against &lt;strong&gt;XSS (Cross-Site Scripting)&lt;/strong&gt; attacks.&lt;/p&gt;

&lt;p&gt;CSP nonce is commonly used for:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;SSR frameworks - Injecting initial state, Hydration scripts&lt;/li&gt;
&lt;li&gt;Analytics / tracking snippets - Inline scripts required by providers&lt;/li&gt;
&lt;li&gt;Critical inline scripts - Small scripts needed before app bootstraps&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🟢 What Problem Does CSP Nonce Solve?
&lt;/h2&gt;

&lt;p&gt;Without nonce, you usually face a trade-off:&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Allow inline scripts (unsafe)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Content-Security-Policy: script-src 'unsafe-inline'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opens the door to XSS attacks&lt;/li&gt;
&lt;li&gt;Any injected script can run&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Block inline scripts completely
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Content-Security-Policy: script-src 'self'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;breaks inline event handlers&lt;/li&gt;
&lt;li&gt;breaks injected scripts (SSR hydration, state)&lt;/li&gt;
&lt;li&gt;breaks some frameworks&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🟢 How to Implement CSP Nonce
&lt;/h2&gt;

&lt;p&gt;The process is relatively simple but let's break it down and explain each step individually.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Generate a nonce per request
&lt;/h3&gt;

&lt;p&gt;Example (Node.js):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;crypto&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;crypto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateNonce&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="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Add it to response headers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nonce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateNonce&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Security-Policy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;`script-src 'nonce-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nonce&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Inject it into your HTML
&lt;/h3&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;nonce=&lt;/span&gt;&lt;span class="s"&gt;"{{nonce}}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&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;__INITIAL_STATE__&lt;/span&gt; &lt;span class="o"&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;h3&gt;
  
  
  ⚠️ Critical rule
&lt;/h3&gt;

&lt;p&gt;The nonce in the header and HTML &lt;strong&gt;must match exactly&lt;/strong&gt;. Otherwise, script will be blocked and app may break silently.&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 CSP Nonce in Nuxt (with nuxt-security)
&lt;/h2&gt;

&lt;p&gt;If you’re using Nuxt, things get much easier thanks to &lt;strong&gt;nuxt-security&lt;/strong&gt; module that can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatically generate nonce per request&lt;/li&gt;
&lt;li&gt;Inject it into CSP headers&lt;/li&gt;
&lt;li&gt;Attach it to scripts/styles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It makes it much easier to work with CSP nonces in Nuxt. Let's take a look at the following configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineNuxtConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;modules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nuxt-security&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;security&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;contentSecurityPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script-src&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;'self'&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;'nonce-{{nonce}}'&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What happens automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nuxt generates a nonce per request&lt;/li&gt;
&lt;li&gt;Replaces &lt;code&gt;{{nonce}}&lt;/code&gt; in headers&lt;/li&gt;
&lt;li&gt;Applies nonce to inline scripts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don’t need to manually wire everything&lt;/p&gt;

&lt;p&gt;You can read more here:&lt;br&gt;
&lt;a href="https://nuxt-security.vercel.app/" rel="noopener noreferrer"&gt;https://nuxt-security.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🟢 Common Mistakes
&lt;/h2&gt;

&lt;p&gt;Let's take a look at the list of common mistakes to understand what to look for:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;❌ Reusing the same nonce - Nonce must be unique per request and cryptographically random&lt;/li&gt;
&lt;li&gt;❌ Forgetting to apply nonce in HTML - if you only set CSP header the scripts will still be blocked&lt;/li&gt;
&lt;li&gt;❌ Mixing nonce with unsafe-inline - &lt;code&gt;script-src 'unsafe-inline' 'nonce-abc'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;❌ Caching issues - if HTML is cached nonce may not match header&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🧪 Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Generate nonce &lt;strong&gt;per request&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Use secure randomness (&lt;code&gt;crypto&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Never reuse nonce&lt;/li&gt;
&lt;li&gt;Avoid &lt;code&gt;unsafe-inline&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Use frameworks/tools (like nuxt-security)&lt;/li&gt;
&lt;li&gt;Test CSP in &lt;strong&gt;report-only mode&lt;/strong&gt; first&lt;/li&gt;
&lt;li&gt;Monitor browser console for CSP violations&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📖 Learn more
&lt;/h2&gt;

&lt;p&gt;If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this &lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vueschool.io/courses?friend=baroshem" rel="noopener noreferrer"&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%2Fj7hlfz848ut2d9ly8i8q.png" alt="Vue School Link" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Advance skills
&lt;/h2&gt;

&lt;p&gt;A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success.&lt;/p&gt;

&lt;p&gt;Check out Certificates.dev by clicking this &lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&gt;link&lt;/a&gt; or by clicking the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://certificates.dev/?friend=JAKUB" rel="noopener noreferrer"&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%2F9iledpqv69huancwg283.png" alt="Certificates.dev Link" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more!&lt;/p&gt;

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

&lt;p&gt;CSP nonce is a powerful mechanism that allows you to safely use inline scripts while maintaining strong security.&lt;/p&gt;

&lt;p&gt;In this article, you learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What CSP nonce is and how it works&lt;/li&gt;
&lt;li&gt;What problem it solves (security vs flexibility)&lt;/li&gt;
&lt;li&gt;How to implement it step by step&lt;/li&gt;
&lt;li&gt;How Nuxt + nuxt-security handle it automatically&lt;/li&gt;
&lt;li&gt;Common mistakes and best practices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Take care!&lt;br&gt;
And happy coding as always 🖥️&lt;/p&gt;

</description>
      <category>security</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
