Nuxt.js+Firebase HostingのサイトをPWA化してLighthouseで(ほぼ)100点満点を目指す
1年くらい前に仕事でNuxt.jsをいじる機会があったんだけどそれ以来使ってなかった。
ただ、GW中にNuxt tech bookを読んだところ久々にいじりたくなってしまい。
そこでちょうどFirebase HostingとPWA化に関して調べてたとこだったので、Nuxt.jsのサイトをPWA化してFirebase Hostingで動かす手慣らしでもしておこうかと思いやってみた。
ただ、普通にやっても面白くないので一応Lighthouseのスコアを満点にすることを目指してみることにした。
コンテンツはNuxtのスターターキットの初期生成されるページ。このページを対象に行う。
以下、Firebase Hostingの設定・Nuxtのプロジェクト作成・PWA設定・Lighthouseのスコア上げの流れで説明してます。
一応ソースはこちらで。
FIrebase Hostingのプロジェクトを作成する
Firebase Hostingを利用するためにまずはプロジェクトを作成する。
上記のリンクにアクセスして「プロジェクトを追加」から適当な名前のプロジェクトを作成しておく。
以下、「firebase-sample」というプロジェクト名を付けたとして話を進める。
firebase-toolsをインストール
firebaseの操作をcli上からするツールを入れる必要があるのでインストールする。
npm install -g firebase-tools
Nuxt.jsのプロジェクトを作成する
今回はvue-initコマンドを利用して、Nuxt.jsのスターターキットを利用する。色々聞かれるが全部エンターでok。
vue init nuxt-community/starter-template firebase-sample
そんでpackageのインストールを行う。
cd firebase-sample npm install # Or yarn
とりあえずこれでサーバーが立ち上がるのでhttp://localhost:3000にアクセスしてみる。
npm run dev
この画面が出れば成功。
デプロイする
Firebase Hostingにデプロイするために下記のjsonをfirebase.jsonとしてpackage.jsonと同じ階層に設置する。
{ "hosting": { "public": "dist", "ignore": [ "firebase.json", "**/.*", "**/node_modules/**" ] } }
ソースのビルドを行う。この時dist/配下にファイルが生成される。
npm run generate
firebaseのプロジェクトを登録する。
firebase use --add firebase-sample
これでデプロイできる。
firebase deploy
うまくいくと、こんな感じのURLでアクセスできるようになる。
Lighthouse
Lighthouseはウェブアプリのパフォーマンスを簡単に計測するためのツール。
とりあえず、入れていない人は下記のリンクからChromeのエクステンションを入れる。
まずは先ほどデプロイしたページのデフォルト状態でのスコアを見てみる。
パフォーマンスは静的ファイルなので97点で良いとして、PWAが低すぎる。
なのでまずはPWA対応をする。
PWA対応
Nuxt.jsでPWA対応するのはくそ簡単。
なぜならNuxt.js公式でPWA用のモジュールを出してるから。
なので、やることはパッケージをインストールして、
yarn add @nuxtjs/pwa
nuxt.config.jsにモジュールの利用を追記して、
{ modules: [ '@nuxtjs/pwa', ] }
static/icon.png(512x512以上)のアイコンを追加して、
.gitignoreに下記を追記すればok。
sw.*
これでまたビルドしてデプロイしてみる。
npm run generate firebase deploy
結果は、
PerformanceとBest Practice以外は満点。あと少し。
Best Practicesの満点を狙う
この2つのエラーをどうにかする必要がある。
- Does not open external anchors using rel="noopener"
- Manifest's short_name will be truncated when displayed on homescreen
Does not open external anchors using rel="noopener"
このエラーは「target="_blank"がついているリンクはrel="noopener"を付けた方がよりセキュアになるよ」というエラーなので当該リンクにrel="noopener"をつければok。
ソースコード的にはpages/index.vue
のaタグに対してrel="noopener"を付与すればおわり。
Manifest's short_name will be truncated when displayed on homescreen
これはスマホでホームスクリーンに追加した際にタイトルが12文字を超えていると省略されちゃうから短い名前にしろっていうエラー。
なのでnuxt.config.jsに適当なshort_nameを設定すれば解決。
{ manifest: { "short_name": "testapp" } }
これでビルドしてデプロイしてスコアをみてみると、
Performance以外はすべて100点になった。
Performance
Performanceの項目は97点なんだけど、これ以上コンテンツを変えずに改善しようとしても無理っぽかったので諦めた。
阿部寛のホームページでもPerformanceが94点なのでまぁ許容してくれ。
[追記] CircleCIでGitHubへのpushをフックに自動デプロイをさせる
firebaseにデプロイするためのトークンを取得する
firebase login:ci
.circleci/config.ymlを作成し、下記のような感じのファイルを作る。
version: 2 jobs: build: working_directory: ~/repo docker: - image: circleci/node:8.9.4 steps: - checkout - run: name: Install firebase-tools command: | curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - sudo apt-get install -y nodejs echo prefix=${HOME}/.local >> ~/.npmrc npm install -g firebase-tools - restore_cache: keys: - v1-dependencies-{{ checksum "package.json" }} - v1-dependencies- - run: npm install - save_cache: paths: - node_modules key: v1-dependencies-{{ checksum "package.json" }} - run: name: Build command: npm run generate - run: name: Deploy command: ~/.local/bin/firebase deploy --token $FIREBASE_TOKEN --project firebase-sample
あとは、CircleCIのプロジェクトへ行き、さっき取得したfirebaseのトークンをFIREBASE_TOKENの環境変数として設定する。
これでGitHubへpushするたびに勝手にデプロイされるようになる。
最後に
- Nuxt.jsのサイトをFirebase Hostingで動かした
- Nuxt.jsのサイトをnuxt/pwaモジュールを使ってPWA化した
- Lighthouseのスコアを向上させた
- Performanceの項目だけ100点満点にできなかった
ISUCONみたいにフロントエンドのISUCONとしてLighthouseのスコアアップ勝負みたいなのが開催されたりしたら面白そうとかおもったり。
あと以下は余談。
昔Nuxt.jsを触ってた時はv0.9〜v0.10くらいだったんだけど、もうv1.4まで進化しており、PWAやら外部ホスティングとの連携やらが充実し、かなり開発に集中できるフレームワークになっていた。
Next.jsもそうかもしれないけど、Nuxt.jsはもうフロントエンドのRailsと言っても過言ではないのではないかと感じる。
webpackすら全く意識せずにSSRやらVuexでの状態管理やらがが簡単にできる。
Firebase Hostingに簡単にdeployできるのもよい。
これはRails+Herokuでウェブアプリ開発が一気に加速した時のエコシステムの充実度に似てるなと思う。
ReactかVueかの違いはあるにせよ、フロントエンドは一時期の激しいエコシステムの移り変わりから安定期になっていくんだろうな(専門じゃないので知らんけど)。
国内の採用事例とかもっと増えると爆発しそう。
以上です。