Ingredients
- 100gr of Nuxt 3
- 1 spoon of @nuxt/kit
- 1L of Nuxt Module Builder
- 100 tons of
node_modules
- 1 bowl of great ideas
- 1 pinch of Vitest (optional)
Preparation
1) Start by pouring 1L of Nuxt Module Builder into a big bowl (this also works if you use a Terminal).
npx nuxi init -t module my-amazing-recipe
If you succeeded this simple but very important step, your folder structure should be nicely firm and moist. It should look like the image below; if not, you failed and should start over.
2) It is now time to add a 100 tons of node_modules
to make sure your mixture doesn't end up too light. We want something really big and thick. Run this command that should do the trick.
yarn install # or npm install
3) The runtime
folder is the place we're going to add most of our great ideas. If you bought your ingredients from Nuxt Module Builder as recommended, there should already be a plugin.ts
file in it. Let's add our recipe there.
// ./src/runtime/plugin.ts
import { defineNuxtPlugin } from '#app'
export default defineNuxtPlugin(nuxtApp => {
nuxtApp.provide('recipe', 'my-amazing-recipe')
})
4) Alright so now that we have provided
this recipe to our dish, let's add a convenient way to read it.
// ./src/runtime/composables/useRecipe/index.ts
/**
* Use the recipe.
*/
export function useRecipe () {
const { $recipe } = useNuxtApp()
return $recipe
}
But for our TypeScript lovers out there, you probably won't like that any
type at all. So, let's spice things up a little bit.
// ./src/runtime/plugin.ts
import { defineNuxtPlugin } from '#app'
export default defineNuxtPlugin(() => ({
provide: {
recipe: 'my-amazing-recipe'
}
}))
Go back to your composable and enjoy that sweet sweet string
type.
5) At this point - and since you're an amazing cook - you should try to make sure that your dish tastes exactly as you'd expect
. Unfortunately, at the time of writing, it's not yet super straight forward. I'm sure we'll get that nice and creamy @nuxt/test-utils
ready for Nuxt 3 in no time but for the sake of our high quality meal, let's just pretend we had it already.
- Add some vitest into the mix.
yarn add --dev vitest
- Immediately add a pinch of testing.
// ./src/runtime/composables/useRecipe/index.test.ts
import { describe, it, expect } from 'vitest'
import { useRecipe } from '.'
describe('useRecipe', () => {
it('should show my recipe', () => {
expect(useRecipe()).toBe('my-amazing-recipe')
})
})
- Run this command and let it fail miserably (for now).
yarn vitest
6) Alright, we're almost done. The last step before putting our mixture into the oven is to ensure that our little useRecipe
composable will evenly expand across all components. The technical cooking term is auto-importing
. But some people like it better when they can choose where they want more flavour, so let's make it optional.
// ./src/module.ts
import { resolve } from 'path'
import { fileURLToPath } from 'url'
import { defineNuxtModule, addPlugin, addAutoImportDir } from '@nuxt/kit'
export interface ModuleOptions {
addPlugin: boolean;
autoImport: boolean; // Add some type for your option.
}
export default defineNuxtModule<ModuleOptions>({
...,
defaults: {
addPlugin: true,
autoImport: true // Set the default option to true.
},
setup (options, nuxt) {
if (options.addPlugin) {
const runtimeDir = fileURLToPath(new URL('./runtime', import.meta.url))
nuxt.options.build.transpile.push(runtimeDir)
addPlugin(resolve(runtimeDir, 'plugin'))
if (options.autoImport) {
// Use that magic helper to auto-import your composables.
addAutoImportDir(resolve(runtimeDir, 'composables'))
}
}
}
})
7) Great, I think we're all set. Let's put it in the oven.
// ./playground/app.vue
<script setup>
const { $recipe } = useNuxtApp()
</script>
<template>
<div>
{{ $recipe }}
</div>
</template>
Let's set it to 180°C by running yarn dev
for about a few seconds because it's running Vite and it's just way too fast, which kind of ruins this step for me.
8) Let's head over to http://localhost:3000
and see if our recipe really is as amazing as my-amazing-recipe
.
9) You're such a good cook. 🎉
Top comments (0)