Nuxt.jsで、Ionic v4 betaをつかってみる

ちょっと私事があって乗り遅れた感ありますが、Ionic v4 beta版がリリースされました。

https://blog.ionicframework.com/announcing-ionic-4-beta/

※まだbeta版で、正式リリースはされておりません。正式リリースまでに仕様変更が行われる可能性は十分にありますので、ご留意ください。

で、せっかくIonic v4からはWeb Componentsベースとなり、すべてのJavaScriptフレームワーク・・・といいますか、No Framework環境も含めてIonicのUIコンポーネントを使えるようになりましたので、Nuxt.jsでの使い方をご紹介します。

なお、本記事はVue.js/Nuxt.jsを知っており、Node.jsなどはインストール済みの方を対象としております。
また、 https://github.com/rdlabo/ionic-nuxt.js でコミット履歴ふくめ公開しておりますので、不明点などありましたらこちらのレポジトリをご確認ください。

<h2>Nuxt.jsインストール</h2>
Nuxt.jsは、Vue CLIをつかって操作しますので、まずVue.jsをインストールします。

```bash
$ npm install -g vue-cli
```

実行後、私の環境では、 

```bash
npm WARN deprecated coffee-script@1.12.7: CoffeeScript on NPM has moved to "coffeescript" (no hyphen)
```

と出たのですが、この警告は「npm packageの名前が変更されてますよ」というものですので気にしなくて大丈夫です。

続いて、Vue CLIを使って、Nuxt.jsのスターターパッケージを展開し、npm iを実行します。 <code>ionic-nuxt</code> はフォルダ名となりますので、適宜変更するようにしてください。

```bash
$ vue init nuxt-community/starter-template ionic-nuxt && cd ionic-nuxt && npm i
```

途中で質問されますが、すべてEnterを押して進めてください。インストールが完了して、`$ npm run dev` で起動すると、以下のような画面がでてきます。

<img class="alignnone size-full wp-image-961" src="https://rdlabo630094126.files.wordpress.com/2018/07/e382b9e382afe383aae383bce383b3e382b7e383a7e38383e38388-2018-07-29-15-59-54.png" alt="スクリーンショット 2018-07-29 15.59.54.png"  />

なお、エラーでるときは利用しようとしているポートがすでに利用中の可能性がありますので、 https://nuxtjs.org/faq/host-port/ を確認して利用するポート番号を別のものに変更ください。
<h2>Ionicを利用する（環境作成）</h2>
Ionic v4では `Not using Angular? Ionic can also be used directly from a CDN using a simple script include!` としていて、Angular以外のユースケースではCDNからの利用を推奨しているので、CDN経由に利用します。

Nuxt.jsの設定ファイルは `nuxt.config.js` にありますので、そこに以下を追記します。

```javascript

module.exports = {
  /*
  ** Headers of the page
  */
  head: {
    title: 'ionic-nuxt',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: 'Nuxt.js project' }
    ],
    link: [
      { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
    ],
+   script: [
+     { src: 'https://unpkg.com/@ionic/core@latest/dist/ionic.js' }
+   ],
  },
```

scriptを追加することでCDN経由でIonicを取得します。
また、Nuxt.jsはServer Side Renderを行いますが、IonicはLazy LoadingでComponentsを取得するために、このままだとエラーがでます。そのため、 `@skatejs/ssr` を使ってエラーを抑制します。

```bash

$ npm i @skatejs/ssr
```

を入れたあと、 <code>plugins/webcomponents.js</code> を作成して、以下を記述します。

```javascript
import Vue from 'vue'

// Render web components server-side
if(!process.browser) {
// Avoid HTMLElement is not defined on server-side
global.HTMLElement = () => {};
// Avoid customElements is not defined on server-side
global.customElements = { define: () => {} };
// Require skatejs/ssr/register only on server side
require('@skatejs/ssr/register')
}

// Vue must ignore custom components that aren't Vue Components
Vue.config.ignoredElements = [/^ion-/];
```

また、このpluginを読み込むために、<code>nuxt.config.js</code>に以下を追記します。

