<?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>Forem: Matteo Fogli</title>
    <description>The latest articles on Forem by Matteo Fogli (@pecus).</description>
    <link>https://forem.com/pecus</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F372395%2F4dea940f-f2c4-4dd7-9e8a-4fe23c743ee9.jpeg</url>
      <title>Forem: Matteo Fogli</title>
      <link>https://forem.com/pecus</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/pecus"/>
    <language>en</language>
    <item>
      <title>How to share SASS variables with JavaScript code in VueJS</title>
      <dc:creator>Matteo Fogli</dc:creator>
      <pubDate>Mon, 28 Sep 2020 13:53:51 +0000</pubDate>
      <link>https://forem.com/pecus/how-to-share-sass-variables-with-javascript-code-in-vuejs-55p3</link>
      <guid>https://forem.com/pecus/how-to-share-sass-variables-with-javascript-code-in-vuejs-55p3</guid>
      <description>&lt;p&gt;Having a single variable declaration that works across different coding languages is a goal every developer strives to reach, no matter the technology or framework they adopt. It brings together convenience (update the value once, see it working everywhere) with consistency and lower runtime error rates.&lt;/p&gt;

&lt;p&gt;This post explains how to share variables between Sass and JavaScript in VueJS. It will be useful every time you have layout constraints that need to be shared with front-end logic. The opposite case, where business logic determines styles update, is mostly solved with inline styles on DOM elements and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/--*"&gt;CSS Custom Properties&lt;/a&gt;. CSS Custom Properties are well supported, but if you are looking for a solution based on SASS, keep on reading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Export variables from SASS/SCSS
&lt;/h2&gt;

&lt;p&gt;We can use a feature borrowed from CSS Modules to &lt;em&gt;export&lt;/em&gt; SASS variables and make them available as imports to JavaScript code. We combine a syntax &lt;a href="https://github.com/css-modules/icss#export"&gt;&lt;code&gt;:export&lt;/code&gt;&lt;/a&gt; with a webpack loader &lt;a href="https://github.com/webpack-contrib/css-loader"&gt;CSS Loader&lt;/a&gt; that provides the exported values to JavaScript imports. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;:export&lt;/code&gt; is implemented as a pseudo-selector and as such is completely transparent to SASS:&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="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;your-sass-var&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;#663399&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;:export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;variablename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;your-sass-var&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 declares an SCSS variable and exports it under the &lt;code&gt;variablename&lt;/code&gt; identifier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Import SASS/SCSS variables in JavaScript
&lt;/h2&gt;

&lt;p&gt;The easiest way to import your exported SASS variables is to import the SASS file itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;exportedVars&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;./path/to/file.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But with Vue, we rarely author styles as independent SCSS or SASS files. Most of the time you’d author Single File Components, a custom VueJS file format that uses HTML-like syntax to describe a Vue component, usually including a &lt;code&gt;template&lt;/code&gt;, a &lt;code&gt;script&lt;/code&gt; and a &lt;code&gt;style&lt;/code&gt; block.&lt;/p&gt;

&lt;p&gt;So how do you import only the style code block from a SFC? It took me a while to find the answer, but the hint is &lt;em&gt;"the same way webpack does"&lt;/em&gt;. You ask &lt;a href="https://github.com/vuejs/vue-loader#how-it-works"&gt;Vue Loader&lt;/a&gt; to do it for you.&lt;/p&gt;

&lt;p&gt;Vue Loader turns a single file into an export of three (or more) files. In doing so, it rewrites the source filename with a syntax that allows to address a specific block. Like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;exportedVars&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;./path/to/file.vue?vue&amp;amp;type=style&amp;amp;index=0&amp;amp;lang=scss&amp;amp;module=1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;./path/to/file.vue&lt;/code&gt; is your usual reference to the target file. If you are importing from the style block within the same SFC, use &lt;code&gt;./yourcomponentname.vue&lt;/code&gt;. Next is the &lt;code&gt;?vue&lt;/code&gt; query string part. This allows Vue Loader to understand it has already &lt;em&gt;destructured&lt;/em&gt; the SFC into parts and should provide the code block based on its type and index. &lt;code&gt;&amp;amp;type=style&lt;/code&gt;, &lt;code&gt;&amp;amp;index=0&lt;/code&gt; and &lt;code&gt;&amp;amp;lang=scss&lt;/code&gt; allow Vue Loader to fetch the correct block and pass it to the correct preprocessor.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;index&lt;/code&gt; parameter allows to address multiple &lt;code&gt;style&lt;/code&gt; blocks that might be in an SFC.&lt;/p&gt;

&lt;p&gt;Lastly, more recent versions of vue-loader strictly enforce exports for CSS modules only. Appending &lt;code&gt;&amp;amp;module=1&lt;/code&gt; provides a default export when self importing our styles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Use your imported variables
&lt;/h2&gt;

