この記事は Drupal Advent Calendar 2021 の22日目です。
DruxtJS は、Nuxt.js と Drupal を組み合わせたフル デカップルのサイトや SPA を構築するためのフレームワークです。Drupal をコンテンツ リポジトリとして利用しながら、Nuxt.js ベースの SPA や SSG サイトを構築することができます。
TL;DR: Druxt = DRUpal + nUXT.
Drupal と Vue.js でデカップル構成のシステムを構築する際の有力な選択肢になりそうです。ここでは、DruxtJS 公式サイトの資料に従って、デモサイトの動作とクイックスタートの手順を確認してみた内容をレポートします。
Umami デモ
Drupal のデモ用インストール プロファイルである Umami を利用したデモが用意されています。GitHub 上に、Drupal プロジェクト(バックエンド)と Nuxt プロジェクト(フロント)のリポジトリが公開されています。
まずは、これをインストールしてみました。どちらも Gitpod 上で動かせるように構成されていますが、今回はローカルの仮想マシン環境で動かすことにします。なお、Gitpod を利用した Drupal の開発環境については、Drupal Advent Calendar 2021 の5日目「最短でDrupal開発環境(お試し環境)を手に入れる2021」に解説があります。
Drupal(バックエンド)側
通常の Drupal サイトの要領でインストールします。ここでは、Drush とサイトエイリアス @local の定義を追加して次のようにローカル サイトを立ち上げました。
$ cd /var/www
$ git clone https://github.com/druxt/demo-api.druxtjs.org.git
$ cd demo-api.druxtjs.org
$ composer require drush/drush
$ drush @local sql:create
$ drush @local site:install demo_umami
なお、サイトエイリアスの使い方については、先日発売されたインプレスR&D「技術の泉」シリーズの商業誌『Drupal 9 おいしいレシピ集』にまとめましたので、是非そちらもチェックしてみてください。
ここでは、上記プロジェクトの web サブディレクトリを umami.internal という仮想ホストとして構成しました。仮想ホストの設定手順は、こちらの動画とトレーニング教材にまとめています。
正常にインストールできたら、DruxtJS Umami モジュールを有効にします。
$ drush pm:enable druxt_umami
管理用テーマの Gin がデフォルトに設定された Umami サイトが立ち上がりました。いつもの umami テーマとは違う外観で、ちょっと新鮮な感じです。
以下では、このサイト http://umami.internal/ をリポジトリ サーバーとして利用します。外部から DruxtJS のリソースへのアクセスができるように、匿名ユーザーにアクセス権を設定しておきます。
$ drush role-add-perm anonymous 'access druxt resources'
Nuxt(フロント)側
次にフロント側の Nuxt プロジェクトをインストールします。今回使用した仮想マシン ffdsm には Node.js が入っていないので、まずインストールしておきます。ffdsm は Ubuntu 20.04 ベースなので、Qiita の記事「Ubuntuに最新のNode.jsを難なくインストールする」を参考にさせていただきました。
$ sudo apt install -y nodejs npm
$ sudo npm install n -g
$ sudo n stable
$ sudo apt purge -y nodejs npm
$ exec $SHELL -l
上記手順で無事インストールされました。
$ node -v
v16.13.1
$ npx -v
8.1.2
フロント側のプロジェクトはホームディレクトリにクローンした後、ディレクトリを移動して、nuxt.config.js ファイルをエディタで開きます。
$ cd ~
$ git clone https://github.com/druxt/demo.druxtjs.org.git
$ cd demo.druxtjs.org
$ vi nuxt.config.js
119行目付近にある baseUrl の値を、先に立ち上げたバックエンド側の URL に設定します。
~
// Druxt Configuration
druxt: {
baseUrl: 'http://umami.internal',
blocks: {
~
パッケージをインストールして起動します。今回は仮想マシン上で動かすので、ホスト OS 側からアクセスできるように環境変数 HOST を 0.0.0.0 に設定しておきます。
$ npm install
$ HOST=0.0.0.0 npm run dev
…
✔ Druxt schema generated 06:26:47
✔ Nuxt files generated 06:26:48
✔ Client
Compiled successfully in 53.45s
✔ Server
Compiled successfully in 38.24s
ℹ Waiting for file changes 06:27:45
ℹ Memory usage: 316 MB (RSS: 497 MB) 06:27:45
ℹ Listening on: http://10.0.2.15:3000/
DeprecationWarning の警告が表示されますが、ポート 3000 の待ち受けで Web サーバーが起動しました。ブラウザで http://umami.internal:3000 にアクセスしてみます。
一見、普通の Umami サイトのように見えますが、Nuxt ベースのアプリケーションなので、Vue.js devtools でコンポーネントの階層を確認することができます。
設定が不十分なためか、パスが未解決になるリンクもありますが、おなじみの Umami サイトが Nuxt アプリケーションとして再現される様子はインパクトがあります。
フロント側を自作してみる
今度は、Nuxt のプロジェクトを自分で作ってアクセスしてみます。プロジェクト名は druxt にしました。
$ cd ~
$ npx create-nuxt-app druxt
create-nuxt-app v4.0.0
✨ Generating Nuxt.js project in druxt
? Project name: druxt
? Programming language: JavaScript
? Package manager: Npm
? UI framework: None
? Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Linting tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Testing framework: None
? Rendering mode: Universal (SSR / SSG)
? Deployment target: Server (Node.js hosting)
? Development tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? What is your GitHub username?
? Version control system: None
公式の Getting started with DraxtSite に従って、使用するモジュールのインストールと設定を行います。
$ cd druxt
$ npm i druxt-site
~
$ vi nuxt.config.js
nuxt.config.js ファイルの最後の部分を次のように編集します。
~
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
'druxt-site'
],
druxt: {
baseUrl: 'http://umami.internal'
},
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
}
}
生成されたプロジェクトには、pages ディレクトリの下にデフォルトの index.vue が生成されていますが、とりあえずファイル名を変更して無効にしておきます。
$ cd pages
$ mv index.vue index.vue.org
$ cd ..
この状態で実行してみます。
$ HOST=0.0.0.0 npm run dev
> druxt@1.0.0 dev
> nuxt
ℹ [HPM] Proxy created: /sites/default/files -> http://umami.internal 07:16:52
╭────────────────────────────────────────╮
│ │
│ Nuxt @ v2.15.8 │
│ │
│ ▸ Environment: development │
│ ▸ Rendering: server-side │
│ ▸ Target: server │
│ │
│ Listening: http://10.0.2.15:3000/ │
│ │
│ Druxt @ v0.15.0 │
│ API: http://umami.internal/jsonapi │
│ │
╰────────────────────────────────────────╯
ℹ Preparing project for development 07:16:54
ℹ Initial build may take a while 07:16:54
ℹ Discovered Components: .nuxt/components/readme.md 07:16:54
✔ Builder initialized 07:16:54
✔ Druxt schema generated 07:16:55
✔ Nuxt files generated 07:16:55
✔ Client
Compiled successfully in 26.63s
✔ Server
Compiled successfully in 23.81s
ℹ Waiting for file changes 07:17:25
ℹ Memory usage: 226 MB (RSS: 345 MB) 07:17:25
ℹ Listening on: http://10.0.2.15:3000/
無事起動したので、ブラウザでアクセスしてみます。
pages のほか、layouts や components の各ディレクトリも空の状態なので、この場合は DruxtSite のデフォルトの出力として、利用可能なブロック コンポーネントがすべて表示されます。必要な情報が不足しているブロックは、枠線の中にコンポーネントのオプションとブロックの設定が表示されるようです。
バックエンド側から JSON:API で提供される情報に基づいて、フロント側で自動的にコンポーネントのインスタンスが用意されるので、それらを利用して、API のドキュメントを見つつレイアウトやページをコーディングしていく流れになるのかなと思います。このあたりは、筆者に Nuxt 力がないため、Theming の具体的な検証には至りませんでした。
Storybook
最後に、Storybook を入れてみました。
$ npm i @nuxtjs/storybook
$ npx nuxt storybook
コンポーネントとして提供されるブロック、メニュー、エンティティ、ビューなどがカタログ化され、ブラウズできます。
まとめ
DruxtJS を利用したサイト作成について、導入のところを簡単に試してみました。モジュールを入れて動かすだけで、Drupal バックエンドが提供する各種ブロックが自動的にコンポーネントとして登録され、DruxtJS の API を通じて利用できるようになるので、デカップル構成におけるサイト制作がかなり楽になるのではと思いました。
DruxtJS には、他にも Proxy や JSON:API Client などの API があり、これらを利用してフォーム送信や検索といったアプリケーション機能の実装もサポートされるようです。このあたりは、Nuxt 力をつけてから改めて検証してみたいと思います。
より網羅的な紹介は、DrupalCon Europe 2021 のセッション「MAKERS & BUILDERS - DruxtJS 101- Fully Decoupled Drupal with JSON-API and Nuxtjs」をご覧になるのが良いと思います。
大変興味深い内容なので、おすすめです。