```javascript

    script: [
      { src: 'https://unpkg.com/@ionic/core@latest/dist/ionic.js' }
    ],
  },
+ plugins: ['~/plugins/webcomponents.js'],
```

これで準備完了です。

<h2>Ionicを利用する（実践）</h2>
では、実際にテンプレートでIonicのComponentsを使っていきましょう。まず、Ionicは位置計算などのためにbodyよりも下位階層を<code>ion-app</code>でくくる必要があるので、<code>layouts/default.vue</code>を以下のように書き換えます。
（なぜか描画計算がうまくいかなかったので、ion-pageに高さ100%のCSSを追記します）

```html
<template>
  <ion-app>
    <nuxt/>
  </ion-app>
</template>

<style>
  ion-page {
    height:100%;
  }
</style>
```

続いて、トップページを指定している<code>pages/index.vue</code>を、すべて以下のように書き換えます。

```html

<template>
  <ion-page>
    <ion-header>
      <ion-toolbar>
        <ion-title>
          Ionic Blank
        </ion-title>
      </ion-toolbar>
    </ion-header>

    <ion-content>
      The world is your oyster.
      <p>If you get lost, the <a target="_blank" href="https://ionicframework.com/docs">docs</a> will be your guide.</p>
    </ion-content>
  </ion-page>
</template>
```

これで、Ionic v4のstarterテンプレートと同等のものができました。

|![markdown-mark.png](https://rdlabo630094126.files.wordpress.com/2018/07/localhost_3333_pixel-2-1.png)|
|:-:|

試しに、ボタンをクリックしたらToastで通知が行われるUIを作成します。

<code>pages/index.vue</code>に、以下のように追記します。

```html
<template>
  <ion-page>
    <ion-header>
      <ion-toolbar>
        <ion-title>
          Ionic Blank
        </ion-title>
      </ion-toolbar>
    </ion-header>

    <ion-content>
      The world is your oyster.
      <p>If you get lost, the <a target="_blank" href="https://ionicframework.com/docs">docs</a> will be your guide.</p>

+     <ion-button @click="presentToast">start Toast</ion-button>
    </ion-content>
+   <ion-toast-controller></ion-toast-controller>
  </ion-page>
</template>

+ <script>
+ export default {
+   methods: {
+     async presentToast() {
+       const toastController = document.querySelector('ion-toast-controller');
+       await toastController.componentOnReady();
+
+       const toast = await toastController.create({
+         message: 'Your settings have been saved.',
+         duration: 200000
+       });
+       return await toast.present();
+     }
+   }
+ }
+ </script>

```

<code>ion-button</code>を追加し、@clickでクリックイベントを設定しています。また、空の<code>ion-toast-controller</code>を追加し、イベントが発生したらToastのDOMを生成できるようにします。

clockイベントは、methodとして登録しておきます。<code>ion-toast-controller</code>をquerySelectorで取得し、そこにToastを描画します。

|![markdown-mark.png](https://rdlabo630094126.files.wordpress.com/2018/07/localhost_3333_pixel-2.png)|
|:-:|

これで、Toastイベントを設定することができました。

<h2>実装してみての感想</h2>
v4はWebComponentsベースとなり「他のフレームワークでも使えるようになった」だけで「Angularと同等に使えるようになった」わけではなく、Ionic teamはAngularにおいてはより使いやすくなる`@ionic/angular`というラッパーを用意しておりますので、特段の理由がない限りはIonic v4を利用するのはAngular上で構築するのがおすすめになると思います。

ただ、例えば「アラートボタンだけを使いたい」「モバイル向けI/Fの一部を使いたい」などのニーズには柔軟に応えることができるようになったようにも感じます。

まだbeta版ですので正式リリースは先となりますが、ぜひ興味ある方はさわってみてください。

また、末尾となりますが、Consoleのエラー抑制で悩んでいるときに解決策を教えてくださった 果物リンさん（ https://twitter.com/FruitRiin ）ありがとうございました。

それでは、また。