<?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: Allan N Jeremy</title>
    <description>The latest articles on Forem by Allan N Jeremy (@allanjeremy).</description>
    <link>https://forem.com/allanjeremy</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%2F38761%2F432d6d4d-ed1c-497d-892e-162721321156.jpg</url>
      <title>Forem: Allan N Jeremy</title>
      <link>https://forem.com/allanjeremy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/allanjeremy"/>
    <language>en</language>
    <item>
      <title>How to retry failed steps in GitHub Action Workflows</title>
      <dc:creator>Allan N Jeremy</dc:creator>
      <pubDate>Wed, 07 Dec 2022 09:41:54 +0000</pubDate>
      <link>https://forem.com/thisdotmedia/how-to-retry-failed-steps-in-github-action-workflows-fkl</link>
      <guid>https://forem.com/thisdotmedia/how-to-retry-failed-steps-in-github-action-workflows-fkl</guid>
      <description>&lt;p&gt;Sometimes things can go wrong in your  &lt;a href="https://docs.github.com/en/actions/using-workflows"&gt;GitHub Action workflow&lt;/a&gt; step(s) and you may want to retry the step(s). This article will cover 2 ways to approach the retrying of steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pre-requisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://git-scm.com/"&gt;Git&lt;/a&gt; (should be installed in your path)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/"&gt;GitHub account&lt;/a&gt; - we'll need this to use GitHub actions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Initial setup
&lt;/h2&gt;

&lt;p&gt;In order to follow along, here are the steps you can take to setup your GitHub actions workflow.&lt;/p&gt;

&lt;h4&gt;
  
  
  Initialize your git repository
&lt;/h4&gt;

&lt;p&gt;In your terminal, run &lt;code&gt;git init&lt;/code&gt; to create an empty git repository or skip this step if you already have an existing git repository.&lt;/p&gt;

&lt;h4&gt;
  
  
  Create workflow file
&lt;/h4&gt;

&lt;p&gt;GitHub workflow files are usually &lt;code&gt;.yaml/.yml&lt;/code&gt; files that contain a series of jobs and steps to be executed by GitHub actions. These files often reside in  &lt;code&gt;.github/workflows&lt;/code&gt;. If the directories do not exist, go ahead and create them.  Create a file  &lt;code&gt;retry.yml&lt;/code&gt;  in  &lt;code&gt;.github/workflows&lt;/code&gt;. For now, the file can contain the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Retry&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;action&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;using&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;retry&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;step"&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# This action is called when this is pushed to github&lt;/span&gt;
    &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# This action can be manually triggered&lt;/span&gt;
    &lt;span class="na"&gt;workflow_call&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# This name is up to you&lt;/span&gt;
    &lt;span class="na"&gt;retry-job&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ubuntu-latest"&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;My Job&lt;/span&gt;
        &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout repository&lt;/span&gt;
              &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Print&lt;/span&gt;
              &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
                &lt;span class="s"&gt;echo 'Hello'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing your workflow
&lt;/h2&gt;

&lt;p&gt;You can test your GitHub Action workflow by pushing your changes to GitHub and going to the &lt;code&gt;actions&lt;/code&gt; tab of the repository or you can choose to test locally using act. &lt;/p&gt;

&lt;h1&gt;
  
  
  Retrying failed steps
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Approach 1: Using the &lt;a href="https://github.com/marketplace/actions/retry-step"&gt;retry-step&lt;/a&gt; action
&lt;/h2&gt;

&lt;p&gt;By using the using the &lt;a href="https://github.com/marketplace/actions/retry-step"&gt;retry-step action&lt;/a&gt;, we can retry any failed shell commands. If our step or series of steps are shell commands then we can use the &lt;code&gt;retry-step&lt;/code&gt; action to retry them. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If however you'd like to try retry a step that is using another action, then the &lt;code&gt;retry-step&lt;/code&gt; action will NOT work for you. In that case, you may want to try the alternative steps mentioned below.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Modify your action file to contain the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Retry&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;action&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;using&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;retry&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;step"&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# This action is called when this is pushed to github&lt;/span&gt;
    &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# This action can be manually triggered&lt;/span&gt;
    &lt;span class="na"&gt;workflow_call&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# This name is up to you&lt;/span&gt;
    &lt;span class="na"&gt;retry-job&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ubuntu-latest"&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;My Job&lt;/span&gt;
        &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout repository&lt;/span&gt;
              &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;


            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Use the reusable workflow&lt;/span&gt;
              &lt;span class="c1"&gt;# Use the retry action&lt;/span&gt;
              &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nick-fields/retry@v2&lt;/span&gt;
              &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;max_attempts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
                &lt;span class="na"&gt;retry_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;error&lt;/span&gt;
                &lt;span class="na"&gt;timeout_seconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
                &lt;span class="c1"&gt;# You can specify the shell commands you want to retry here&lt;/span&gt;
                &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
                    &lt;span class="s"&gt;echo 'some command that would potentially fail'             &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Approach 2: Duplicate steps
&lt;/h2&gt;

&lt;p&gt;If you are trying to retry steps that use other actions, the &lt;code&gt;retry-step&lt;/code&gt; action may not get the job done. In such a case, you can still retry steps by retrying steps conditionally depending on whether or not a step failed. &lt;/p&gt;

