Join 13,567+ other Vue devs and get exclusive tips and insights delivered straight to your inbox, every week.
đź‘‹Hey friend! I work hard to send you amazing stuff each week.
— Michael
Hey all!
This week I've got a couple of articles for you, as well as some tips.
I'm just getting started on my next project for Mastering Nuxt. You'll find out more about that soon enough.
Enjoy the newsletter!
— Michael
Looking at a component itself is the primary way that we can figure out when and how to refactor it. But we can also look at how the component is used for some clues.
Specifically, we’re looking to see if there are subsets of this component where those features are only used together.
This suggests that there may be more than one component hidden inside of this one.
Let's say we have the following component:
<template><div v-if="conditional"><!-- ... --></div><div v-else><!-- ... --></div></template>
Because the v-if
is at the root, we know that it's not actually adding any value to this component.
Instead, we can simplify by splitting into one component for each branch of our conditional:
<template><ComponentWhereConditionalIsTrue /><ComponentWhereConditionalIsFalse /></template>
Now, we don't need to hard-code the conditional
prop — we can just use the more descriptive and specific component.
For another example, if prop1
and prop2
are only ever used together, but never with prop3
and prop4
, it could mean that the functionality relying on prop1
and prop2
should be separated from the rest of the component.
In this illustration, the usage of MyComponent
always uses two distinct sets of props, prop1
and prop2
, or prop3
and prop4
:
<MyComponent prop-1="someValue" prop-2="anotherValue" /><MyComponent prop-1="hello" prop-2="world" /><MyComponent :prop-3="34" prop-4 />
In our theoretical refactoring, we would split the component to work like this:
<FirstComponent prop-1="someValue" prop-2="anotherValue" /><FirstComponent prop-1="hello" prop-2="world" /><SecondComponent :prop-3="34" prop-4 />
Here are the steps to do this refactoring:
Learn more about this pattern in the Clean Components Toolkit.
When building a UI, there are many different states that you need to consider:
200ms
before showing a spinner. If the data loads before that, it feels faster than if you quickly flash the loading spinner on and then off again.Since 3.9 we can control how Nuxt deduplicates fetches with the dedupe
parameter:
useFetch('/api/menuItems', {// Cancel the previous request and make a new requestdedupe: 'cancel'});
The useFetch
composable (and useAsyncData
composable) will re-fetch data reactively as their parameters are updated. By default, they’ll cancel the previous request and initiate a new one with the new parameters.
However, you can change this behaviour to instead defer
to the existing request — while there is a pending request, no new requests will be made:
useFetch('/api/menuItems', {// Keep the pending request and don't initiate a new onededupe: 'defer'});
This gives us greater control over how our data is loaded and requests are made.
One of Vue's core features is the use of props. Props are how we pass data around in Vue, from parent to child components.
But not all props are created equal.
There are three main kinds:
Check it out here: 3 Kinds of Props in Vue
In Nuxt we get a new useState
composable.
But how does it compare to Pinia?
In this article for Vue Mastery, I discuss the main differences and when to use each.
Check it out here: Nuxt State Management: Pinia vs useState
"The best reaction to "this is confusing, where are the docs" is to rewrite the feature to make it less confusing, not write more docs." — Jeff Atwood
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.
Hydration errors are one of the trickiest parts about SSR — especially when they only happen in production.
Thankfully, Vue 3.4 lets us do this.
In Nuxt, all we need to do is update our config:
export default defineNuxtConfig({debug: true,// rest of your config...})
If you aren’t using Nuxt, you can enable this using the new compile-time flag: __VUE_PROD_HYDRATION_MISMATCH_DETAILS__
.
This is what Nuxt uses.
Enabling flags is different based on what build tool you’re using, but if you’re using Vite this is what it looks like in your vite.config.js
file:
import { defineConfig } from 'vite'export default defineConfig({define: {__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'true'}})
Turning this on will increase your bundle size, but it’s really useful for tracking down those pesky hydration errors.
Michael Hoffman curates a fantastic weekly newsletter with the best Vue and Nuxt links.
p.s. I also have a bunch of products/courses: