モジュールは、Nuxt.js のコア機能を拡張し、無限のインテグレーションを加える Nuxt.js の拡張機能です。
Nuxt を使ってプロダクションレベルのアプリケーションを開発していると、Nuxt のコア機能が十分ではないことにすぐに気が付くでしょう。Nuxt はオプション設定やプラグインにより拡張できますが、複数のプロジェクトにわたってそれらのカスタマイズをメンテナンスしていくことは、退屈で、繰り返される、時間を浪費する作業です。しかし一方であらゆるプロジェクトのニーズを盛り込んでしまうと、Nuxt がとても複雑になり使いづらいものになってしまうでしょう。
これが Nuxt が、コア機能を簡単に拡張できるようにするために、より高度なモジュールシステムを導入する理由のひとつです。モジュールは、Nuxt 起動時に順番に呼び出される、シンプルな関数です。フレームワークは Nuxt が処理を続けるよりも前に、各モジュールが処理を完了するまで待機します。このようにして、モジュールは Nuxt のほとんどすべての項目をカスタマイズできます。Webpack の Tapable に基づいた Nuxt のモジュール設計のおかげで、モジュールは例えばビルドの初期化のような特定のエントリーポイントに、フックを簡単に登録できるのです。また、モジュールはテンプレートの上書き、webpack のローダーの設定、CSS ライブラリの追加、その他多くの便利なタスクを実行することができます。
素晴らしいことに Nuxt モジュールは npm パッケージと統合できます。したがって複数のプロジェクト間で再利用したり、Nuxt コミュニティでシェアすることが容易にできます。そして高品質の Nuxt アドオンのエコシステムをつくっていくことに繋がるでしょう。
もしあなたが下記に該当するならば、モジュールはきっと役に立ってくれるでしょう:
Nuxt.js チームが提供している 公式 モジュール:
コミュニティによって作成されたモジュール一覧は https://github.com/topics/nuxt-module で確認できます。
既に言及されているように、モジュールはただの関数です。npm モジュールとしてパッケージングしたり、あるいはプロジェクトのソースコードに直接インクルードすることができます。
modules/simple.js
export default function SimpleModule (moduleOptions) {
// ここにあなたのコードを書く
}
// モジュールを npm パッケージとして公開するのであれば必須
// module.exports.meta = require('./package.json')
moduleOptions
これは modules
の配列を利用するために、モジュールの利用者から渡されるオブジェクトです。これを使うことで modules のふるまいをカスタマイズすることができます。
this.options
この参照を利用して Nuxt options へ直接アクセスすることができます。これはすべてのデフォルトのオプションがアサインされた、ユーザーの nuxt.config.js
の内容です。モジュール間で共有されるオプションとして利用できます。
this.nuxt
現在の Nuxt インスタンスへの参照です。利用可能なメソッドは Nuxt クラスのドキュメント を参照してください。
this
モジュールのコンテキストです。利用可能なメソッドは モジュールコンテナ クラスのドキュメントを参照してください。
module.exports.meta
この行は npm パッケージとして公開するときは必須です。Nuxt はあなたのパッケージをより良く機能させるために、内部でメタ情報を利用します。
nuxt.config.js
export default {
modules: [
// シンプルな使い方
'~/modules/simple'
// 直接オプションを渡す
['~/modules/simple', { token: '123' }]
]
}
それから Nuxt にプロジェクトでいくつかの特定のモジュールをロードするよう伝えます。その際に任意のパラメーターを options として渡すようにします。詳しくは モジュール設定 を参照してください。
すべてのモジュールが同期的に処理を行うわけではありません。例えばどこかの API からフェッチしたり IO を非同期的に扱うモジュールを開発したい場合もあるでしょう。このような場合のために Nuxt は Promise を返したりコールバックを呼び出す非同期モジュールをサポートしています。
async
/await
は Node.js 7.2 より上のバージョンでしかサポートされていないことに注意してください。そのため、あなたがモジュール開発者であれば、少なくとも async
/await
を使用しているかどうかをユーザーに知らせてください。大きめの非同期モジュールを作成したり、レガシーサポートを行いやすくするため、バンドラを利用して古い Node.js と互換性を持たせるよう変換するか、Promise メソッドに変換するかを選ぶことができます。
import fse from 'fs-extra'
export default async function asyncModule() {
// `async`/`await` を使って非同期処理ができる
let pages = await fse.readJson('./pages.json')
}
import axios from 'axios'
export default function asyncModule() {
return axios.get('https://jsonplaceholder.typicode.com/users')
.then(res => res.data.map(user => '/users/' + user.username))
.then(routes => {
// Nuxt のルートを拡張して何かの処理を行う
})
}
nuxt.config.js
に登録しているモジュールのトップレベルのオプションを使用すると、より便利な時があります。オプションは複数組み合わせることができます。
nuxt.config.js
export default {
modules: [
['@nuxtjs/axios', { anotherOption: true }]
],
// axios モジュールは下記のオプションを `this.options.axios` で利用できることを知っている
axios: {
option1,
option2
}
}
module.js
export default function (moduleOptions) {
// `options` は option1, option2 そして anotherOption を含む
const options = Object.assign({}, this.options.axios, moduleOptions)
// ...
}
モジュールが追加されるときに、ひとつ以上のプラグインを提供することは一般的です。例えば bootstrap-vue モジュールは bootstrap-vue モジュール自身を Vue に登録することを求めます。このようなケースのため this.addPlugin
ヘルパーが用意されています。
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) {
// `plugin.js` テンプレートを登録する
this.addPlugin(path.resolve(__dirname, 'plugin.js'))
}
登録されたテンプレートやプラグインは、登録されたプラグインの出力を条件に応じて変更するために lodash templates を利用できます。
plugin.js
// Google Analytics UA をセットする
ga('create', '<%= options.ua %>', 'auto')
<% if (options.debug) { %>
// 開発時のみのコード
<% } %>
module.js
import path from 'path'
export default function nuxtBootstrapVue (moduleOptions) {
// `plugin.js` テンプレートを登録する
this.addPlugin({
src: path.resolve(__dirname, 'plugin.js'),
options: {
// Nuxt はプラグインをプロジェクトにコピーする際に `options.ua` を `123` に置き換える
ua: 123,
// 開発時のみ有効な部分であり、プロダクションビルド時にはプラグインのコードから取り除かれる
debug: this.options.dev
}
})
}
モジュールが CSS ライブラリを提供する際、重複を回避するために CSS ライブラリが存在しているかの確認や、モジュール内の CSS ライブラリの無効化オプションの追加を検討してください。
module.js
export default function (moduleOptions) {
if (moduleOptions.fontAwesome !== false) {
// Font Awesome を追加する
this.options.css.push('font-awesome/css/font-awesome.css')
}
}
ビルド時にアセットを出力するために Webpack のプラグインを登録することができます。
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) => {
// info 変数の内容を用いて `.nuxt/dist/info.txt' を生成する
// source はバッファとなる
compilation.assets['info.txt'] = { source: () => info, size: () => info.length }
cb()
})
}
})
}
nuxt.config.js
内の build.extend
と同じように this.extendBuild
を使うことができます。
module.js
export default function (moduleOptions) {
this.extendBuild((config, { isClient, isServer }) => {
// `.foo` ローダー
config.module.rules.push({
test: /\.foo$/,
use: [...]
})
// 既存のローダーをカスタマイズする
// 詳しくは Nuxt 内部のソースコードを参照:
// https://github.com/nuxt/nuxt.js/tree/dev/packages/builder/src/webpack/base.js
const barLoader = config.module.rules.find(rule => rule.loader === 'bar-loader')
})
}
単に Nuxt の初期化処理時だけではなく、特定の条件下でのみ、モジュールにある処理を実行させたいこともあるでしょう。強力な Hookable Nuxt.js システムを使用して特定のイベントでタスクを実行できます。タスクが Promise を返すか async
として定義されている場合は Nuxt はその関数を待機します。
以下が基本的な例です。
export default function myModule() {
this.nuxt.hook('modules:done', moduleContainer => {
// 全てのモジュールのロードが完了したときに呼ばれます
})
this.nuxt.hook('render:before', renderer => {
// renderer が作成された後に呼ばれます
})
this.nuxt.hook('build:compile', async ({name, compiler }) => {
// コンパイラ (デフォルト: webpack) が始まる前に呼ばれます
})
this.nuxt.hook('generate:before', async generator => {
// Nuxt が pages を generate する前に呼ばれます
})
}
実験的
v2.4.0
からは、Nuxt モジュールのパッケージを通してカスタムの nuxt コマンドを追加することができます。そのためには、コマンドを定義するときに NuxtCommand
API に従ってください。仮想的に my-module/bin/command.js
に置かれたシンプルな例は次のようになります。
#!/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)
}
})
ここで注意すべきことがいくつかあります。まず、Node 実行ファイルを取得するための /usr/bin/env
の呼び出しを忘れないでください。 また、ES モジュールの構文は、esm
をコードに手動で組み込んでいない限り、コマンドには使用できません。
次に、NuxtCommand.run()
がコマンドの設定と振る舞いを指定するためにどのように使われるかに気づくでしょう。オプションは options
で定義され minimist
によってパースされます。引数がパースされると、NuxtCommand
インスタンスを最初のパラメータとして run()
が自動的に呼び出されます。
上の例では、cmd.argv
はパースされたコマンドライン引数を取得するために使われています。NuxtCommand
には更に多くのメソッドとプロパティがあります -- これらのドキュメントはこの機能がさらにテストされ改善されていくにつれて提供されるでしょう。
コマンドを Nuxt CLI で認識できるようにするには、それを package.json の bin
セクションの下に、nuxt-module
規約を使って記述してください。この module
はパッケージの名前に関係します。この中心的なバイナリを使って、さらに subcommands
をパースするために argv
を使うこともできます。
{
"bin": {
"nuxt-foobar": "./bin/command.js"
}
}
(NPM か Yarn によって)パッケージがインストールされると、コマンドラインで nuxt foobar ...
を実行できるようになります。
モジュールには他にも多くのフックがあり、また他にももっとできることがあります。Nuxt の内部 API については Nuxt Internals を参照してください。
間違いを見つけた、またはドキュメントに貢献したいですか? GitHub でこのページを編集する