Skip to the content.

Create Nuxt module

Disclaimer

This article is a description of my own experience of creating a naxt module, with components and plugins. And is an addition to the documentation and the article:

Module registration

Name: commonModule Entry point: modules/commonModule/index.ts

Global module options

Let’s tell nuxt about the new module and set the global options in nuxt.config.ts:

modules: [
   '@nuxtjs/i18n',
   '@nuxtjs/axios',
   ['~/modules/commonModule', { namespace: 'commonModule', option1: 'something' }] //* Попадает в переменную moduleOptions в точке входа модуля
 ],

 commonModule: { nuxtInitialValue: 22, debug: true }, //* В точке входа в модуль это будет: nuxt.options.commonModule

Accessing parameters from a module Entry point

In the entry point modules/commonModule/index.ts we access the globally defined options like this:

const commonModule: Module<Options> = function (moduleOptions) {

  const { nuxt } = this

  const options = {
    ...moduleOptions,             // { namespace: 'commonModule', option1: 'something' }
    ...nuxt.options.commonModule  // { nuxtInitialValue: 22, debug: true }
  }

Accessing parameters from plugin

Access global nuxt module options defined in nuxt.config.ts from helpers plugin modules/commonModule/plugins/helpers/helpers.ts:

const options = JSON.parse(`<%= JSON.stringify(options) %>`) //! Доступ к глобальным опциям nuxt модуля, определенным в nuxt.config.ts
const { namespace } = options
console.log(`===== helpers plugin ===== ${namespace} options: `, options)

Plugins

For example, let’s create a helpers plugin with a list of functions that we want to use both in the commonModule module and anywhere in the application. modules/commonModule/plugins/helpers/helpers.ts:

import { Plugin } from '@nuxt/types'
import { FileStateFile, IHelpers } from './interfaces';

const helperFunctions: IHelpers = {

  capitalize: (str: string): string => {
    return str.charAt(0).toUpperCase() + str.slice(1)
  },
  ...
}

Ways to inject

Next, you need to inject the plugin functions in order to be able to use them. In the article mentioned at the beginning, inject is advised to do [as in the file] (https://medium.com/carepenny/creating-a-nuxt-module-1c6e3cdf1037#2264) modules/commonModule/plugins/index.ts after importing plugin functions from modules/commonModule/plugins/helpers/index.ts

So in the files of each plugin То есть в: modules/commonModule/plugins/helpers/helpers.ts ...

I liked the second idea better. Because as a result, after the creation of the module, the transparency of the logic is preserved. It turns out:

I got it like this modules/commonModule/plugins/helpers/helpers.ts:

import { Plugin } from '@nuxt/types'
import { FileStateFile, IHelpers } from './interfaces';

const helperFunctions: IHelpers = {

  capitalize: (str: string): string => {
    return str.charAt(0).toUpperCase() + str.slice(1)
  },
  ...
}

const helpersPlugin: Plugin = (context, inject) => {
  inject('capitalize', helperFunctions.capitalize)
  ...
}

export default helpersPlugin;

Thus, as a result of many hours of reading articles and documentation, trial and error, I came to the conclusion that I do not need the following files, which Jamie Curnow describes in the article:- modules/commonModule/plugins/index.ts

But it’s all a matter of taste for everyone. Both approaches have a right to exist. I am for justified minimalism.

Plugin call

This is how we call plugin functions from anywhere. Whether it’s a custom module where the plugin is defined. Or anywhere in the app.

this.$nuxt.$options.$capitalize(test)

The plugin defined in this way modules/commonModule/plugins/helpers/helpers.ts after rebuilding the application “sprouts” into .nuxt/commonModule/plugins/helpers/helpers.ts

Components

I will not rewrite the description of creating components, it is perfectly described in the indicated sources. Below are the points that helped me.

In my case, it was not creating components and plugins from scratch. And the transfer of previously written code to the nuxt module. So you should have done this:

Using .sync

Parent:

<file-manager :sort-by.sync="sortBy" />
 get sortBy() {
   return this.$store.state.gui.gcodefiles.sortBy
 }
 
 set sortBy(newVal) {
   if (newVal === undefined) newVal = "modified"
 
   this.$store.dispatch('gui/saveSetting', { name: "gcodefiles.sortBy", value: newVal })
 }

Child:

@PropSync('sortBy') sortBySync!: string

In the markup and code of the child component (the component that we transfer to the nuxt module), we use sortBySync

Declaration

Without this block, it will not be possible to insert the components of our module into *.vue pages So that TypoScript can import .vue files. For example like this: modules/commonModule/components/lib/index.ts

import WebcamCard from './WebcamCard.vue'
import FileManager from './FileManager.vue'

You will need to write a declaration. Create a file fileName.d.ts in the root of the application module.d.ts:

declare module "*.vue" {
 import Vue from 'vue'
 export default Vue
}

Specify in the nuxt configuration where to get the components

In nuxt.config.ts specify the folder where to get the modules from. Now we have not only the components folder, as it was before we created our own module, but also modules/commonModule/components/lib. That is, in nuxt.config.ts it was like this:

components: true

Стало:

components: [
   '~/components',
   { path: 'modules/commonModule/components/lib', extensions: ['vue'] }
 ],

About the components property, you can почитать тут

You can check if our project sees our commonModule along with its components like this Rebuild project: npm run dev And we check the file with the list of nuxt components: .nuxt/components/readme.md and see that our component, for example called FileManager (modules/commonModule/components/lib/FileManager.vue) is available for insertion into pages as

<FileManager>
<file-manager>

and reading from modules/commonModule/components/lib/FileManager.vue

- `<FileManager>` | `<file-manager>` (modules/commonModule/components/lib/FileManager.vue)