Nuxt.JS Module

From WikiOD

Modules are Nuxt.js extensions that can extend its core functions and add unlimited integrations.

introduce[edit | edit source]

When using Nuxt to develop applications, you will soon find that the core functions of the framework are not enough. Nuxt can be extended with configuration options and plugins, but maintaining these customizations in multiple projects is tedious, repetitive, and time-consuming. On the other hand, the need to support each project out of the box will make Nuxt very complicated and difficult to use.

This is why Nuxt provides a higher-level module system that can easily expand the core. Modules are just functions that are called in order when Nuxt is booted. The framework waits for each module to complete before loading. In this way, the module can be customized almost anywhere in Nuxt. We can use the powerful  Hookable  Nuxt.js system to complete tasks for specific events.

Most importantly, Nuxt modules can be merged into npm packages. This makes them easy to reuse across project development and share with the Nuxt community, and we can create a high-quality Nuxt add-on ecosystem.

If you:

  • Be a member of an excellent team and need to guide new projects quickly.
  • Tired of reinventing the wheels for common tasks such as integrating Google Analytics.
  • Is an excellent open source enthusiast, hope to easily share your work with the community.
  • It is a member of an enterprise company that values ​​quality and reusability.
  • It is usually completed within a short period of time, and there is no time to learn more about the details of each new library or integration.
  • Tired of dealing with major changes to low-level interfaces, and need something that works properly.
Nuxt.js module list[edit | edit source]

The Nuxt.js team provides official modules:

  • @nuxt/http : Lightweight and universal HTTP request based on ky-universalModules are Nuxt.js extensions that can extend its core functions and add unlimited integrations.
  • @nuxtjs/axios : Safe and easy to use Axios integrates with Nuxt.js to request HTTP
  • @nuxtjs/pwa : Use rigorously tested, updated and stable PWA solutions to enhance Nuxt
  • @nuxtjs/auth : Nuxt.js authentication module, providing different schemes and authentication strategies

Community list of modules can be made Nuxt.js  https://github.com/topics/nuxt-module  query

Basic module[edit | edit source]

As mentioned above, modules are just simple functions. They can be packaged as npm modules or directly included in the project source code.

modules/simple.js

export default function SimpleModule (moduleOptions) {
   // Write your code here
 }
 
 // REQUIRED if publishing as an npm package
 // module.exports.meta = require('./package.json')

moduleOptions

This is the user using the modules array to pass objects, we can use it to customize its behavior.

this.options

You can use this attribute to directly access Nuxt options. This is nuxt.config.js, which contains all the default options and can be used to share options between modules.

this.nuxt

This is a reference to the current Nuxt instance. Please refer to  Nuxt class docs for available methods .

this

For the context in modules, please refer to  ModuleContainer  to see the available methods.

module.exports.meta

If you want to publish the module as an npm package, you need to configure this option. Nuxt uses meta internally to better handle your packages.

nuxt.config.js

export default {
   modules: [
     // Simple usage
     '~/modules/simple'
 
     // Passing options
       ['~/modules/simple', { token: '123' }]
   ]
 }

Then, we tell Nuxt to load some specific modules for the project and use optional parameters as options. Please refer to the  module configuration  document to see more!

Asynchronous module[edit | edit source]

Not all modules will complete all operations synchronously. For example, you may want to develop a module that needs to obtain certain APIs or perform asynchronous IO. For this reason, Nuxt supports returning Promises or calling callbacks in asynchronous modules.

Project name use async/await[edit | edit source]

Please note that the use of async / await is only supported in Node.js> 7.2. Therefore, if you are a module developer, you should at least warn users that the Node.js version cannot be lower than 7.2 when using them. For a large number of asynchronous modules or better traditional support, you can use bundler to convert it to be compatible with older Node.js versions or Promise methods.

import fse from 'fs-extra'
 
 export default async function asyncModule () {
   // You can do async works here using `async`/`await`
   const pages = await fse.readJson('./pages.json')
 }
Return Promise[edit | edit source]
import axios from 'axios'
 
 export default function asyncModule () {
   return axios.get('<nowiki>https://jsonplaceholder.typicode.com/users'</nowiki>)
     .then(res => res.data.map(user => '/users/' + user.username))
     .then((routes) => {
       // Do something by extending Nuxt routes
     })
 }
Use callback[edit | edit source]
import axios from 'axios'
 
 export default function asyncModule (callback) {
   axios.get('<nowiki>https://jsonplaceholder.typicode.com/users'</nowiki>)
     .then(res => res.data.map(user => '/users/' + user.username))
     .then((routes) => {
       callback()
     })
 }


Common modules[edit | edit source]
Highest priority option[edit | edit source]

Sometimes it is more convenient to use top-level options when registering modules in nuxt.config.js, which allows us to combine multiple option sources.

nuxt.config.js

export default {
   modules: [
     ['@nuxtjs/axios', { anotherOption: true }]
   ],
 
   // axios module is aware of this by using `this.options.axios`
   axios: {
     option1,
     option2
   }
 }

module.js

export default function (moduleOptions) {
   const options = Object.assign({}, this.options.axios, moduleOptions)
   // ...
 }
Provide plug-ins[edit | edit source]

Usually, a module needs to provide one or more plug-ins when it is added. For example: The bootstrap-vue  module needs to register itself in Vue. For this we can use the this.addPlugin method.

plugin.js

