Nuxt.js で PWA(Progressive Web Apps) のベースアプリを作る

ウェブの技術を使い、またウェブサイトとしてホスティングしながらも、モバイルやデスクトップのアプリとして振る舞うことができる PWA。最近では Google Play Store でも配信できるようになったり、iOS での対応強化など話題に事欠きません。
そんな PWA を簡単に高速に開発することができる Nuxt.js を紹介するとともに、今後さまざまな機能を試すためのベースアプリを作ります。

シリーズの記事

環境
本記事の開発環境は以下となります。

  • Windows 10 64bit + WSL Ubuntu 18.04.1 LTS
  • Visual Studio Code
  • Node.js 12.2.0
  • Yarn 1.15.2
  • Nuxt.js 2.6.3

PWA とは

PWA は Progressive Web Apps の略称で、ウェブサイトをモバイルアプリとして使えるようにする仕組みです。さらに Google Chrome 67 からデスクトップアプリとしても動作させることができるようになりました。

アプリを PWA とすることで、以下のような機能が提供できます。

  • 端末にインストールしホームやデスクトップにアイコンを追加できる
  • ブラウザとは異なるネイティブアプリのような操作感
  • オフラインでも使えるように作ることができる
  • プッシュ通知を受け取ることができる
  • リンクやサイトへの埋め込みができる
  • 自身の運営サイト、および Google Play Store から配信できる

一方でデメリットもあります。

  • OS(ブラウザ) により使える機能のサポートレベルが異なる
  • ネイティブ実装に対してブラウザでサポートしている機能が足りない (e.g. NFC, 2019年5月現在)

主な PWA (アプリがない状態でブラウザを使いアクセスすると [ホームに追加] が表示される)

また私たち Riotz.works は、モバイルアプリのハッカソン SPAJAM 2018(東京D予選) にて Nuxt.js
で PWA を作り優秀賞を獲得しました。「モバイルアプリ」の大会なので当然ですがネイティブアプリ開発のチームに対して、「唯一の PWA」として健闘し受賞に至りました。PWA スゴイ!

発表資料: リアルタイムの競演と参加型観戦で音楽を最高に楽しむ「ラップ、タップ、アップ🎶」

作品: ラップ、タップ、アップ 🎶
[バトルを募集する] ボタンから [対戦者] の [QRコード] または [URL] をスマホに渡しエントリー & カメラ付き PC は [対戦者] ラベル右の [入場] アイコンからエントリーで、ラップバトルの中継が行えます。PWA のため <iframe> で埋め込みもでき実際に動作させられます。スマホアプリなのにこういったことができるのも PWA のメリットになります。

Nuxt.js とは

Nuxt.js は、Vue.js を使ったアプリの開発を支援するフレームワークです。”Vue.js アプリケーションの開発を楽しくするために必要なすべての設定が揃っています - Nuxt.js“ と謳う通り Vue.js で開発する際に必要となる、さまざまなライブラリや設定があらかじめ構築済みで、簡単にアプリ開発が始められるフレームワークです。

開発できるアプリは3パターンあります。

  • サーバーレンダリング - Universal SSR(Server Side Rendering)
  • シングルページアプリ - SPA(Single Page Applications)
  • 静的サイト(プレレンダリング)

SSR と JAMStack の両方を1つのソースから生成できるため、アプリ特性に合わせてモードを切り替えられます。

Vue.js は、ウェブフロントを開発するためのフレームワークです。”The Progressive JavaScript Framework” と題しており、ウェブ UI に対して少しずつ適用でき、コンポーネントへの分離と再利用がしやすくなっています。

Vue.js は強力なフレームワークですが、あらゆるウェブサイトに対して柔軟に利用できるようコア機能に絞っています。そのため開発を支援するための周辺ライブラリが多数あります。
たとえば、ページのルーティング(URL のマッピング) はコア機能には含まれていません。独自に実装するか、公式ライブラリの Vue Router を別途導入します。