&lt;p&gt;Sass variables are accessible as properties of the identifier used for import, e.g. &lt;code&gt;identifier.variablename&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;Here is a complete (and simplicistic) full 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;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Andy Kaufman &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;lyrics&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/p&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;/&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="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styles&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;./ManOnTheMoon.vue?vue&amp;amp;type=style&amp;amp;index=0&amp;amp;lang=scss&amp;amp;module=1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&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;ManOnTheMoon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;lyrics&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lyrics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&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;lang=&lt;/span&gt;&lt;span class="s"&gt;"scss"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nv"&gt;$lyrics&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;' in the wrestling match'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;:export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;lyrics&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$lyrics&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;Which will display the phrase: "Andy Kaufman in the wrestling match"&lt;sup&gt;1&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; that all variables are exported as strings. Use type casting and conversion if you need to coerce a value to number or boolean.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;This article focuses on VueJS, but this approach is valid with any framework or build pipeline that relies on webpack with css-loader.&lt;/p&gt;

&lt;p&gt;CSS Custom Properties (AKA CSS Vars) provide an even smoother implementation: you can read and update custom properties via &lt;code&gt;element.style.getPropertyValue()&lt;/code&gt; and &lt;code&gt;element.style.setProperty()&lt;/code&gt; respectively, and I encourage you to make the switch and adopt CSS Custom Properties in place of SASS vars (even within SASS!). Yet,  this solution can be useful if you already have a fully developed project built on SASS variables where refactoring to CSS Custom Properties is not an option.&lt;/p&gt;




&lt;p&gt;&lt;small&gt;&lt;/small&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you caught the reference in the example, I suspect that you’ll be singing "Yeah, yeah, yeah, yeah" in your head by now. At &lt;a href="https://modo.md"&gt;modo&lt;/a&gt; we can't miss a chance to drop an R.E.M. reference if we can 😬&lt;/li&gt;
&lt;li&gt;
&lt;span&gt;Cover Photo by &lt;a href="https://unsplash.com/@aznbokchoy?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Lucas Benjamin&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/abstract?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>vue</category>
      <category>css</category>
      <category>webpack</category>
    </item>
    <item>
      <title>When to avoid VueJs Computed Properties for greater performance</title>
      <dc:creator>Matteo Fogli</dc:creator>
      <pubDate>Fri, 14 Aug 2020 17:11:24 +0000</pubDate>
      <link>https://forem.com/pecus/when-to-avoid-vuejs-computed-properties-for-greater-performance-5anj</link>
      <guid>https://forem.com/pecus/when-to-avoid-vuejs-computed-properties-for-greater-performance-5anj</guid>
      <description>&lt;p&gt;VueJs is fast, easy to learn, reactive framework. It offers a gentle learning curve and a rich developer experience, with powerful inspection and CLI based tools.&lt;/p&gt;

&lt;p&gt;At &lt;a href="https://modo.md" rel="noopener noreferrer"&gt;modo&lt;/a&gt;, we use Vue for most of our dynamic frontend projects: we like it for its clear separation of concerns, easily composable components, a wide range of build options (from Single Page Applications to standalone Web Components) and for being generally very well performing out–of–the–box.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Computed Properties&lt;/li&gt;
&lt;li&gt;What happens inside computed properties&lt;/li&gt;
&lt;li&gt;How and when to avoid computed properties&lt;/li&gt;
&lt;li&gt;Going from a few milliseconds to tens of seconds of execution (and back) &lt;/li&gt;
&lt;li&gt;Performance by design&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Computed Properties &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Among the many traits of VueJs that are optimized for computational and rendering performance are &lt;strong&gt;computed properties&lt;/strong&gt;. Computed properties are component functions that return a value. They are reactive, in that they are automatically updated whenever one of  the values used for computing the property changes, and can be used in templates and component logic.&lt;/p&gt;

&lt;p&gt;The real power (and the true difference in comparison to component methods) is that computed properties are cached.&lt;/p&gt;

&lt;p&gt;While component methods are executed at every rendering of the component, computed properties are evaluated conditionally: if none of the dependency has changed, the property is not recomputed and the cache value is used, saving a considerable amount of runtime execution. Component re–rendering thus happens considerably faster, as the runtime engine can skip re–evaluating potentially expensive data, relying instead on the cached value.&lt;/p&gt;

&lt;p&gt;If you’re not familiar with computed properties, you can read more in the &lt;a href="https://vuejs.org/v2/guide/computed.html#Computed-Properties" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;, but for the sake of this article a simple use case can help.&lt;/p&gt;

&lt;p&gt;Suppose we have a list of books, and a component that should filter them based on a condition, let’s say a matching text in the title.&lt;/p&gt;

