Introduction to Nuxt modules
Tags: nuxt, module, vue, javascript
Published: 2021-11-19 12:15:59

Developing my first Nuxt module took much more time than I expected, probably because I had no experience in creating such modules whatsoever. I spent hours reading Nuxt.js documentation (which is very good btw), watching tutorials, inspecting code repositories of other modules, so I was finally able to create my first module -> Adyen payment module for Nuxt. But don't worry. To built a second module, it took only 3 hours (including reading platform docs ;))

One of the best sources of knowledge so far about creating Nuxt modules is an article by @debs_obrien -> <https://nuxtjs.org/tutorials/creating-a-nuxt-module/>. Definitely worth checking out alongside this article to build your next (Nuxt ;) ) module.

## What is a Nuxt module?

Nuxt.js has a very good documentation on the purpose and anatomy of [modules](https://nuxtjs.org/docs/directory-structure/modules/), so I will just copy/paste some short definitions here.

Nuxt provides a higher-order module system that makes it possible to extend the core. Modules are functions that are called sequentially when booting Nuxt.

```js
export default {
 modules: [
   // Using package name
   '@nuxtjs/axios',
 
   // Relative to your project srcDir
   '~/modules/awesome.js',
 
   // Providing options
   ['@nuxtjs/google-analytics', { ua: 'X1234567' }],
 
   // Inline definition
   function () {}
 ]
}
```

For more details, I highly encourage you to read the modules section in the Nuxt.js documentation.

## Nuxt module directory structure

Woah! There are many files here. I suppose, you can feel quite lost right now but don't worry. Below I explained each folder and meaningful file that you need to create/modify in order to have your own module set up.

![nuxt-module-directory](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rsbz9wn36zfl6384wykn.png)

### `dist`

The output of your source files written in TypeScript (if your module is built on top of that). If you are using plain JavaScript you will most probably export your package with direct `src/lib`.

### `docs`

Nuxt.js based docs for modules. Nuxt.js team provides a very good documentation template that you can see across many Nuxt modules.

![nuxt-i18n-docs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ku6mzkzr1zbvz4hczhho.png)

In here you can write instructions on how to use your module in a Nuxt application.

### `example`

In this directory you will find a very basic Nuxt project where you can test how your module works. It's good to keep it as simple as possible so that it will be easy for the newcomers to try it out.

Inside `example/nuxt.config.js` you can import the module and its options.

```js
export default {
 modules: ['../src/module.js'],
 
 'my-awesome-module': {
   option1: 'test',
   ...
 }
}
```

### `src/lib`

In this directory you will put your files related to the module itself. The most basic example contains a `module.js` and `plugin.js` files.

#### `module.js`

In simple words, this file will be used as a declaration inside the `nuxt.config.js` file in the `modules` section. It will allow for module registration and will also accept some module options that will be later used in your `plugin.js` file.

```js
const path = require('path')
 
const nuxtModule = function (moduleOptions) {
 const options = {
   ...this.options['my-awesome-module'],
   ...moduleOptions
 }
 
 this.addPlugin({
   src: path.resolve(runtimeDir, 'plugin.js'),
   fileName: 'my-awesome-module.js',
   options
 })
}
 
export default nuxtModule
```

Inside this file you can also add some error handling when a user forgets to add certain options, modify options and create separate plugins for client, server, or both.

If you need to access the underlying server of Nuxt application you can do so by calling `this.addServerMiddleware()` and passing your routes. You can see an example in Nuxt [docs](https://nuxtjs.org/docs/configuration-glossary/configuration-servermiddleware#custom-api-endpoint).

The easiest way to indicate that a plugin is server/client side only is to add a corresponding word to the plugin name, i.e.:

```js
 this.addPlugin({
   src: path.resolve(runtimeDir, 'plugin.js'),
   fileName: 'my-awesome-module.server.js',  // add .server here to make it server only
   options
 })
```

If you are using TypeScript you can also declare global typings here:

```js
declare module '@nuxt/types' {
 interface NuxtConfig {
   ['my-awesome-module']: ModuleOptions
 } // Nuxt 2.14+
 interface Configuration {
   ['my-awesome-module']: ModuleOptions
 } // Nuxt 2.9 - 2.13
 interface Context {
   ['$my-awesome-module']: Api
 }
}
```

#### `plugin.js`

In this file you will be injecting content into global Nuxt context.

```js
const configuration = <%= JSON.stringify(options, null, 2) %>
 
export default function (context, inject) {
 inject('my-awesome-module', configuration)
 context.app['my-awesome-module'] = configuration
}
```

In some cases you may want to register a component/function to be used by Vue. You can do that here:

```js
<% if (options.registerComponent) { %>
 import Vue from 'vue'
 import SomeComponent from '~directory/SomeComponent.vue'
 
 Vue.component('SomeComponent', SomeComponent);
<% } %>
```

### `test`

In this directory you will write your unit tests using Jest. The simplest unit test case can look like this:

```js
describe('module', () => {
 setupTest({
   testDir: __dirname,
   fixture: '../example',
   server: true,
   config: {
     dev: true,
     'my-awesome-module': {
       option1: 'test',
     }
   }
 })
 
 test('should have config with Adyen options', () => {
   const { option1 } = getNuxt().options['my-awesome-module']
 
   expect(option1).toBeDefined()
 })
})
```

## Summary

You just got knowledge that should allow you to create your own Nuxt module. Well done! I highly encourage you to dig into the Nuxt.js documentation about modules and plugins, as well as the source code of certain modules to get a better understanding of how it is all working together.

I have recently released two E-Commerce related packages that you may want to checkout:

* <https://github.com/Baroshem/nuxt-bigcommerce>
* <https://github.com/Baroshem/nuxt-adyen-module>

## Bonus links

* <https://github.com/Baroshem/nuxt-module-template>
* <https://github.com/nuxt-community/module-template>
* <https://modules.nuxtjs.org>