&lt;p&gt;GitHub provides us with two main additional attributes in our steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;continue-on-error&lt;/code&gt; - Setting this to &lt;code&gt;true&lt;/code&gt; means that the even if the current step fails, the job will continue on to the next one (by default failure stops a job's running).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;steps.{id}.outcome&lt;/code&gt; - where &lt;code&gt;{id}&lt;/code&gt; is an &lt;code&gt;id&lt;/code&gt; you add to the steps you want to retry.
This can be used to tell whether a step failed or not, potential values include &lt;code&gt;'failure'&lt;/code&gt; and &lt;code&gt;'success'&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;if&lt;/code&gt; - allows us to conditionally run a step
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Retry&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;action&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;using&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;retry&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;step"&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# This action is called when this is pushed to GitHub&lt;/span&gt;
    &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# This action can be manually triggered&lt;/span&gt;
    &lt;span class="na"&gt;workflow_call&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# This name is up to you&lt;/span&gt;
    &lt;span class="na"&gt;retry-job&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ubuntu-latest"&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;My Job&lt;/span&gt;
        &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout repository&lt;/span&gt;
              &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Some action that can fail&lt;/span&gt;
              &lt;span class="c1"&gt;# You need to specify an id to be able to tell what the status of this action was&lt;/span&gt;
              &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myStepId1&lt;/span&gt;
              &lt;span class="c1"&gt;# This needs to be true to proceed to the next step of failure&lt;/span&gt;
              &lt;span class="na"&gt;continue-on-error&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
              &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/someaction&lt;/span&gt;

            &lt;span class="c1"&gt;# Duplicate of the step that might fail ~ manual retry&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Some action that can fail&lt;/span&gt;
              &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myStepId2&lt;/span&gt;
              &lt;span class="c1"&gt;# Only run this step if step 1 fails. It knows that step one failed because we specified an `id` for the first step&lt;/span&gt;
              &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;steps.myStepId1.outcome == 'failure'&lt;/span&gt;
              &lt;span class="c1"&gt;# This needs to be true to proceed to the next step of failure&lt;/span&gt;
              &lt;span class="na"&gt;continue-on-error&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
              &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/someaction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Bonus: Retrying multiple steps
&lt;/h2&gt;

&lt;p&gt;If you want to retry multiple steps at once, then you can use &lt;a href="https://docs.github.com/en/actions/creating-actions/creating-a-composite-action"&gt;composite actions&lt;/a&gt; to group the steps you want to retry and then use the duplicate steps approach mentioned above. &lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;How do you decide which approach to use? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you are retrying a step that is only shell commands then you can use the &lt;a href="https://github.com/marketplace/actions/retry-step"&gt;retry step action&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If you are retrying a step that needs to use another action, then you can use duplication of steps with conditional running to manually retry the steps.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;This Dot Labs is a JavaScript consulting firm that enables companies to build and improve their digital technologies with confidence. For expert architectural guidance, training, consulting, engineering leadership, and development services in React, Angular, Vue, Web Components, GraphQL, Node, Bazel, Polymer, and more, visit &lt;a href="https://www.thisdot.co/"&gt;thisdot.co&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>github</category>
    </item>
    <item>
      <title>Using PartyTown to improve the performance of VueJS Applications</title>
      <dc:creator>Allan N Jeremy</dc:creator>
      <pubDate>Fri, 14 Oct 2022 07:13:07 +0000</pubDate>
      <link>https://forem.com/thisdotmedia/using-partytown-to-improve-the-performance-of-vuejs-applications-5bk6</link>
      <guid>https://forem.com/thisdotmedia/using-partytown-to-improve-the-performance-of-vuejs-applications-5bk6</guid>
      <description>&lt;h2&gt;
  
  
  What is partytown?
&lt;/h2&gt;

&lt;p&gt;Partytown is a JavaScript library that helps relocate resource intensive scripts (often third-party scripts) into a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers"&gt;web worker&lt;/a&gt; and off the &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Main_thread"&gt;main thread.&lt;/a&gt; This speeds up our site by freeing up the main thread to run our code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
Partytown does not get bundled with the rest of your site's JavaScript. Instead, it intentionally stays separate from your code so that it can run within a webworker.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Using partytown with VueJS
&lt;/h2&gt;

&lt;p&gt;To use partytown with VueJS, you need to find where your third-party scripts are inserted into your page. Typically, this would mean in the &lt;code&gt;index.html&lt;/code&gt; page of your vue application.&lt;/p&gt;

&lt;h4&gt;
  
  
  Create the VueJS application
&lt;/h4&gt;

&lt;p&gt;If you already have an existing VueJS application, you can skip this step. If you are simply looking to test out partytown, you can do so by creating a new VueJS project.&lt;/p&gt;

&lt;p&gt;Create a new vue project by running [and following the steps after that].&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init vue@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should have an &lt;code&gt;index.html&lt;/code&gt; in the generated project. In a new VueJS project, this is generally where we would add global third-party scripts. This file is also going to be where we add partytown&lt;/p&gt;

&lt;h4&gt;
  
  
  Add third-party scripts
&lt;/h4&gt;

&lt;p&gt;If you already have third-party scripts such as &lt;a href="https://analytics.google.com"&gt;Google Analytics&lt;/a&gt; or any other tracking/measurement scripts in your project, you can skip this step. Otherwise, you can set up third-party scripts.&lt;/p&gt;

&lt;h4&gt;
  
  
  Install partytown
&lt;/h4&gt;

&lt;p&gt;To install partytyown into your application, all you need is to use npm or yarn where your &lt;code&gt;package.json&lt;/code&gt; is of your project.&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; @builder.io/partytown
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or (if using yarn)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add @builder.io/partytown
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setup PartyTown
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Setup partytown (vite)
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Available as of Partytown 0.3.6&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Import the partytownVite plugin from @builder.io/partytown/utils into your vite.config.js config file. Next, add partytownVite(opts) to the plugins option.&lt;/p&gt;

&lt;p&gt;The Vite plugin will copy Partytown lib directory to the given destination, which must be an absolute file path. The copying will happen at the time of the writeBundle() hook. When in dev mode, the Partytown lib files will be served using the Vite Dev Server.&lt;/p&gt;

&lt;p&gt;Below is an example of using a Vite config to copy the Partytown lib to a dist build directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// vite.config.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;path&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;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;partytownVite&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;@builder.io/partytown/utils&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="nx"&gt;command&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;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nx"&gt;partytownVite&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;~partytown&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;h4&gt;
  
  
  Setup partytown (the long version)
&lt;/h4&gt;

&lt;p&gt;After installing partytown, you need to modify your package.json to setup partytown. You do this by copying the partytown lib files into a directory we can reference from within our VueJS application.&lt;/p&gt;

&lt;p&gt;Add the partytown script and change the relevant build/preview scripts to run the partytown script before your actual build/preview script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;In&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"partytown &amp;amp;&amp;amp; vite"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"partytown &amp;amp;&amp;amp; vite build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"preview"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"partytown &amp;amp;&amp;amp; vite preview --port 4173"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"partytown"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"partytown copylib public/~partytown"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see a &lt;code&gt;public/~partytown&lt;/code&gt; directory in your project now. Inside this directory, we have a &lt;code&gt;partytown.js&lt;/code&gt; file. This is the file we will be referencing in our html page.&lt;/p&gt;




&lt;p&gt;It is also worth noting that as of the time of writing this article, there is no official &lt;a href="https://partytown.builder.io/integrations"&gt;integration&lt;/a&gt; for partytown with native VueJS applications. There are however other vue tool integrations such as the &lt;a href="https://partytown.builder.io/nuxt"&gt;Nuxt partytown integration&lt;/a&gt; that make this process a lot faster. There are also &lt;a href="https://partytown.builder.io/copy-library-files"&gt;approaches to setting up for different build tools&lt;/a&gt; such as &lt;a href="https://vitejs.dev/"&gt;vite&lt;/a&gt; and &lt;a href="https://webpack.js.org/"&gt;webpack&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Using partytown with third-party scripts
&lt;/h4&gt;

&lt;p&gt;Before we can use partytown with our thirdparty scripts, we need to include it into our page.&lt;br&gt;
Open the &lt;code&gt;index.html&lt;/code&gt; page and add your partytown script.&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="c"&gt;&amp;lt;!-- ./index.html --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"public/~partytown/partytown"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&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;In order to use partytown to move the execution of your third-party scripts from the main thread to a web worker (and improve the performance of your VueJS application), all you need to do is mark the script with the type of &lt;code&gt;text/partytown&lt;/code&gt;. Add the &lt;a href="https://partytown.builder.io/partytown-scripts"&gt;&lt;code&gt;type="text/partytown"&lt;/code&gt; attribute&lt;/a&gt; for each script that should run from a web worker.&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 html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./third-party-script.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;would turn into&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;src=&lt;/span&gt;&lt;span class="s"&gt;"./third-party-script.js"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/partytown"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By adding the &lt;code&gt;text/partytown&lt;/code&gt; you are telling partytown that this script should not be executed on the main JavaScript thread. Partytown also makes sure that the script runs in a web worker for you, no additional setup required.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; that each script is opt-in, meaning that the updated type attribute should only be added to scripts that should run with Partytown. Partytown will not automatically upgrade any scripts unless this attribute is added.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Browser support
&lt;/h2&gt;

&lt;p&gt;Partytown works to ensure that all browsers can still run third-party scripts, whether they have support for service workers, atomics, or neither. This means if you’re supporting legacy browsers such as IE11, the scripts should continue to work as if Partytown wasn’t being used.&lt;/p&gt;

&lt;p&gt;For more information on partytown's browser support, you can check out &lt;a href="https://partytown.builder.io/browser-support"&gt;the official partytown documentation.&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;By making sure our main thread does only what it needs to do (run our code), we can deliver smoother experiences for our users. PartyTown helps us do this effortlessly. I would recommend that you check it out. To learn more about PartyTown (including &lt;a href="https://partytown.builder.io/configuration"&gt;how to configure it&lt;/a&gt;), check out &lt;a href="https://partytown.builder.io/"&gt;partytown's documentation.&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This Dot Labs is a JavaScript consulting firm that enables companies to build and improve their digital technologies with confidence. For expert architectural guidance, training, consulting, engineering leadership, and development services in React, Angular, Vue, Web Components, GraphQL, Node, Bazel, Polymer, and more, visit &lt;a href="https://www.thisdot.co/"&gt;thisdot.co&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>performance</category>
      <category>javascript</category>
      <category>vue</category>
      <category>partytow</category>
    </item>
    <item>
      <title>How to omit `.value` in refs (Vue 3 Composition API)</title>
      <dc:creator>Allan N Jeremy</dc:creator>
      <pubDate>Fri, 17 Jun 2022 08:55:05 +0000</pubDate>
      <link>https://forem.com/thisdotmedia/how-to-omit-value-in-refs-vue-3-composition-api-3jbd</link>
      <guid>https://forem.com/thisdotmedia/how-to-omit-value-in-refs-vue-3-composition-api-3jbd</guid>
      <description>&lt;h2&gt;
  
  
  How to omit &lt;code&gt;.value&lt;/code&gt; in refs (Vue 3 Composition API)
&lt;/h2&gt;

&lt;p&gt;A technical article that expounds on how we can omit using &lt;code&gt;.value&lt;/code&gt; in VueJS ref creating APIs by converting them into &lt;a href="https://vuejs.org/guide/extras/reactivity-in-depth.html"&gt;&lt;strong&gt;reactive variables&lt;/strong&gt;&lt;/a&gt; using macros.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When &lt;a href="https://vuejs.org"&gt;Vue 3&lt;/a&gt; first came around, it introduced the &lt;a href="https://vuejs.org/api/composition-api-setup.html"&gt;Composition API&lt;/a&gt;. The API allowed for greater code re-usability as well as a better way to organize Vue JS code. Along with the composition API, came the concept of &lt;code&gt;refs&lt;/code&gt;. To access the value of a &lt;code&gt;ref&lt;/code&gt;, you needed to append &lt;code&gt;.value&lt;/code&gt; to the name of the &lt;code&gt;ref&lt;/code&gt; variable. To tackle this, the Vue team came up with a solution &lt;a href="https://github.com/vuejs/rfcs/discussions/369"&gt;(Reactivity Transform)&lt;/a&gt; that would allow us to create reactive variables without creating refs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;This article is primarily aimed at intermediate Vue 3 developers and assumes three things.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intermediate knowledge of JavaScript&lt;/li&gt;
&lt;li&gt;Basic &lt;a href="https://vuejs.org/"&gt;Vue 3&lt;/a&gt; usage&lt;/li&gt;
&lt;li&gt;A basic understanding of &lt;a href="https://vuejs.org/guide/essentials/reactivity-fundamentals.html#reactive-variables-with-ref"&gt;how to use refs&lt;/a&gt; and &lt;a href="https://vuejs.org/guide/essentials/reactivity-fundamentals.html"&gt;reactivity in vue&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The functionality discussed in this article is purely opt-in and existing behaviour is unnafected.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tools needed
&lt;/h3&gt;

&lt;p&gt;For this to work, you will need to be using &lt;code&gt;vue@^3.2.25&lt;/code&gt; and above. No additional dependencies are required. Vue 3.2.25+ ships an implementation under the package &lt;a href="https://github.com/vuejs/vue-next/tree/master/packages/reactivity-transform"&gt;@vue/reactivity-transform.&lt;/a&gt; It is also integrated (with its APIs re-exported) in &lt;code&gt;@vue/compiler-sfc&lt;/code&gt; so most userland projects won't need to explicitly install it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reactivity in Vue 3
&lt;/h2&gt;

&lt;p&gt;Reactivity refers to the ability to keep track of changes that occur in our applications. One such way to achieve reactivity in Vue 3 is by using &lt;code&gt;refs&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Refs
&lt;/h3&gt;

&lt;p&gt;The syntax for creating a ref would be something on the lines of 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="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="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// By wrapping our default value (true) with a ref, we tell vue to keep track of changes made to it&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isReading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means that when the value of &lt;code&gt;isReading&lt;/code&gt; changes, Vue knows about it and it can keep track of the changes. This means that UI is automatically updated whenever the value of &lt;code&gt;isReading&lt;/code&gt; changes. In your template file, you would access the reactive value the same way you would access any variable, 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;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;isReading&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Shhh, I'm reading&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;Talk to me&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/h1&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;h3&gt;
  
  
  Using refs
&lt;/h3&gt;

&lt;p&gt;That's all fine and dandy, but when you want to access or modify the value of the refs in the script, then you need to append a &lt;code&gt;.value&lt;/code&gt; at the end of it. This is because &lt;code&gt;ref()&lt;/code&gt; wraps the actual variable(&lt;code&gt;isReading&lt;/code&gt;) in an object that can keep track of any changes made to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;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="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isReading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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="c1"&gt;// prints an object that represents the ref object that wraps isReading&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isReading&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// This is how you would need to access the value of isReading&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isReading&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="c1"&gt;// prints true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Reactivity Transform
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Removing the need for &lt;code&gt;.value&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The new Vue 3 syntax allows you to use refs without needing to use &lt;code&gt;.value&lt;/code&gt;. To make this work, the Vue team implemented &lt;a href="https://github.com/vuejs/rfcs/discussions/369#discussioncomment-2132119"&gt;Reactivity Transform&lt;/a&gt;. This allows us to create &lt;strong&gt;reactive variables&lt;/strong&gt; for every API that creates refs instead of using &lt;code&gt;refs&lt;/code&gt;. This means we can use our variables without appending &lt;code&gt;.value&lt;/code&gt; everywhere. Reactive variables &lt;strong&gt;do not&lt;/strong&gt; need &lt;code&gt;.value&lt;/code&gt; to be accessed while &lt;code&gt;refs&lt;/code&gt; need you to append &lt;code&gt;.value&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Previously we used to write code 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isReading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isReading&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which can now be written 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="c1"&gt;// Prepending $ to ref makes $ref() a macro that wraps around the original ref()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isReading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isReading&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// no need to write&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Behind the scenes, Vue will unwrap the &lt;code&gt;$ref()&lt;/code&gt; and compile into the original &lt;code&gt;.value&lt;/code&gt; syntax we are used to writing. The only difference is that this time you don't have to write &lt;code&gt;isReading.value&lt;/code&gt; everywhere. This is particularly useful in areas where the &lt;code&gt;ref&lt;/code&gt; created is used in multiple places within a script.&lt;/p&gt;

&lt;p&gt;It is also worth noting that every reactivity API that returns &lt;code&gt;refs&lt;/code&gt; will have a &lt;code&gt;$&lt;/code&gt;-prefixed macro equivalent.&lt;br&gt;
These APIs include:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ref&lt;/code&gt; -&amp;gt; &lt;code&gt;$ref&lt;/code&gt;&lt;br&gt;
&lt;code&gt;computed&lt;/code&gt; -&amp;gt; &lt;code&gt;$computed&lt;/code&gt;&lt;br&gt;
&lt;code&gt;shallowRef&lt;/code&gt; -&amp;gt; &lt;code&gt;$shallowRef&lt;/code&gt;&lt;br&gt;
&lt;code&gt;customRef&lt;/code&gt; -&amp;gt; &lt;code&gt;$customRef&lt;/code&gt;&lt;br&gt;
&lt;code&gt;toRef&lt;/code&gt; -&amp;gt; &lt;code&gt;$toRef&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Do you need to import &lt;code&gt;$ref&lt;/code&gt; ?
&lt;/h4&gt;

&lt;p&gt;Since &lt;code&gt;$ref&lt;/code&gt; and equivalents are &lt;a href="https://en.wikipedia.org/wiki/Macro_(computer_science)"&gt;macros&lt;/a&gt;, they &lt;em&gt;do not&lt;/em&gt; need to be imported. However, if you would like to import them explicitly, you can do so from &lt;code&gt;vue/macros&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="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="s2"&gt;vue/macros&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;h3&gt;
  
  
  Convert an existing ref as reactive variable using &lt;code&gt;$()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;In situations where we have a function that returns a &lt;code&gt;ref&lt;/code&gt;, the Vue compiler would not be able to know that the function will return a &lt;code&gt;ref&lt;/code&gt; ahead of time. In such cases, we can wrap the function call with &lt;code&gt;$()&lt;/code&gt; to explicitly convert it into a reactive variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getIsReadingRef&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;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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isReading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getIsReadingRef&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Destructuring objects of refs
&lt;/h3&gt;

&lt;p&gt;Previously, if you tried to destructure an object that was a &lt;code&gt;ref&lt;/code&gt;, the destructured variables would lose their reactivity.&lt;/p&gt;

&lt;p&gt;Let's go with an example ref.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getDefaultReader&lt;/span&gt; &lt;span class="o"&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="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;VueJS lover&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;timeOnPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Vue will be able to tell when any part of `reader` changes&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getDefaultReader&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="c1"&gt;// Vue won't be able to tell when the values of `name` and `timeOnpage` change&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timeOnPage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getDefaultReader&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Reactivity transform, you can destructure the objects of refs &lt;em&gt;and maintain reactivity&lt;/em&gt;. You do so by wrapping the value with a &lt;code&gt;$()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Vue will now be able to tell when the values of `name` and `timeOnpage` change&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timeOnPage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getDefaultReader&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code will compile to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;__temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getDefaultReader&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;toRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__temp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;timeOnPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;toRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__temp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;timeOnPage&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;h3&gt;
  
  
  Reactive props destructuring
&lt;/h3&gt;

&lt;p&gt;This example is from &lt;a href="https://github.com/vuejs/rfcs/discussions/369"&gt;the original Reactivity Transform RFC.&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There are two pain points with the current &lt;code&gt;defineProps()&lt;/code&gt; usage in &lt;code&gt;&amp;lt;script setup&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Similar to &lt;code&gt;.value&lt;/code&gt;, you need to always access &lt;code&gt;props&lt;/code&gt; as &lt;code&gt;props.x&lt;/code&gt; in order to retain reactivity. This means you cannot destructure defineProps because the resulting destructured variables are not reactive and will not update.&lt;/li&gt;
&lt;li&gt;When using the type-only &lt;code&gt;props&lt;/code&gt; declaration, there is no easy way to declare default values for the &lt;code&gt;props&lt;/code&gt;. We introduced the &lt;code&gt;withDefaults()&lt;/code&gt; API for this exact purpose, but it's still clunky to use.
&lt;/li&gt;
&lt;/ul&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;string&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// default value just works&lt;/span&gt;
  &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// local aliasing also just works&lt;/span&gt;
  &lt;span class="c1"&gt;// here we are aliasing `props.foo` to `bar`&lt;/span&gt;
  &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;bar&lt;/span&gt;&lt;span class="p"&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;defineProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Props&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;watchEffect&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="c1"&gt;// will log whenever the props change&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bar&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;The above will be combined to the following in runtime&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;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;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;msg&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;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="na"&gt;count&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;Number&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="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;foo&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="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;watchEffect&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foo&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;h2&gt;
  
  
  Using $$() to retain reactivity
&lt;/h2&gt;

&lt;p&gt;To get around reactivity loss in certain scenarios, the &lt;code&gt;$$()&lt;/code&gt; macro can be used.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retaining reactivity when passing refs as function arguments
&lt;/h3&gt;

&lt;p&gt;Consider a situation where you have a function that needs to accept a reactive variable as an argument.&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;function&lt;/span&gt; &lt;span class="nx"&gt;trackChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isReading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isReading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isReading&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;isReading changed!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isReading&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;isReading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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="c1"&gt;// This will not work&lt;/span&gt;
&lt;span class="nx"&gt;trackChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isReading&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In such a case, reactivity is lost.The reason for this is that the &lt;code&gt;isReading&lt;/code&gt; ref is actually unwrapped into &lt;code&gt;isReading.value&lt;/code&gt; when being passed in as the argument for &lt;code&gt;trackChange&lt;/code&gt; while &lt;code&gt;trackChange&lt;/code&gt; expects an actual &lt;code&gt;ref&lt;/code&gt;. The above code compiles to 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="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="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;isReading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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="c1"&gt;// This is what is actually happening&lt;/span&gt;
&lt;span class="nx"&gt;trackChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isReading&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To get around this, we can wrap the ref in &lt;code&gt;$$()&lt;/code&gt; which tells the compiler not to append a &lt;code&gt;.value&lt;/code&gt; to it.&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="c1"&gt;// This will work&lt;/span&gt;
&lt;span class="nx"&gt;trackChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isReading&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above example compiles to 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="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="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;isReading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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="c1"&gt;// This is what we want - the isReading variable should be passed as a ref&lt;/span&gt;
&lt;span class="nx"&gt;trackChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isReading&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Retaining reactivity when returning inside function scope
&lt;/h3&gt;

&lt;p&gt;Another scenario where reactivity is lost is when we are returning reactive variables from within a function.&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;function&lt;/span&gt; &lt;span class="nx"&gt;useMouse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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="c1"&gt;// listen to mousemove...&lt;/span&gt;

  &lt;span class="c1"&gt;// doesn't work!&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;y&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;Similar to the example with passing refs as arguments, the above return statement compiles to:&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;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;x&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="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;y&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to maintain the reactivity of &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;, we can wrap the entire return statement with the &lt;code&gt;$$()&lt;/code&gt; macro.&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;function&lt;/span&gt; &lt;span class="nx"&gt;useMouse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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="c1"&gt;// listen to mousemove...&lt;/span&gt;

  &lt;span class="c1"&gt;// This works&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Retaining reactivity on destructured props
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;$$()&lt;/code&gt; works on destructured props since they are reactive variables as well. The compiler will convert it with toRef for efficiency:&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;count&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defineProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;passAsRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;compiles to:&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;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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;__props_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;toRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;count&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;passAsRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__props_count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  TypeScript &amp;amp; Tooling Integration
&lt;/h2&gt;

&lt;p&gt;Vue will provide typings for these macros (available globally) and all types will work as expected. There are no incompatibilities with standard TypeScript semantics so the syntax would work with all existing tooling.&lt;/p&gt;

&lt;p&gt;This also means the macros can work in any files where valid JS/TS are allowed - not just inside Vue SFCs.&lt;/p&gt;

&lt;p&gt;Since the macros are available globally, their types need to be explicitly referenced (e.g. in a env.d.ts file):&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="c1"&gt;/// &amp;lt;reference types="vue/macros-global" /&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When explicitly importing the macros from &lt;code&gt;vue/macros&lt;/code&gt;, the type will work without declaring the globals.&lt;/p&gt;

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

&lt;p&gt;By taking advantage of the macros added to Vue 3, you can drastically cleanup your code base by getting rid of &lt;code&gt;.value&lt;/code&gt; usage. You also get to preserve reactivity within your application when destructuring reactive variables as well as props when using the Composition API and &lt;code&gt;defineProps()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you'd like to read more on the same, you can do so in &lt;a href="https://github.com/vuejs/rfcs/discussions/369"&gt;the official Vue JS RFC discussion for the feature.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I do hope you find this helpful in reducing your code footprint and making your general life easier. The next time you think of using &lt;code&gt;.value&lt;/code&gt; for your refs, remember that you don't have to. With that, thanks for stopping by(e)!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This Dot Labs is a development consultancy focused on providing staff augmentation, architectural guidance, and consulting to companies.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We help implement and teach modern web best practices with technologies such as React, Angular, Vue, Web Components, GraphQL, Node, and more.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Using Quasar with Vue3 &amp; Storybook</title>
      <dc:creator>Allan N Jeremy</dc:creator>
      <pubDate>Thu, 07 Apr 2022 08:27:19 +0000</pubDate>
      <link>https://forem.com/allanjeremy/using-quasar-with-vue3-storybook-4dl8</link>
      <guid>https://forem.com/allanjeremy/using-quasar-with-vue3-storybook-4dl8</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is a draft article and may be polished later&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Create a new quasar project. Install the quasar cli if you haven't already. Using the Vite option for this example.&lt;/p&gt;

&lt;p&gt;Select Vue 3 and Vite instead of Webpack to follow along with this example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ yarn global add @quasar/cli
$ yarn create quasar

# or:

$ npm i -g @quasar/cli
$ npm init quasar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Initialize storybook
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;cd into the directory of your created project&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run &lt;code&gt;npx sb init&lt;/code&gt; to initialize storybook in your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update package.json
&lt;/h2&gt;

&lt;p&gt;Replace whatever version of autoprefixer you have in your &lt;code&gt;package.json&lt;/code&gt; in order for Storybook to work. The version of PostCSS being used by Storybook will not work with later versions of autoprefixer. More details on why that is &lt;a href="https://stackoverflow.com/questions/64057023/error-postcss-plugin-autoprefixer-requires-postcss-8-update-postcss-or-downgra" rel="noopener noreferrer"&gt;can be found here.&lt;/a&gt;&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; "autoprefixer": "^9.0.0",
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Update your Storybook settings
&lt;/h2&gt;

&lt;p&gt;In order for storybook to load and display quasar components correctly, we need to update our &lt;code&gt;.storybook/preview.js&lt;/code&gt; file with the following:&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@quasar/extras/roboto-font/roboto-font.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// These are optional&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@quasar/extras/material-icons/material-icons.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@quasar/extras/animate/fadeInUp.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@quasar/extras/animate/fadeOutDown.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@quasar/extras/animate/fadeInRight.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@quasar/extras/animate/fadeOutRight.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Loads the quasar styles and registers quasar functionality with storybook&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;quasar/dist/quasar.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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;app&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;@storybook/vue3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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;Quasar&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;quasar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// This is also where you would setup things such as pinia for storybook&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Quasar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;argTypesRegex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^on[A-Z].*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;controls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;matchers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;background|color&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;$/i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/Date$/&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;h2&gt;
  
  
  Run storybook
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;yarn storybook&lt;/code&gt; to run storybook. It should open your browser at &lt;code&gt;localhost:6006/&lt;/code&gt; by default.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Quasar Components
&lt;/h2&gt;

&lt;p&gt;Replace the code in your &lt;code&gt;src/stories/Button.vue&lt;/code&gt; with&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;q-btn&lt;/span&gt; &lt;span class="na"&gt;color=&lt;/span&gt;&lt;span class="s"&gt;"primary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Something&lt;span class="nt"&gt;&amp;lt;/q-btn&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;You should now see your quasar button in storybook.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvekirg3huyj5em4f8hld.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvekirg3huyj5em4f8hld.png" alt="Quasar button in storybook screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;That's it! You can now begin to use storybook with Vue3 + Vite + Quasar&lt;/p&gt;

</description>
      <category>quasar</category>
      <category>vue</category>
      <category>storybook</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Three types of console.log users. Which one are you?</title>
      <dc:creator>Allan N Jeremy</dc:creator>
      <pubDate>Tue, 05 May 2020 14:12:16 +0000</pubDate>
      <link>https://forem.com/allanjeremy/three-types-of-console-log-users-which-ome-are-you-3l75</link>
      <guid>https://forem.com/allanjeremy/three-types-of-console-log-users-which-ome-are-you-3l75</guid>
      <description>&lt;p&gt;Any js developer has definitely used &lt;code&gt;console.log()&lt;/code&gt; before. Among these 3 main ways to print variables with text within &lt;code&gt;console.log()&lt;/code&gt;, I am curious to see what kind of developers people are. &lt;/p&gt;

&lt;p&gt;I have added comments for of the three methods mentioned  feel free to vote for the method you use by liking the comment that corresponds to how you use `console.log(). I'd also love to hear why you use the method that you use.&lt;/p&gt;

</description>
      <category>discus</category>
      <category>poll</category>
      <category>survey</category>
    </item>
    <item>
      <title>What's the funniest error message you've seen</title>
      <dc:creator>Allan N Jeremy</dc:creator>
      <pubDate>Tue, 11 Feb 2020 10:44:26 +0000</pubDate>
      <link>https://forem.com/allanjeremy/what-s-your-favorite-error-message-2c33</link>
      <guid>https://forem.com/allanjeremy/what-s-your-favorite-error-message-2c33</guid>
      <description>&lt;p&gt;I just recently tried to discard a file in a new repo in VSCode and got this error (which I found funny for some reason - insert awkward laugh)&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CXp6WGbr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://pasteall.org/pic/show.php%3Fid%3D51e7965e6e64a3f411b17c836923103e" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CXp6WGbr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://pasteall.org/pic/show.php%3Fid%3D51e7965e6e64a3f411b17c836923103e" alt="Error message"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Which got me thinking. What are your favorite/funniest error messages?&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>So I just got back to youtube after 7 years...</title>
      <dc:creator>Allan N Jeremy</dc:creator>
      <pubDate>Fri, 03 Jan 2020 11:00:10 +0000</pubDate>
      <link>https://forem.com/allanjeremy/so-i-just-got-back-to-youtube-after-7-years-5eld</link>
      <guid>https://forem.com/allanjeremy/so-i-just-got-back-to-youtube-after-7-years-5eld</guid>
      <description>&lt;h2&gt;
  
  
  Heads up
&lt;/h2&gt;

&lt;p&gt;This article contains some shameless plugs to my channels. If you find this offensive, I apologize in advance. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/4HcW7p5pIIeLdvkj2X/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/4HcW7p5pIIeLdvkj2X/giphy.gif" alt="Shrug" width="480" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Please don't eat me 😅&lt;/p&gt;




&lt;h2&gt;
  
  
  We've all been there
&lt;/h2&gt;

&lt;p&gt;We've all started something that we stopped doing. For me, one of those things was &lt;a href="https://www.youtube.com/channel/UCB7kPKJ2gznFwBOaUW7k-8Q"&gt;YouTube&lt;/a&gt;. I started &lt;a href="https://www.youtube.com/watch?v=gT4CemTAjAg"&gt;teaching the fundamentals of programming&lt;/a&gt; and 3D stuff a year after I finished high school.&lt;/p&gt;

&lt;p&gt;At the time, I knew nothing about YouTube and simply wanted to share knowledge regardless of whether or not the quality was good. My audio was &lt;strong&gt;horrible&lt;/strong&gt; (as you'd see with multiple comments on the same) and I &lt;em&gt;never appeared on camera&lt;/em&gt;. For some of the videos, the aesthetic was also horrid, but for some reason I kept making videos. &lt;/p&gt;

&lt;p&gt;I stopped YouTubing when I joined campus - studying Film &amp;amp; Animation. That made me a lot more critical of what I could put out as well as bombarded me with a tonne of work.  &lt;/p&gt;

&lt;p&gt;Anyway. Fast forward to 2020, I figured it's time to get back to it. I bought a blue yeti mic &amp;amp; borrowed a camera from a friend. The first two videos (more like 100 takes) I recorded felt cringey as hell. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bkRq4FKW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media1.giphy.com/media/cFKz0XrOLjQIM/giphy.gif%3Fcid%3D790b7611a7a0f5a13362fdf8c1386ca92cddad6c641576ff%26rid%3Dgiphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bkRq4FKW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media1.giphy.com/media/cFKz0XrOLjQIM/giphy.gif%3Fcid%3D790b7611a7a0f5a13362fdf8c1386ca92cddad6c641576ff%26rid%3Dgiphy.gif" alt="Cringe" width="384" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So in the end I decided to say 🤷‍♂️ it (insert the word you're thinking of here.). It is quite thrilling, since I have no idea what kind of reception I'll get.&lt;/p&gt;

&lt;p&gt;Not only did I decide to continue with my old channel. I also started &lt;a href="//www.youtube.com/channel/UC6pQpWMdnyxbYmCotBlUyMQ"&gt;a new channel&lt;/a&gt; where I've challenged myself to build a multi-million dollar company in the next 2 years, starting with $0 in Africa. For the most part, I think it's worth a try, given that I have tried a bunch of things, failed and learnt a tonne over the past 7ish years.&lt;/p&gt;

&lt;h3&gt;
  
  
  So yeah...
&lt;/h3&gt;

&lt;p&gt;I'll be posting new videos on Friday &amp;amp; Monday . &lt;br&gt;
&lt;a href="//www.youtube.com/channel/UC6pQpWMdnyxbYmCotBlUyMQ"&gt;Making it in Africa&lt;/a&gt; - Fridays&lt;br&gt;
&lt;a href="https://www.youtube.com/channel/UCB7kPKJ2gznFwBOaUW7k-8Q"&gt;Tutorial channel&lt;/a&gt; - Mondays&lt;/p&gt;

&lt;p&gt;Hopefully I can commit this time - this article is meant to hold me accountable as well.&lt;/p&gt;

&lt;p&gt;I also figured I'd start doing bi-weekly (Probably on weekends) life tips on &lt;a href="https://www.instagram.com/theallanjeremy/"&gt;my Instagram&lt;/a&gt; just to share what I've learnt over the course of my life and career.&lt;/p&gt;

&lt;h2&gt;
  
  
  I could use some help
&lt;/h2&gt;

&lt;p&gt;What would you suggest as tips for getting back into the game? Any YouTube tips? I've got a few more general video related questions that I'll ask in a different post.&lt;/p&gt;

</description>
      <category>watercooler</category>
      <category>youtube</category>
      <category>video</category>
      <category>startup</category>
    </item>
    <item>
      <title>Specifying good requirements in Gherkin - BDD</title>
      <dc:creator>Allan N Jeremy</dc:creator>
      <pubDate>Wed, 01 Jan 2020 10:39:48 +0000</pubDate>
      <link>https://forem.com/allanjeremy/specifying-good-requirements-in-gherkin-bdd-113j</link>
      <guid>https://forem.com/allanjeremy/specifying-good-requirements-in-gherkin-bdd-113j</guid>
      <description>&lt;p&gt;First of all. Happy new Year!&lt;/p&gt;

&lt;h1&gt;
  
  
  TL;DR
&lt;/h1&gt;

&lt;p&gt;Explain how to write good &lt;a href="https://cucumber.io/docs/gherkin"&gt;Gherkin&lt;/a&gt;, beyond just the syntax Like I'm five.&lt;/p&gt;




&lt;p&gt;So. I just started learning &lt;a href="https://en.wikipedia.org/wiki/Behavior-driven_development"&gt;Behavior Driven Development (BDD)&lt;/a&gt; seriously. I stumbled upon &lt;a href="https://cucumber.io/docs/gherkin"&gt;Gherkin&lt;/a&gt; while looking into &lt;a href="https://cucumber.io/"&gt;Cucumber&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For those who may not know, Gherkin is a language that makes it easy for businesses to write down requirements for a system that fulfills business needs. This reduces the chances of wasting time in development where there is a disconnect between the tech team and the product owner or business team.&lt;/p&gt;

&lt;p&gt;However, while trying to actually implement the actual Gherkin. I have found it difficult to establish the following things: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What counts as a &lt;em&gt;Feature&lt;/em&gt;?&lt;/li&gt;
&lt;li&gt;What counts as a &lt;em&gt;Scenario&lt;/em&gt;? When should you pull out a scenario and make it a feature and when should you make a feature a scenario?&lt;/li&gt;
&lt;li&gt;What makes good &lt;em&gt;Given&lt;/em&gt; statements?&lt;/li&gt;
&lt;li&gt;Why not split individual &lt;em&gt;And&lt;/em&gt; sections into their own scenarios in most cases?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I speak from naivety and would like to understand what makes for good &lt;a href="https://cucumber.io/docs/gherkin"&gt;Gherkin&lt;/a&gt; and good requirements specification&lt;/p&gt;

</description>
      <category>requestforpost</category>
      <category>testing</category>
      <category>help</category>
      <category>discuss</category>
    </item>
    <item>
      <title>What are your daily routines? #2020</title>
      <dc:creator>Allan N Jeremy</dc:creator>
      <pubDate>Tue, 24 Dec 2019 09:37:07 +0000</pubDate>
      <link>https://forem.com/allanjeremy/what-are-your-daily-routines-2020-401m</link>
      <guid>https://forem.com/allanjeremy/what-are-your-daily-routines-2020-401m</guid>
      <description>&lt;p&gt;Seeing as we are almost getting into a new year. I'd love to hear what routines you have in your life to stay productive and minimize distractions while maintaining a relatively stress free healthy lifestyle.&lt;/p&gt;

&lt;p&gt;If you're planning to start a new routine, feel free to share it as well.&lt;/p&gt;

&lt;p&gt;We can all learn something from each other.&lt;/p&gt;

</description>
      <category>2020</category>
      <category>business</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Looking for remote work</title>
      <dc:creator>Allan N Jeremy</dc:creator>
      <pubDate>Sat, 16 Nov 2019 23:25:32 +0000</pubDate>
      <link>https://forem.com/allanjeremy/looking-for-remote-work-4i6</link>
      <guid>https://forem.com/allanjeremy/looking-for-remote-work-4i6</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;I am looking for remote work. If you know anyone looking for Fullstack devs/consultants with cloud experience, feel free to email me @ &lt;a href="mailto:dev@allanjeremy.com"&gt;dev@allanjeremy.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="//github.com/AllanJeremy"&gt;My github&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If this violates any rules, I can take it down &lt;a class="mentioned-user" href="https://dev.to/ben"&gt;@ben&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Hey, what's up guys. Been a while since I last posted here. &lt;/p&gt;

&lt;p&gt;Anyway, earlier this year, I'd joined a startup as a CTO. However, the other founders ended up going back on their word &amp;amp; I had to leave (more on this in an article I'll write)&lt;/p&gt;

&lt;p&gt;That being said. I am currently looking for remote work/consulting work.&lt;/p&gt;

&lt;p&gt;I have been coding for the past 9 years. I am a fullstack dev with experience  &amp;amp; multiple projects in Nodejs, Vue, PhP, SQL, MongoDb &amp;amp; Firebase among other tools. I am well versed in TDD &amp;amp; system architecture as well as design &amp;amp; game development. I have built systems on MVC, Service based architectures as well as supervised multiple teams of developers to deliver multiple solutions. I am an effective communicator in business, tech &amp;amp; entrepreneurship&lt;/p&gt;

&lt;p&gt;If you are looking for someone or know anyone who may looking for a fullstack dev/consultant, please email me @ &lt;a href="mailto:dev@allanjeremy.com"&gt;dev@allanjeremy.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks a tonne for your time&lt;br&gt;
Cheers&lt;/p&gt;

</description>
      <category>career</category>
      <category>remote</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Can you solo podcast?</title>
      <dc:creator>Allan N Jeremy</dc:creator>
      <pubDate>Thu, 19 Sep 2019 06:47:59 +0000</pubDate>
      <link>https://forem.com/allanjeremy/can-you-solo-podcast-4igl</link>
      <guid>https://forem.com/allanjeremy/can-you-solo-podcast-4igl</guid>
      <description>&lt;p&gt;It's 9am and I feel like talking to myself. I record my thoughts but hesitate before posting them.&lt;/p&gt;

&lt;p&gt;One question lingers around my mind, can you solo podcast?&lt;/p&gt;

&lt;p&gt;Any examples of tech solo podcasts?&lt;/p&gt;

&lt;p&gt;Ps, I'll eventually look for someone once I decide to take podcasting seriously &lt;/p&gt;

</description>
      <category>discuss</category>
      <category>podcast</category>
    </item>
    <item>
      <title>What do guys use to create/host podcasts</title>
      <dc:creator>Allan N Jeremy</dc:creator>
      <pubDate>Thu, 19 Sep 2019 06:44:31 +0000</pubDate>
      <link>https://forem.com/allanjeremy/what-do-guys-use-to-create-host-podcasts-25cd</link>
      <guid>https://forem.com/allanjeremy/what-do-guys-use-to-create-host-podcasts-25cd</guid>
      <description>&lt;p&gt;If you've done podcasts or are considering doing so, what platforms do you use to host &amp;amp; manage them?&lt;/p&gt;

&lt;p&gt;What are the advantages vs disadvantages of these various tools?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>blogging</category>
      <category>podcast</category>
    </item>
  </channel>
</rss>