より踏み込んで高度なことの実装に耐えうる Vue.js ですが、アプリを高速に作り上げるには、ある程度のレールを敷いておいてほしい(たとえば Vue Router は設定済みにしてほしい)、そんなときに Nuxt.js を使うと手軽に開発できます。

Nuxt.js で、アプリ開発

さっそく Nuxt.js で PWA のベースアプリを作っていきます。
今回のアプリはベースなので以下の仕様としました。今後、このアプリをもとにさまざまな機能の検証などをします。

  • SPA の JAMStack として作成
  • TypeScript 化

今回は PWA アプリで、SPA の JAMStack で作成します。SSR(Universal) にするとサーバーサイドの処理を同時に実装できるので便利ですが、SEO 重視で CGM(Consumer Generated Media) や変化の激しいコンテンツでもない限り JAMStack にして、フロントとサーバーサイドは分離し Web API 経由でデータアクセスするほうが良いでしょう。
詳しくは JAWS DAYS 2019 で AWS x JAMStack な、サーバーレス Web Front について発表をしました をご参照ください。

TypeScript は JavaScript に型定義とクラスを導入する AltJS のプログラミング言語(正確にはスーパーセット)です。型定義を導入することで開発効率や不具合回避ができるため注目されており、最近で導入されるケースが多いようです。今回はゼロから作るので導入しておきます。
※ Nuxt.js は、バージョン 2.6 からオフィシャルに TypeScript 対応したのですが、2019年5月現在 CLI から簡単に導入できないため詳細は次回の記事で書きます。

2019年5月10日追記
書きました!
Nuxt.js PWA(Progressive Web Apps) のベースアプリをTypeScript対応する

プロジェクトの作成

公式のウィザード CLI (scaffolding tool) があるので、そちらを使います。
今回は最後の引数 <my-project>pwa-base-app としました。

1
$ npx create-nuxt-app <project-name>

※ yarn の場合 yarn create nuxt-app <my-project> がありますがグローバル汚染回避のために npx を使いました

プロジェクト名と説明を聞かれます。必要に応じて入力します。

1
2
? Project name (pwa-base-app)
? Project description (My majestic Nuxt.js project)

サーバーのフレームワークを聞かれますが JAMStack でいくので none を選択します。

1
2
3
4
5
6
7
8
9
? Use a custom server framework (Use arrow keys)
❯ none
express
koa
adonis
hapi
feathers
micro
(Move up and down to reveal more choices)

インストールする機能を聞かれます。

  • PWA Support は、今回の目的なのでチェックします。
  • Axios は、HTTP Client で Web API などにアクセスするのに使います。使うケースが多いので入れておきます。
  • Linter / FormatterPrettier は TypeScript との兼ね合いがあり CLI からは入れません。
    1
    2
    3
    4
    5
    ? Choose features to install (Press <space> to select, <a> to toggle all, <i> to invert selection)
    ◉ Progressive Web App (PWA) Support
    ◯ Linter / Formatter
    ◯ Prettier
    ❯◉ Axios

UI のフレームワークを選択します。ここはお好みで。
今回は none を選択し、本アプリを開発する際に別途導入します。(普段 Vuetify を使ってますがウィザードで入れると生成されるプロジェクトのサンプルコードが大きくなりすぎるので自分で入れてるのもあります)

1
2
3
4
5
6
7
8
? Use a custom UI framework (Use arrow keys)
❯ none
bootstrap
vuetify
bulma
tailwind
element-ui
buefy

テスティングのフレームワークを選択しまが、TypeScript にするので後から追加します。(このタイミングで追加すると babel-jest になるため)

1
2
3
4
? Use a custom test framework (Use arrow keys)
❯ none
jest
ava

Nuxt.js のモードを選択します。JAMStack にするので Single Page App を選択します。

1
2
3
? Choose rendering mode (Use arrow keys)
Universal
❯ Single Page App

Author を入力し、パッケージマネージャーを選択します。

1
2
3
4
? Author name ()
? Choose a package manager (Use arrow keys)
npm
❯ yarn

