This guide aims to provide detailed insights and clear explanations to fully grasp the power and utility of Nuxt modules.
Get notified when we release new tutorials, lessons, and other expert Nuxt content.
Nuxt.js is a powerful framework built on Vue.js, designed to create universal, server-side rendered (SSR) applications. One of its standout features is its modular architecture, which makes it incredibly flexible and extendable. In this article, we will dive deep into Nuxt modules, exploring what they are, why they are beneficial, and how to get started with creating and using them.
Nuxt modules are essentially packages that extend your Nuxt application's core functionality. They can modify the Nuxt configuration, register hooks, add plugins, and seamlessly integrate third-party libraries. By encapsulating functionality into modules, you can keep your codebase clean, organized, and maintainable.
If you want to learn everything about Nuxt Modules, checkout our comprehensive course “Nuxt Modules: The Ultimate Guide” on Vue School.
There are many types for Nuxt Modules. Each type has its own characteristics and place in the ecosystem.
Official modules are developed and maintained by the Nuxt team. These modules adhere to Nuxt’s best practices, ensuring compatibility and stability. They are prefixed with @nuxt/
. Examples include @nuxt/image for optimizing images, @nuxt/content for content management, and @nuxt/ui
for building beautiful and accessible user interfaces.
Community modules are developed by the Nuxt community. These modules can be used to fill gaps not covered by official modules. They cover a wide range of use cases, from SEO enhancements to integration with various APIs and services. They are prefixed with @nuxtjs/
. Examples include @nuxtjs/i18n for internationalization for Nuxt apps and @nuxtjs/google-fonts for easy access to Google Fonts.
Third-party modules are developed by independent developers or companies. These modules may not always follow Nuxt conventions, but they can still be useful for integrating specific libraries or services that you might need.
Private or local modules are custom modules specific to your application, developed internally to encapsulate and reuse functionality across different parts of your application. These are not shared with the community but are crucial for maintaining a clean and organized codebase within your project.
Nuxt Modules are important for many reasons. Let’s go through some of the main ones.
Modules allow you to encapsulate functionality in a reusable way. This modularity helps in keeping your codebase clean and organized. You can easily share modules between projects or with the community. For example, if you develop a custom authentication mechanism, encapsulating it in a module allows you to reuse it across multiple projects without duplicating code.
Modules can abstract complex configurations, making it easier to integrate various functionalities without dealing with intricate details. For example, the @nuxtjs/tailwindcss module provides an easy way to integrate TailwindCSS with Nuxt.
Modules can hook into the Nuxt lifecycle and extend or modify the core functionality. This makes it possible to add custom behavior or integrate third-party services seamlessly. For instance, you might use a module to add custom middleware that runs during the build process, or to extend the server-side functionality with custom routes.
Using well-maintained community modules ensures you have access to a wide range of functionalities without reinventing the wheel. The community actively contributes and maintains these modules, ensuring they stay up-to-date with the latest Nuxt releases. Additionally, community modules often come with extensive documentation and examples, making it easier to integrate them into your projects.
Let’s get hands-on and create a Nuxt module from scratch. We’ll start with a simple local module and then explore how to publish it for reuse in other projects.
First, let’s create a new Nuxt project. Open your terminal and run the following commands:
mkdir nuxt-modules
cd nuxt-modules
npx nuxi@latest init nuxt-app
cd nuxt-app
This will scaffold a new Nuxt project with the necessary files and directories. Open the project in your favorite code editor to begin.
We’ll start by creating a local module inside our project. Local modules reside within the project’s file structure and are specific to that project.
modules
directory in the project root:mkdir modules
modules
directory, create a file named first-module.js
with the below code:// modules/first-module.ts
export default function () {
console.log('Hello from the module!')
}
npm run dev
You should see the message "Hello from the module!" in your terminal. This confirms that your module is being loaded and executed during the build process.
We can also define a module using the defineNuxtModule
function from @nuxt/kit
:
import { defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule((options, nuxt) => {
console.log('Hello from the module!')
})
The defineNuxtModule
function also allow us to use the object syntax to define our module:
import { defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
meta: {
// Usually the npm package name of your module
name: '@nuxtjs/example',
// The key in `nuxt.config` that holds your module options
configKey: 'sample',
// Compatibility constraints
compatibility: {
// Semver version of supported nuxt versions
nuxt: '>=3.0.0'
}
},
// Default configuration options for your module, can also be a function returning those
defaults: {},
// Shorthand sugar to register Nuxt hooks
hooks: {},
// The function holding your module logic, it can be asynchronous
setup(moduleOptions, nuxt) {
console.log('Hello from the module!')
}
})
We’re getting into all the details in our course “Nuxt Modules: The Ultimate Guide” on Vue School.
Nuxt modules are more than just simple functions. They can access and modify the Nuxt configuration, register hooks, and even add plugins. Let’s extend our module to demonstrate these capabilities.
Modules can directly modify the Nuxt configuration. For instance, let’s disable the Nuxt Devtools option from within our module. This option in enabled by default for freshly installed apps
first-module.ts
:// modules/first-module.ts
export default defineNuxtModule({
meta: {
name: 'first-module',
configKey: 'firstModule',
compatibility: {
nuxt: '>=3.0.0'
}
},
defaults: {},
setup(moduleOptions, nuxt) {
console.log('Devtools enabled by default');
nuxt.options.devtools.enabled = false;
console.log('Devtools is disabled now');
}
})
Plugins are a powerful way to extend the functionality of your Nuxt application. To inject a Nuxt plugin from within a module, we need to follow the below steps:
runtime
directory inside the modules
directory and add a file named plugin.ts
. The runtime directory is our way to pass files from the module to the application’s runtime.// modules/runtime/plugin.ts
export default defineNuxtPlugin(() => {
return {
provide: {
hello: (msg: string) => `Hello ${msg}!`
}
}
})
first-module.js
to import the addPlugin and createResolver utilities from @nuxt/kit
and include the plugin:// modules/first-module.ts
import { defineNuxtModule, addPlugin, createResolver } from '@nuxt/kit'
export default defineNuxtModule({
meta: {
name: 'first-module',
configKey: 'firstModule',
compatibility: {
nuxt: '>=3.0.0'
}
},
defaults: {},
setup(moduleOptions, nuxt) {
const { resolve } = createResolver(import.meta.url)
addPlugin(resolve('./runtime/plugin'))
}
})
App.vue
and add the following:<template>
<div>
<h1>{{ $hello('world!') }}</h1>
</div>
</template>
<script setup lang="ts">
const { $hello } = useNuxtApp()
</script>
When you’re focused on a specific app and the logic for the module is only needed there, local modules work just fine. However, if you aim to use a module across multiple apps or contribute to the Nuxt modules ecosystem, publishing your module is the way to go.
The process is a bit different from working with local modules, but Nuxt provides a fantastic starter template that simplifies the process. Instead of preparing an npm package from scratch, the template takes care of most of the boilerplate work for you.
Nuxt provides a starter template for creating and publishing modules, making the process much simpler.
npx nuxi init -t module my-nuxt-module
cd my-nuxt-module
This command sets up a new directory with a structure specifically designed for developing a Nuxt module.
package.json
: Contains metadata and dependencies for your module.src
: The source code for your module.test
: Basic tests using Vitest.playground
: A Nuxt app to test your module.src/module.ts
and define your module:import { defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
meta: {
name: 'my-nuxt-module',
configKey: 'myModule',
},
defaults: {},
setup (moduleOptions, nuxt) {
nuxt.options.devtools.enabled = false
console.log('Devtools disabled')
}
})
This code sets up a basic module that logs the module options and disables devtools.
dev
command will launch the Nuxt app in the playground, allowing you to ensure that your module works as expected.npm run dev
npm run build
npm login
npm run release
With that, any developer can install your module in their Nuxt app and register it to their nuxt.config.ts
file.
export default defineNuxtConfig({
modules: [
MyModule
]
})
Nuxt modules offer a powerful way to extend and customize your Nuxt applications. By encapsulating functionality into reusable modules, you can keep your codebase clean, maintainable, and scalable. Whether you are developing local modules for a specific project or publishing modules for the wider community, Nuxt’s modular architecture and tooling make the process straightforward and enjoyable.
Remember, the key to mastering Nuxt modules is practice and exploration. As you work on different projects, try to identify common patterns and functionalities that can be abstracted into modules. This approach will not only improve your coding skills but also make your projects more modular and easier to manage.