import Vue from 'vue'
 import BootstrapVue from 'bootstrap-vue/dist/bootstrap-vue.esm'
 
 Vue.use(BootstrapVue)

module.js

import path from 'path'
 
 export default function nuxtBootstrapVue (moduleOptions) {
   // Register `plugin.js` template
   this.addPlugin(path.resolve(__dirname, 'plugin.js'))
 }
Template plugin[edit | edit source]

Registered templates and plugins can use lodash templates to conditionally change the output of registered plugins.

plugin.js

// Set Google Analytics UA
 ga('create', '<%= options.ua %>', 'auto')
 
 <% if (options.debug) { %>
 // Dev only code
 <% } %>

module.js

import path from 'path'
 
 export default function nuxtBootstrapVue (moduleOptions) {
   // Register `plugin.js` template
   this.addPlugin({
     src: path.resolve(__dirname, 'plugin.js'),
     options: {
       // Nuxt will replace `options.ua` with `123` when copying plugin to project
       ua: 123,
 
       // conditional parts with dev will be stripped from plugin code on production builds
       debug: this.options.dev
     }
   })
 }
Add CSS library[edit | edit source]

Consider whether there is a CSS library to avoid duplication, and add an option to disable the CSS library in the module. See the example below.

module.js

export default function (moduleOptions) {
   if (moduleOptions.fontAwesome !== false) {
     // Add Font Awesome
     this.options.css.push('font-awesome/css/font-awesome.css')
   }
 }


Emit assets[edit | edit source]

We can register the webpack plugin to emit resources during the build.

module.js

export default function (moduleOptions) {
   const info = 'Built by awesome module - 1.3 alpha on ' + Date.now()
 
   this.options.build.plugins.push({
     apply (compiler) {
       compiler.plugin('emit', (compilation, cb) => {
         // This will generate `.nuxt/dist/info.txt' with contents of info variable.
         // Source can be buffer too
         compilation.assets['info.txt'] = { source: () => info, size: () => info.length }
 
         cb()
       })
     }
   })
 }
Register custom loaders[edit | edit source]

We can use this.extendBuild to perform the same operation as build.extend in nuxt.config.js.

module.js

export default function (moduleOptions) {
     this.extendBuild((config, { isClient, isServer }) => {
       // `.foo` Loader
       config.module.rules.push({
         test: /\.foo$/,
         use: [...]
       })
 
       // Customize existing loaders
       // Refer to source code for Nuxt internals:
       // <nowiki>https://github.com/nuxt/nuxt.js/tree/dev/packages/builder/src/webpack/base.js</nowiki>
       const barLoader = config.module.rules.find(rule => rule.loader === 'bar-loader')
   })
 }


Run the task on the specified hook[edit | edit source]

Your module may only need to perform operations under certain conditions, not just during Nuxt initialization. We can use the powerful Tapable plug-in to perform tasks for specific events. Nuxt will wait for the hook to return Promise or be defined as async (asynchronous).

export default function () {
   // Add hook for modules
   this.nuxt.hook('module', (moduleContainer) => {
     // This will be called when all modules finished loading
   })
 
   // Add hook for renderer
   this.nuxt.hook('renderer', (renderer) => {
     // This will be called when renderer was created
   })
 
   // Add hook for build
   this.nuxt.hook('build', async (builder) => {
     // This will be called once when builder created
 
     // We can even register internal hooks here
     builder.hook('compile', ({ compiler }) => {
       // This will be run just before webpack compiler starts
     })
   })
 
   // Add hook for generate
   this.nuxt.hook('generate', async (generator) => {
     // This will be called when a Nuxt generate starts
   })
 }
Module package commands[edit | edit source]

Experimental

Starting from v2.4.0, you can add custom nuxt commands through the package of the Nuxt module. To do this, you must follow the API rules when NuxtCommand defines commands. Suppose a simple example of my-module/bin/command.js is placed as follows:

#!/usr/bin/env node
 
 const consola = require('consola')
 const { NuxtCommand } = require('@nuxt/cli')
 
 NuxtCommand.run({
   name: 'command',
   description: 'My Module Command',
   usage: 'command <foobar>',
   options: {
     foobar: {
       alias: 'fb',
       type: 'string',
       description: 'Simple test string'
     }
   },
   run (cmd) {
     consola.info(cmd.argv)
   }
 })

Here are some things worth noting. First, pay attention to calling /usr/bin/env to retrieve the Node executable file. Please also note that ES module syntax cannot be used for commands unless you manually merge esm into the code.

Next, you will notice how to use NuxtCommand.run() to specify the settings and behavior of the command. Define options options, by parsing minimist . After parsing the parameters, run() will be automatically called with the NuxtCommand` instance as the first parameter.

In the above example, cmd.argv is used to retrieve the parsed command line parameters. There are more methods and properties NuxtCommand --- will provide documentation about them, because this feature will be further tested and improved.

To make your command recognize the bin through Nuxt CLI, please use the nuxt-module convention to list it under the package.json section. The convention module is related to your package name. Using this binary file, you can further parse more subcommands according to argv needs.

{
   "bin": {
     "nuxt-foobar": "./bin/command.js"
   }
 }

Once the package is installed (via NPM or Yarn), you can nuxt foobar... execute it on the command line.

Modules have many hooks and possibilities. Please refer to  Nuxt Internals for  more information about Nuxt Internal APIs.