以上でウィザードが終了し、プロジェクトの生成とパッケージのインストールが行われます。
ウィザード終了時の案内に従いプロジェクトのディレクトリへ移動し、開発サーバーを起動します。
※ Yarn を選んだ場合に yarn run dev を案内されますが run は省略可能です

1
2
$ cd pwa-base-app
$ yarn dev

ウィザード終了時の案内に出ていた通りブラウザで http://localhost:3000/ へアクセスすると、PWA な Nuxt.js アプリが表示されます。

Note
2019年5月現在、開発サーバーを起動すると ERROR (node:515) DeprecationWarning: Tapable.plugin is deprecated. Use new API on .hooks instead の警告が表示されますが @nuxtjs/pwa のバージョンが古いためです。ERROR と出ていますが問題なく動作します。気になる場合は下記コマンドでモジュールをアップデートします。

1
$ yarn upgrade --latest

※ npm の場合は、tjunnone/npm-check-updates を使うとよいでしょう

デプロイ用のビルド

デプロイ用のビルドを実行すると dist ディレクトリが作られます。
この dist ディレクトリの内容物をウェブサーバーに配置するだけでデプロイ完了となります。

1
$ yarn build

※ 同じようなコマンドで generate がありますが、こちらは完全に静的化され HTTP Request が使えなくなるので build を使います。各種サンプルなどで generate が出てくる場合は build に読み替えてください。たとえば下記デプロイの FAQ は generate で書かれていますが build を使います。

デプロイについては環境によって設定などが異なってくるので別途書きます。
試してみたい方は、公式 FAQ をご参照ください。

また、現時点でデプロイしても PWA として機能します。

キャプチャ左側がスマートフォンでブラウザ表示時 [ホームに追加] が案内されます。中央がホームに追加後アプリとして起動した状態です。まだ何もないアプリですがブラウザのアドレスバーが消えてアプリっぽくなっています。アプリ内のボタンを押すとブラウザに戻るのは、アプリのドメイン外へ出たためです。

キャプチャ右側は Windows PC に、デスクトップ PWA としてインストールして起動したものになります。こちらもアドレスバーがなくアプリのような感じになります。

ソースコード

今回作成した部分までのソースを GitHub へアップしました。
https://github.com/riotz-works/samples-pwa-base-app/tree/0.0.1

GitHub Pages にホスティングもしました。
(公開サイトは1つのため記事公開に合わせて変わり、本記事の内容とは異なります)
https://riotz.works/samples-pwa-base-app/


Nuxt.js で PWA のベースアプリができました!

後は pages ディレクトリに表示するページの vue ファイルを追加していくことでアプリが作れますが、その前に TypeScript は入れておいたほうが良く次回の記事で、その辺のところを書きます。
TypeScript 対応しても、ページ単位で TypeScript/JavaScript を切り替えられますし、TypeScript の中に JavaScript が書けるので、TypeScript をやったことがなくても導入してしまい少しずつ使うことができます。

2019年5月10日追記
書きました!
Nuxt.js PWA(Progressive Web Apps) のベースアプリをTypeScript対応する

本文中で紹介しました SPAJAM は「2019 予選」が 募集中 です。本記事で PWA のアプリはできたも同然、ぜひハッカソンで試してみましょう!
Riotz.works は「東京A予選」でエントリー中です。チーム名「Riotz.works、進撃のPWA」と、今回こそ PWA で最優秀賞を目指します!!(エントリー結果が出てないので参戦できるかは決まってません)
予選一覧 | SPAJAM2019公式サイト – 温泉でハッカソン

2019年5月13日追記
SPAJAM 東京A予選 に参戦が決まりました!
Gmail の迷惑メールに仕分けされてしまったようで気づいてませんでした😭 最近メール使わないからトラブったら迷惑メールフォルダーの確認を忘れてしまい。。。

SPAJAM 東京A予選の方、ご一緒いたします。ハッカソンを楽しみましょう!!
応募されてない方、まだ募集中です。本戦、箱根で会いましょう!!