Exclusive tips every week

Join 11,067 other Vue devs and get exclusive tips and insights delivered straight to your inbox, every week.

    Picture of Michael Thiessen

    👋Hey friend! I work hard to send you amazing stuff each week.

    — Michael

    I really love and enjoy reading these emails.

    You are one of the most pro VueJS devs I know, and I am happy that you share this knowledge.

    Fabian Beer

    Here's my latest newsletter

    🔥 (#192) Testing components in Nuxt, extract conditional patterns, and more

    Hey!

    Yesterday I gave my talk on Nuxt Layers at VueConf Toronto, and I think it went really well — maybe one of my best talks yet.

    Alex and I are also doing some recording at the conference, so you'll see that in an upcoming episode soon.

    I've also got a quick Black Friday reminder:

    On Monday, November 25, you'll get a single email about my Black Friday sale. That's it.

    As always, I've got some great tips and articles for you.

    — Michael

    🔥 Restrict a prop to a list of types

    With the Composition API we get fantastic TypeScript support, so this is quite straightforward:

    defineProps<{
    src: string;
    style: 'square' | 'rounded';
    }>();

    Doing this in the Options API is more complicated, and not as powerful as TypeScript.

    Using the validator option in a prop definition you can restrict a prop to a specific set of values:

    export default {
    name: 'Image',
    props: {
    src: {
    type: String,
    },
    style: {
    type: String,
    validator: s => ['square', 'rounded'].includes(s)
    }
    }
    };

    This validator function takes in a prop and returns either true or false — if the prop is valid or not.

    I often restrict props like this when I need more options than a boolean will allow but still want to restrict what can be set.

    Button types or alert types (info, success, danger, warning) are some of the most common uses — at least in what I work on. Colours, too, are a really great use case for this.

    🔥 Mount Components When Testing in Nuxt

    When writing unit tests, you have access to a bunch of helper methods.

    One super useful one is mountSuspended. It lets you mount any component inside your Nuxt context with async setup:

    import { describe, it, expect } from 'vitest';
    import { mountSuspended } from '@nuxt/test-utils/runtime';
    import MyComponent from './MyComponent.vue';
    describe('MyComponent', () => {
    it('renders the message correctly', async () => {
    const wrapper = await mountSuspended(MyComponent);
    expect(wrapper.text()).toContain('This component is set up.');
    });
    });

    You’re also able to mount your app at a specific route, by passing in the App component and a route:

    import { describe, it, expect } from 'vitest';
    import { mountSuspended } from '@nuxt/test-utils/runtime';
    import App from './App.vue';
    describe('About', () => {
    it('renders the about page', async () => {
    const wrapper = await mountSuspended(App, { route: '/about' });
    expect(wrapper.text()).toContain('Hi, my name is Michael!');
    });
    });

    🔥 Extract Conditional Pattern

    An extremely common question I get asked all the time is, “how do you know when to split up a component?”

    I want to share a simple pattern with you that is basically fool-proof, and can be applied to lots of components with almost no thought.

    When we encounter a v-if (or v-show) in our template, there's one main pattern we can use:

    Extracting the body of each branch into its own component.

    This is just one of many patterns included in Clean Components. There, we go into much more detail, examining each pattern more closely and really fine-tuning our understanding.

    When we extract each branch body we go from this:

    <div v-if="condition">
    <div>
    <!-- Lots of code here -->
    </div>
    </div>
    <div v-else>
    <div>
    <!-- Lots of other code -->
    </div>
    </div>

    To this:

    <div v-if="condition">
    <NewComponent />
    </div>
    <div v-else>
    <OtherComponent />
    </div>

    We know we can do this for two reasons:

    1. Each branch is semantically related
    2. Each branch does distinct work

    We know that each branch is semantically related, meaning all of that code works together to perform the same task.

    Each branch also does distinct work — otherwise, why have a v-if at all?

    This means it's a perfect opportunity to create new components.

    And by replacing a large chunk of code with a well-named component that represents the code’s intent, we make our code much more self-documenting. But we’ll get to that later on.

    🎙️ #034 — Data Fetching in Vue and Nuxt

    Data fetching is a crucial part of any web application. In this episode of DejaVue, we discuss the different ways to fetch data in Vue.js and Nuxt.js, and how to cache it. 

    We also talk about the experimental Suspense feature in Vue.js and how it can be used to improve the user experience, as well as how to handle third-party scripts in your application.

    In addition, Nuxt's data fetching options are discussed, including the $fetch method, useFetch, useAsyncData and the useNuxtData composable. Finally, we cover server-side caching in Nuxt.js, including route rules, defineCachedEventHandler, and defineCachedFunction.

    Enjoy the episode! 

    Watch on YouTube or listen on your favorite podcast platform.

    Chapters:

    In case you missed them:

    📜 How to Redirect in Nuxt (Every Single Way)

    There are a lot of different ways to redirect users in Nuxt, each with their own use cases.

    In this (very detailed!) article I explore the different ways to redirect users in Nuxt, giving examples of when each might be useful.

    Check it out here: How to Redirect in Nuxt (Every Single Way)

    📜 Dynamically Updating my Landing Page with Nuxt Content

    I recently spent some time updating the landing page for Clean Components Toolkit so that it will automatically update the outline as I update the course content itself.

    In this article, I'll show you how it's done.

    Check it out here: Dynamically Updating my Landing Page with Nuxt Content

    📅 Upcoming Events

    Here are some upcoming events you might be interested in. Let me know if I've missed any!

    Vuejs Amsterdam 2025 — (March 12, 2025 to March 13, 2025)

    The biggest Vue conference in the world! A two-day event with workshops, speakers from around the world, and socializing.

    Check it out here

    💬 Write Code for Humans

    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand." — Martin Fowler

    🧠 Spaced-repetition: Refresh a Page in Vue

    The best way to commit something to long-term memory is to periodically review it, gradually increasing the time between reviews 👨‍🔬

    Actually remembering these tips is much more useful than just a quick distraction, so here's a tip from a couple weeks ago to jog your memory.

    If you need to force a reload your entire page using Vue, all you need is some Javascript:

    window.location.reload();

    But this is a code smell — you should almost never need to use this method.

    Instead, a better solution might be one of these:

    • Create a method to reset and initialize state instead of relying on onMounted hooks or the top-level of setup. You can also create an initialize action for Pinia.
    • Make sure your important state is reactive. This tends to fix a lot of common issues.
    • Key-changing — by changing just the key attribute on a specific component, you can force just one component to reload instead of your entire app. Still a bit of a hack, but it gets the job done.

    Michael Hoffman curates a fantastic weekly newsletter with the best Vue and Nuxt links.

    Sign up for it here.

    _p.s. I also have a bunch of products/courses:

    Here's what others are saying

    I'm starting to think that your newsletter is one of the best things that happened to me this year. I just love these emails.
    Stanislaw Gregor
    I'm somewhere in the upper-middle level at Vue, and I never miss an email you and always find something cool when reading!
    Eduard Climov
    This is the first time where I'm actually enjoying email newsletters. I like your format a lot.
    Fahmi Alfituri
    You have great content in your emails. I seriously learn something from every one of them.
    Titus Decali
    Just wanted to say I enjoy these emails. They encourage me to constantly improve my craft. Fantastic work.
    Joe Radman
    Thanks for another beautiful tip 🙏
    Victor Martins Onuoha
    Loving these, and the spaced repetition.
    Mark Goldstein
    I really enjoy reading your emails, because I love Vue. Thanks for these emails.
    Arturo Espinoza
    I really love and enjoy reading these emails. You are one of the most pro VueJS devs I know, and I am happy that you share this knowledge.
    Fabian Beer
    THANK YOU! I did not know about the deep property, so I assumed you simply couldn't watch objects.
    Darryl Noakes
    I really must say you are doing a really great job. Now I am aware of a cleaner and more performant way to use Tailwind. Thanks a lot!
    Henry Eze
    Thank you so much, I really enjoy and appreciate your emails.
    Carlos Gonzalez
    Thanks for sharing great Vue tips.
    Fernando Navarro
    I really enjoy these tips.
    Martin H
    Thank you so much for the weekly Vue education. Thanks and live on longer to educate us more.
    Kabolobari Benakole
    I look forward to your emails every week. This week was something I knew, but I like to be reminded of. Thanks for keeping it up!
    Nathan Strutz
    Thank you for your weekly emails. I always look forward to learning a new tip about Vue or at least relearning old tips :)
    Colin Johnson
    I have really been enjoying your weekly emails, and I also got my two team members to join in on the fun as well.
    Keith Dawson
    Thank you for your newsletter, your explanations have very concise examples and I like it.
    Nicolas Decayeux
    Thanks A LOT for your great work!!! One of the few newsletters that I let pass!
    Martin Tillmann

    Want to level up your Vue skills?

    With over two million reads and 11,067 subscribers, you've come to the right place.

    Subscribe now to get exclusive insights and tips every week.