NuxtJS – 自作のmoduleを作成する

NuxtJS

https:/nuxtjs.org/

はじめに

UI/UXの設計やプロトタイプ作成してイメージを具現化し仮説検証していくプロセスを効率的に回せるようになりたいという目的でフロントエンドを触り出してから、NuxtJSを学んでいます。

今回は、NuxtJSでの自作したライブラリをモジュールとして使う方法について整理してみました。コンポーネント共通で使用するアプリ用のモジュールはどうすべきか?というところから来ています。NuxtJSには、communityから提供されるmoduleと同じように自前のモジュールをロードしてアプリケーション内で使用可能になるようなので、その仕組みを使って自作モジュールを作成していきます。

理解の誤りがあるかもしれませんので記述内容については個人の責任のもと判断ください。

NuxtJSのビルドの流れ

以下のソースを参考に、ssrモードでnuxt run devを実行した時の大まかな流れを掴んでおきます。

https://github.com/nuxt/nuxt.js/blob/2.x/packages/cli/src/commands/dev.js

  • Nuxtインスタンスの作成と初期処理(ready)
    • moduleのreadyはここで実行される。
      moduleのhandlerが実行される(実行コンテキストはModuleContainerインスタンスでnuxt.config.jsで指定したmoduleのオプションが引数に渡される)
  • Server インスタンスの作成と初期処理(ready)
    • VueRendererインスタンスの作成と初期処理(ready)
      • manifestファイルなどを読む(dev時はmemoryfsから)
  • Serverのlisten
  • バナーの表示
  • ビルド
    • .nuxtディレクトリにアプリケーションリソースをgenerate
    • webpackビルド

モジュールでできること

プラグインやビルド、serverMiddleWare、フックなどの機能を提供することができます。

// プラグイン
// MyComponent.vue
this.$myplugin.mymethod()

// serverMiddleWare
export default function (req, res, next) {
  console.log(`request: ${req.url}`)
  next()
}

NuxtJSでモジュールを作成する

単純な出力だけを行なうモジュールを作成し、モジュール作成のイメージをつかみます。

モジュールのファイル構成

作成するモジュールの構成は以下のとおり。

$ 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がロードされるようになります。

// nuxt.config.js
// Modules (https://go.nuxtjs.dev/config-modules)
modules: [
  '~/modules/mymodule', // mymoduleをロードする。
],

オプションがある場合は以下のようにして渡すことができます。

// nuxt.config.js
// Modules (https://go.nuxtjs.dev/config-modules)
modules: [
  ['~/modules/mymodule', { optionKey: 'optionValue' }]
],

なお、他にも以下のような書き方もできます。

// 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

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されます。

// .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

import mymodule from "./mymodule";

export default ({ app, $config }, inject) => {
  const mymod = mymodule({ var: "value" });
  inject("mymodule", mymod);
};

ここでは、inject関数を呼び、コンポーネントなどからthis.$mymoduleのように呼び出せるようにします。

mymodule.js

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はテンプレートファイルとしてコンパイルされるので、オプションの値を元に生成するソースを可変にもできます。

Object.assign(mymodule.prototype, {
  hello() {
    return "<%= options.myopt %>";
  }
});

componentからmymoduleを呼び出す

// 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で追加したリソースは、テンプレートとしてコンパイルされる。

参考リンク

 

byebyehaikikyou

日記やIT系関連のネタ、WordPressに関することなど様々な事柄を書き付けた雑記です。ITエンジニア経験があるのでプログラミングに関することなどが多いです。

シェアする

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

コメントする

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください