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
Hi!
If you like design patterns, I've got something great for you.
A free, 5 day mini-course that covers 5 different patterns for writing better components.
You can get more details and sign up for it here:
I also wrote up a detailed blog post about the new data fetching in Nuxt 3.17:
Nuxtβs Data Layer Has Been Rewritten: 5 New Features You Need to Know
No new podcast episode this week, but we've got a couple great episodes coming soon!
Have a great week!
β Michael
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.
provide
and inject
defineProps
, defineEmits
, and defineExpose
(when using script setup
)refs
and reactive
variablesawait
(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.
Yes, mini tips within a tip. It's meta.
Here they are:
use___
ref
of null
, you can update those values later when your logic completes. No need to await
around.effectScope
to group effects if you have lots of them in your composable. This makes cleaning up your reactivity a lot simpler.shallowRef
instead to prevent Vue from recursively making the whole thing reactive. Of course, you'll need to use triggerRef
to trigger any reactive effects for it, but it can improve performance.Some tips on making your composables more flexible:
watch
, make immediate
and flush
configurablerefs
and primitive values as inputs. By passing the variable through ref
, you'll either reuse the existing ref
or create a new one.unref
if what you need in your composable is a primitive and not a ref
.You can define composables inline, keeping them in your SFC file:
<script setup>const useCount = (i) => {const count = ref(0);const increment = () => count.value += 1;const decrement = () => count.value -= 1;return {id: i,count,increment,decrement,};};const listOfCounters = [];for (const i = 0; i < 10; i++) {listOfCounters.push(useCount(i));}</script><template><div v-for="counter in listOfCounters" :key="counter.id"><button @click="counter.decrement()">-</button>{{ counter.count }}<button @click="counter.increment()">+</button></div></template>
But is there any point to doing this?
If youβre keeping your components focused on a specific task (and you should be), then it stands to reason that the logic is also focused on a single task.
This means that if you wrap up all relevant logic into an inline composable, youβve wrapped up all β or nearly all β the logic that this component has:
<script setup>// Create an inline composableconst useStuff = () => {<all_our_logic>};// ...only to destructure most of it to use in our templateconst {value,anotherValue,eventHandler,anotherEventHandler} = useStuff();</script>
At which point, we might as well write our logic without that unnecessary wrapper:
<script setup>const value = ...const anotherValue = ...const eventHandler = ...const anotherEventHandler = ...</script>
However, if you have do have logic that can be encapsulated nicely within this inline composable, it could make your code cleaner and easier to use.
Using lexical scoping to create more boundaries within your files helps you to understand and think through your code, which is always helpful.
In this article I share 21 tips for working with Nuxt.
These are tips and tricks that I've found useful, and I think every Nuxt developer should know.
We cover a lot of topics here, including:
Check it out here: 21 Nuxt Tips You Need to Know
In this article I explore several features of Nuxt that I think are the most interesting.
This will give you a good overview of why Nuxt is so great to work with.
Check it out here: My Favourite Nuxt Features
Here are some upcoming events you might be interested in. Let me know if I've missed any!
VueConf US 2025 is a great Vue conference, this year held in Tampa from May 13β15, with two days of talks and a day of workshops. Unfortunately, I am no longer able to make it to the conference this year. I hope everyone attending has an amazing time and I look forward to joining in the future!
It's time to get together in Madrid. Join for a full day of talks, activities, and networking with the Vue.js community and ecosystem.
"Things arenβt always #000000 and #FFFFFF." βΒ undefined
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.
Vue allows you to do performance tracing to help you debug any performance issues:
const app = createApp({});app.config.performance = true;
Once you do this, you can use the official Vue Devtools to debug your app's performance.
Michael Hoffman curates a fantastic weekly newsletter with the best Vue and Nuxt links.
p.s. I also have a bunch of products/courses: