はじめに
UI/UXの設計やプロトタイプ作成してイメージを具現化し仮説検証していくプロセスを効率的に回せるようになりたいという目的でフロントエンドを触り出してから、NuxtJSを学んでいます。
今回は、NuxtJSでの自作したライブラリをモジュールとして使う方法について整理してみました。コンポーネント共通で使用するアプリ用のモジュールはどうすべきか?というところから来ています。NuxtJSには、communityから提供されるmoduleと同じように自前のモジュールをロードしてアプリケーション内で使用可能になるようなので、その仕組みを使って自作モジュールを作成していきます。
理解の誤りがあるかもしれませんので記述内容については個人の責任のもと判断ください。
NuxtJSのビルドの流れ
以下のソースを参考に、ssrモードでnuxt run dev
を実行した時の大まかな流れを掴んでおきます。
- Nuxtインスタンスの作成と初期処理(ready)
-
- moduleのreadyはここで実行される。
moduleのhandlerが実行される(実行コンテキストはModuleContainer
インスタンスでnuxt.config.js
で指定したmoduleのオプションが引数に渡される)
- moduleのreadyはここで実行される。
- Server インスタンスの作成と初期処理(ready)
VueRenderer
インスタンスの作成と初期処理(ready)- manifestファイルなどを読む(dev時はmemoryfsから)
- Serverのlisten
- バナーの表示
- ビルド
.nuxt
ディレクトリにアプリケーションリソースをgenerate- webpackビルド
モジュールでできること
プラグインやビルド、serverMiddleWare、フックなどの機能を提供することができます。
1 2 3 4 5 6 7 8 9 |
// プラグイン // MyComponent.vue this.$myplugin.mymethod() // serverMiddleWare export default function (req, res, next) { console.log(`request: ${req.url}`) next() } |
NuxtJSでモジュールを作成する
単純な出力だけを行なうモジュールを作成し、モジュール作成のイメージをつかみます。
モジュールのファイル構成
作成するモジュールの構成は以下のとおり。
1 2 3 4 5 6 7 |
$ tree modules/mymodule/ modules/mymodule/ ├── index.js ├── mymodule.js └── plugin.js 0 directories, 3 files |
moduleによって構成は異なると思いますが、ここでは以下の構成としてみます。
- index.jsは、module機能を使えるようにする定義を書く
- plugin.jsは、Componentなどでモジュール内の機能を使用可能にする定義を書く
- mymodule.jsは、プラグイン機能の本体を書く
モジュールを利用可能にする
まず、mymoduleをNuxtJSでロードし利用可能な状態にします。nuxt.config.js
に以下のような定義を書くことで、moduleがロードされるようになります。
1 2 3 4 5 |
// nuxt.config.js // Modules (https://go.nuxtjs.dev/config-modules) modules: [ '~/modules/mymodule', // mymoduleをロードする。 ], |
オプションがある場合は以下のようにして渡すことができます。
1 2 3 4 5 |
// nuxt.config.js // Modules (https://go.nuxtjs.dev/config-modules) modules: [ ['~/modules/mymodule', { optionKey: 'optionValue' }] ], |
なお、他にも以下のような書き方もできます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// nuxt.config.js // Modules (https://go.nuxtjs.dev/config-modules) modules: [ // optionを渡す ['~/modules/mymodule', { myopt: "optvalue" }], // Objectで定義 { src: "mymodule", options: { myopt: "optvalue" }, handler: function(opts) { console.log(opts); } }, // Functionで定義 function() => { console.log(this); } ], // mymoduleのオプション // this.options.mymoduleで参照できる mymodule: { myopt: "optvalue" } |
モジュールを作成する
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
import { resolve, join } from "path"; // .nuxt/ROOT_DIR const ROOT_DIR = "mymodule"; const templatesPath = __dirname; export default function(moduleOptions) { // オプションのマージ const options = Object.assign({}, this.options.mymodule, moduleOptions); console.log(options); // ビルドされるテンプレートをダンプしてみる this.nuxt.hook( "build:templates", ({ templateVars, templatesFiles, resolve }) => { console.log(templatesFiles); } ); // .nuxt/ROOT_DIR/plugin.js // addTemplateが実行される、index.jsにpluginsがimportされる this.addPlugin({ src: resolve(templatesPath, "plugin.js"), fileName: join(ROOT_DIR, "plugin.js"), options: options }); // .nuxt/ROOT_DIR/mymodule.js this.addTemplate({ src: resolve(templatesPath, "mymodule.js"), fileName: join(ROOT_DIR, "mymodule.js"), options: options }); } |
index.jsでは、オプションのマージ、hookでビルドされるテンプレートファイルをダンプ、プラグインファイル及びテンプレートファイルを追加しています。プラグインで登録しているファイルはnuxtの実行時にimportされます。
1 2 3 4 5 6 7 8 9 10 |
// .nuxt/index.js ... /* Plugins */ import nuxt_plugin_plugin_4e57dd76 from 'nuxt_plugin_plugin_4e57dd76' // Source: ./components/plugin.js (mode: 'all') import nuxt_plugin_plugin_441b4a38 from 'nuxt_plugin_plugin_441b4a38' // Source: ./vuetify/plugin.js (mode: 'all') import nuxt_plugin_plugin_05a04c90 from 'nuxt_plugin_plugin_05a04c90' // Source: ./mymodule/plugin.js (mode: 'all') ... |
plugin.js
1 2 3 4 5 6 |
import mymodule from "./mymodule"; export default ({ app, $config }, inject) => { const mymod = mymodule({ var: "value" }); inject("mymodule", mymod); }; |
ここでは、inject関数を呼び、コンポーネントなどからthis.$mymodule
のように呼び出せるようにします。
mymodule.js
1 2 3 4 5 6 7 8 9 10 11 |
export default function mymodule(properties) { const mymod = Object.create(mymodule.prototype); Object.assign(mymod, properties); return mymod; } Object.assign(mymodule.prototype, { hello() { return "hello world"; } }); |
hello関数が登録されたオブジェクトを定義します。moduleはテンプレートファイルとしてコンパイルされるので、オプションの値を元に生成するソースを可変にもできます。
1 2 3 4 5 |
Object.assign(mymodule.prototype, { hello() { return "<%= options.myopt %>"; } }); |
componentからmymoduleを呼び出す
1 2 3 4 5 6 7 8 9 10 |
// layouts/default.vue <template> <v-app dark> {{ $mymodule.hello() }} </v-app> </template> <script> export default {}; </script> |
npm run dev
で起動してブラウザ画面を開くと、以下のような画面が表示されることを確認できます。
まとめ
- モジュール機構で自作のライブラリをNuxtアプリケーションに組み込み、コンポーネントなどから利用できる。
- モジュールを使用するには、nuxt.config.jsのmodulesで定義する。
- addTemplateやaddPluginで追加したリソースは、テンプレートとしてコンパイルされる。
参考リンク
- https://ja.nuxtjs.org/docs/2.x/concepts/nuxt-lifecycle/
- https://ja.nuxtjs.org/docs/2.x/directory-structure/modules/
- https://ja.nuxtjs.org/docs/2.x/internals-glossary/internals-module-container
- https://github.com/nuxt/nuxt.js
コメント