&lt;p&gt;Our code would probably look like this:&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;section&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"c-book"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Your search for &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;bookQuery&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt; returned &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;filteredBookList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt; books&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"filteredBookList.length"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"c-book__list"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"book in filteredBookList"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"book.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;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/section&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="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&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;BookFilter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;bookList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;required&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="na"&gt;bookQuery&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&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="na"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;filteredBookList &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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bookList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;book&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bookQuery&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&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;Our component and application would probably have additional logic and greater complexity, but this example should be good enough to show how computed properties work. &lt;code&gt;filteredBookList&lt;/code&gt; returns a copy of the array of books, filtered with those that include the search query (&lt;code&gt;bookQuery&lt;/code&gt;) in their title. The value is then cached by Vue, and will not be recomputed unless either &lt;code&gt;bookList&lt;/code&gt; or &lt;code&gt;bookQuery&lt;/code&gt; change.&lt;/p&gt;

&lt;p&gt;An important tidbit to remember, tightly coupled with their &lt;em&gt;cacheability&lt;/em&gt;, is that &lt;strong&gt;computed properties must be evaluated synchronously&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens inside computed properties &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;We’re not going to deep dive into Vue internals. If you are interested, VueMastery has produced a series of videos with Evan You coding &lt;a href="https://www.vuemastery.com/courses/vue3-deep-dive-with-evan-you/vue3-overview/" rel="noopener noreferrer"&gt;step–by–step, high level, simplified demos of how VueJs works&lt;/a&gt;. You can also inspect &lt;a href="https://github.com/vuejs/vue" rel="noopener noreferrer"&gt;Vue source code&lt;/a&gt; and, for this specific case, I found &lt;a href="https://medium.com/dailyjs/tracing-or-debugging-vue-js-reactivity-the-computed-tree-9da0ba1df5f9" rel="noopener noreferrer"&gt;this article by Michael Gallagher&lt;/a&gt; very inspiring. &lt;/p&gt;

&lt;p&gt;So, to make it short, in version 2.x, &lt;a href="https://vuejs.org/v2/guide/reactivity.html#How-Changes-Are-Tracked" rel="noopener noreferrer"&gt;Vue tracks reactivity using &lt;em&gt;getters&lt;/em&gt; and &lt;em&gt;setters&lt;/em&gt;&lt;/a&gt; (&lt;a href="https://medium.com/the-vue-point/plans-for-the-next-iteration-of-vue-js-777ffea6fabf#ba44" rel="noopener noreferrer"&gt;Version 3 will use &lt;em&gt;proxies&lt;/em&gt;&lt;/a&gt;, and will also provide better tracing and debugging of reactivity. It is currently a Release Candidate).&lt;/p&gt;

&lt;p&gt;To understand why computed properties can bite back in specific cases, we need to remember that Vue needs to track each dependency of a computed property. This can be expensive if these variables are large arrays, or complex, nested objects, or a combination of both, as in the case I found out. &lt;/p&gt;

&lt;p&gt;In case of circular dependencies (a computed property depending on another computed property), Vue also needs to stabilize values and might have to &lt;a href="https://github.com/vuejs/vue/issues/622#issuecomment-66470072" rel="noopener noreferrer"&gt;iterate the evaluation twice&lt;/a&gt; to ensure that values don’t change within the current update cycle.&lt;/p&gt;

&lt;p&gt;All of this can add up significantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  How and when to avoid computed properties &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Despite all the praises I’ve written so far for computed properties, there are cases in which you might want or even &lt;em&gt;need&lt;/em&gt; to avoid them.&lt;/p&gt;

&lt;p&gt;The simplest case is if you need a &lt;em&gt;static&lt;/em&gt; computed value, that is a value that needs to be calculated only once, no matter how data in your component will change.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;options API&lt;/em&gt; of VueJs 2.x does not make it particularly evident, but declaring any property inside the component &lt;em&gt;created&lt;/em&gt; function makes it available to both the component logic and the component template.&lt;/p&gt;

&lt;p&gt;Let’s see this in code, with our book example:&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;section&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"c-book"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Your search for &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;bookQuery&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt; returned &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;filteredBookList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt; books&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"filteredBookList.length"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"c-book__list"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"book in filteredBookList"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"book.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;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;footer&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;productName&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt; v&lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;productVersion&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/footer&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/section&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="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// let’s import the name and version number from package.json&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;productVersion&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;productName&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="s2"&gt;../package.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&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;BookFilter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;bookList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;required&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="na"&gt;bookQuery&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&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="na"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;filteredBookList &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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bookList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;book&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bookQuery&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="nf"&gt;created&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// once the component has been created, we can add non reactive properties to it.&lt;/span&gt;
    &lt;span class="c1"&gt;// this data is static and will never be tracked by Vue&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;productVersion&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;productName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&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;&lt;small&gt;&lt;a href="https://codesandbox.io/s/book-search-vue-demo-pk4hh?file=/src/App.vue" rel="noopener noreferrer"&gt;See this example on CodeSandbox&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;In the above example, the product name and version are completely static. They are imported from the &lt;code&gt;package.json&lt;/code&gt; file and used in the template as if they were any other computed or reactive property.&lt;/p&gt;

