Exclusive tips every week

Join 13,567+ 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

    🔥 (221) Debugging Templates, Directly Accessing Parent Components, and SSR Safe Directives

    Read this on my blog

    What's up?

    We're sooooo close to finishing Mastering Nuxt!

    This week I'm working on the last set of videos for Mastering Nuxt, the module on authentication. Then, I need to re-record a few videos to fix some mistakes and tidy things up.

    Once Nuxt 4 stable is released, I'll re-record the very first video (where we install Nuxt) so it's all up-to-date.

    It takes a bit to edit and polish things up after recording, but we're looking good for finishing everything up not too long after Nuxt 4 drops!

    In other Nuxt news, my friend, Adam DeHaven, wrote a great article on how to power multi-tenant applications with Nuxt.

    Even if you don't have a multi-tenant application, this is a great article to read, filled with tons of advanced Nuxt tips and tricks.

    Powering Multi-Tenant Applications with Nuxt

    Now, on to your weekly tips!

    — Michael

    🔥 Debugging Templates

    If you ever need to debug what’s happening inside of a template, you can just throw in a function:

    <template>
    <div v-for="i in 4" :key="i">
    {{ log(i) }}
    {{ i + 1 }}
    </div>
    </template>

    Vue will execute anything within the curly braces as Javascript, so this function is called normally.

    It can be whatever you want. Set it to console.log if you just want to log out some values:

    const log = console.log;

    Or add in a debugger statement so you can step through the code one line at a time and inspect the variables more closely:

    const log = (val) => {
    debugger;
    };

    If we want global access to a debugging utility, we can use the globalProperties field on our app config:

    app.config.globalProperties.$log = console.log;

    Now, we can use this $log method in whatever component we want:

    🔥 Directly accessing parent components (and why)

    Props down, events up. That's how your components should communicate — most of the time.

    But in rare cases, that just doesn't work.

    If you need direct access to the parent component, you should just use provide/inject to pass down the relevant value or method:

    import { provide } from 'vue';
    const someMethodInTheParent = () => {};
    provide('method', someMethodInTheParent)

    Then, inject it into the child component:

    import { inject } from 'vue';
    const method = inject('method');
    method();

    In Vue 2, you can also use the instance property $parent:

    // Tight coupling like this is usually a bad idea
    this.$parent.methodOnParentComponent();

    This is simpler, but leads to higher coupling and will more easily break your application if you ever refactor.

    You can also get direct access to the application root, the very top-most component in the tree, by using $root. Vue 2 also has $children, but these were taken out for Vue 3 (please don't use this one).

    When would these be useful?

    There are a few different scenarios I can think of. Usually, when you want to abstract some behaviour and have it work "magically" behind the scenes.

    You don't want to use props and events to connect up a component in those cases. Instead, you use provide/inject, $parent, or $root, to automatically connect the components and make things happen.

    (This is similar to the Compound Component pattern)

    But it's hard to come up with an example where this is the best solution. Using provide/inject is almost always the better choice.

    🔥 SSR Safe Directives

    In many cases, we need to generate unique IDs for elements dynamically.

    But we want this to be stable through SSR so we don’t get any hydration errors.

    And while we’re at it, why don’t we make it a directive so we can easily add it to any element we want?

    Here's a stripped-down version of this directive:

    const generateID = () => Math.floor(Math.random() * 1000);
    const directive = {
    getSSRProps() {
    return { id: generateID() };
    },
    }

    When using it with Nuxt, we need to create a plugin so we can register the custom directive:

    // ~/plugins/dynamic-id.ts
    const generateID = () => Math.floor(Math.random() * 1000);
    export default defineNuxtPlugin((nuxtApp) => {
    nuxtApp.vueApp.directive("id", {
    getSSRProps() {
    return { id: generateID() };
    },
    });
    });

    In Vue 3.5+, you can also use the useId composable instead:

    <template>
    <div :id="id" />
    </template>
    <script setup>
    const id = useId();
    </script>

    Normally, custom directives are ignored by Vue during SSR because they typically are there to manipulate the DOM. Since SSR only renders the initial DOM state, there’s no need to run them, so they’re skipped.

    But there are some cases where we actually need the directives to be run on the server, such as with our dynamic ID directive.

    That’s where getSSRProps comes in.

    It’s a special function on our directives that is only called during SSR, and the object returned from it is applied directly to the element, with each property becoming a new attribute of the element:

    getSSRProps(binding, vnode) {
    // ...
    return {
    attribute,
    anotherAttribute,
    };
    }

    🎙️ #058 — The History of Nuxt and NuxtLabs (with Sébastien Chopin)

    Join Alex and Michael with special guest Sébastien Chopin, creator of Nuxt.js and CEO of NuxtLabs, to learn more about the origins and evolution of the Vue-based meta framework. Sébastien shares valuable lessons from open source, how he came to create Nuxt.js in the first place and which challenges came with it.

    In the second part of the episode, they cover Sébastien's company NuxtLabs - from its inception over to taking Venture Capital and products, such as NuxtHub or Nuxt UI Pro.

    Eventually, the NuxtLabs CEO also outlines how they handle sponsorships of maintainers, and what the future holds for Nuxt and NuxtLabs.

    Watch on YouTube or listen on your favorite podcast platform.

    Chapters:

    In case you missed them:

    📜 Controlling When Components Are Loaded in Nuxt

    Nuxt gives us a few different options for controlling when components are loaded.

    In this article I explore the different options and how to use each.

    Check it out here: Controlling When Components Are Loaded in Nuxt

    📜 Client-Side Error Handling in Nuxt

    It may not be as fun as shipping the next feature, but making sure our apps are rock-solid and can recover from errors is crucial.

    Without good error-handling, our UX suffers and our applications can be hard to use.

    In this article I explore handling client-side errors using the NuxtErrorBoundary component.

    Check it out here: Client-Side Error Handling in Nuxt

    📅 Upcoming Events

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

    💬 Libraries

    "Telling a programmer there's already a library to do X is like telling a songwriter there's already a song about love." — Pete Cordell

    🧠 Spaced-repetition: Structuring Composables

    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.

    To keep your composables — those extracted functions written using the composition API — neat and easy to read, here's a way to organize the code.

    1. Component and directives
    2. provide and inject
    3. defineProps, defineEmits, and defineExpose (when using script setup)
    4. refs and reactive variables
    5. Computed properties
    6. Immediate watchers
    7. Watchers
    8. Lifecycle methods, in their correct order
    9. Non-reactive state
    10. Methods
    11. Async code using await (or Promises if you're into that sort of thing)

    Why this order? Because it more or less follows the order of execution of the code.

    It's also based on the this linting rule.

    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.