Skip to the content.

Создание Nuxt модуля

Дисклаймер

Эта статья является описанием собственного опыта создания модуля накст, с компонентами и плагинами. И является дополнением к документации и статье:

Регистрация модуля

Название: commonModule Точка входа: modules/commonModule/index.ts

Глобальные параметры

Расскажем nuxt о новом модуле и пропишем глобальные параметры в nuxt.config.ts:

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

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

Доступ к параметрам из точки входа модуля

В точке входа modules/commonModule/index.ts обращаемся к глобально описанным опциям так:

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

  const { nuxt } = this

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

Доступ к параметрам из плагина

Доступ к глобальным опциям nuxt модуля, определенным в nuxt.config.ts из плагина helpers 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)

Плагины

Например, создадим плагин helpers со списком функций, которые хотим использовать как в модуле commonModule, так и в любом месте приложения. 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)
  },
  ...
}

Способы сделать inject

Далее необходимо сделать inject функций плагина, чтобы иметь возможность использовать их. В статье, указанной в начале, inject советуют делать как в файле modules/commonModule/plugins/index.ts, предварительно импортировав функции плагинов из modules/commonModule/plugins/helpers/index.ts

Так и в файлах каждого плагина То есть в: modules/commonModule/plugins/helpers/helpers.ts ...

Мне больше понравилась вторая идея. Т.к. в итоге, после создания модуля, сохраняется прозрачность логики. Получается:

У меня получилось так 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;

Таким образом, в результате многих часов чтения статей и документации, проб и хождения по граблям, я пришла к выводу, что следующие файлы, которые описывает Jamie Curnow в статье, мне не нужны:

Но это встеки дело вкуса каждого. Оба подхода имеют право на существование. Я - за оправданный минимализм.

Вызов плагина

Вот так вызываем функции плагинов из любого места. Будь то собственный модуль, в котором определен плагин. Или любое место в приложении.

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

Определенный таким образом плагин modules/commonModule/plugins/helpers/helpers.ts после перебилдинга приложения “прорастает” в .nuxt/commonModule/plugins/helpers/helpers.ts

Компоненты

Я не буду переписывать описание создания компонентов, оно отлично описано в указанных источниках. Ниже моменты, которые помогли мне.

В моем случае это было не создание компонентов и плагинов “с нуля”. А перенос ранее написанного кода в nuxt модуль. Поэтому следовало сделать так:

Использование .sync

Родитель:

<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 })
 }

Дочерний:

@PropSync('sortBy') sortBySync!: string

В разметке и коде дочернего компонента (компонента, который переносим в nuxt модуль) используем sortBySync

Декларирование

Без этого блока нельзя будет вставлять компоненты нашего модуля на страницы *.vue Чтобы в TypoScript можно было импортировать .vue файлы. Например так: modules/commonModule/components/lib/index.ts

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

Потребуется прописать декларацию. Создать в корне приложения файл fileName.d.ts module.d.ts:

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

Укажем в конфигурации nuxt откуда брать компоненты

В nuxt.config.ts указать папку, откуда брать модули. Теперь у нас это не только папка components, как было до создания нами собственного модуля, но и modules/commonModule/components/lib. То есть в nuxt.config.ts было так:

components: true

Стало:

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

О свойстве components можно почитать тут

Проверить, видит ли наш проект наш commonModule вместе с его компонентами можно так Пересобираем проект: npm run dev И проверяем файл со списком nuxt компонентов: .nuxt/components/readme.md и видим, что наш компонент, например под названием FileManager (modules/commonModule/components/lib/FileManager.vue) доступен для вставки на страницы как

<FileManager>
<file-manager>

и читается из modules/commonModule/components/lib/FileManager.vue

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