&lt;p&gt;You could still define &lt;code&gt;productVersion&lt;/code&gt; and &lt;code&gt;productName&lt;/code&gt; as computed properties: Vue would not track values that are not registered in the reactive system, but this approach becomes useful when you need to explicitely avoid having Vue track a large array or object.&lt;/p&gt;

&lt;p&gt;In our example above, &lt;code&gt;bookList&lt;/code&gt; is reactive. It is passed to the component as a prop, and therefore tracked for reactivity changes. The component needs to update should the list change. If the list is very large and includes complex objects, we’re adding an unnecessary overhead to the reactivity system. We’re not reacting to changes in &lt;code&gt;bookList&lt;/code&gt;: we’re reacting only to changes in &lt;code&gt;bookQuery&lt;/code&gt;! The list of books stays the same, no matter the search the user performs.&lt;/p&gt;

&lt;p&gt;This might not be intuitive, and most of the time Vue is forgiving because its internal optimizations favour speed. But every time we know that some data does not need to ever be re–evaluated, we should &lt;strong&gt;design for performance&lt;/strong&gt; and make it available as a static property.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;&lt;a href="https://codesandbox.io/s/book-search-vue-demo-static-list-qcxeh?file=/src/main.js" rel="noopener noreferrer"&gt;See the final example on CodeSandbox&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Going from a few milliseconds to tens of seconds of execution (and back) &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The book example described above has many similarities with a project I worked on recently. This project needed to handle an array of around 10.000 objects, and filter them dynamically based on various query types.&lt;/p&gt;

&lt;p&gt;In a particular scenario, the performance of the app degraded significantly, blocking the browser main thread for several seconds and making the browser completely unresponsive. Granted, the app was managing a lot of data: the JSON representation of the array was ~19Mb of data. But the slowdown was not due to the data size.&lt;/p&gt;

&lt;p&gt;The code for filtering the array was not at fault. An isolated case in plain JavaScript performing the same filtering took only a few milliseconds, no matter the code style (functional or imperative) or the complexity of the filter function.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;the greatest advantage of a computed property can sometime become its greatest defect&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To troubleshoot the issue, I used the performance profiler of Firefox DevTools to generate a &lt;a href="https://developer.mozilla.org/en-US/docs/Tools/Performance/Flame_Chart" rel="noopener noreferrer"&gt;flame chart&lt;/a&gt;. This showed where the application was spending time in long tasks that blocked the browser main thread. Reading the chart provided some insight: it turned out that the greatest advantage of computed properties sometimes becomes a performance bottleneck. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.prod.mdn.mozit.cloud%2Fattachments%2F2015%2F05%2F29%2F10989%2F49567ba0c0d3027e27a9daed10364417%2Fperf-flame-chart-overview.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.prod.mdn.mozit.cloud%2Fattachments%2F2015%2F05%2F29%2F10989%2F49567ba0c0d3027e27a9daed10364417%2Fperf-flame-chart-overview.png" alt="A flame chart from Firefox DevTools"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tracking dependencies has a cost. Most of the time this cost is negligible, especially compared to the advantage provided by cached values and a fast, reactive frontend. In our app, this cost was acceptable when the component tracked in total one list of items. But when tracking two, and combining this cost with the cost generated on the heap and the call stack by a high number of callback functions—such as the one used to &lt;code&gt;filter()&lt;/code&gt; a large array—it blocked the browser event loop and made the application unresponsive.&lt;/p&gt;

&lt;p&gt;To solve it, as explained above, we removed the list of items to search from the reactivity system. In retrospect it was a mistake to add it from the beginning, since it never changes and never needs to be tracked for updates. The array is now filtered once inside the &lt;code&gt;created()&lt;/code&gt; function and the resulting value added as a non–reactive property to the component. We’re back in the milliseconds range of updates. Yeah! 🍾&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance by design &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Despite working with VueJs for years, this was the first time we hit a performance penalty this severe. VueJs 3.x has a lot of internal improvements and might perform flawlessly in this scenario (we haven’t tested it yet). But if you’re still relying on VueJs 2, and like us are obsessed with performance, I hope this helps you if you ever experience an unexpected slowdown in your VueJs code. And if it’s really puzzling, &lt;strong&gt;you might want to let us take a look at it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;&lt;span&gt;Cover photo by &lt;a href="https://unsplash.com/@heyeje?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Heye Jensen&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/u-turn?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;&lt;/small&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>webperf</category>
    </item>
  </channel>
</rss>
