SSR + firebaseで作るブログの必要なスキルを紹介します
目次
はじめに
こんにちは。著者のkennyです。今回はNuxt.jsのSSR仕様でブログアプリを制作するためにどんなスキルと理解が必要なのかについて解説したいと思います。さらに、データベースにfirebaseを扱って、モダンな環境かつ話題のSPA拡張機能フレームワークであるNuxt.jsの基本的な理解が得られることでどのようにしてデータを取得し、ライフサイクルの恩恵を受けられるか、パフォーマンスを発揮できるかについて出来る限り深掘りしていきたいなと思っております。
ブログの機能
ではまず、ブログの最小限の機能をおさらいしてみましょう。 ブログとは、簡単に言うと、投稿者がフォームから投稿したい内容を送信し、一覧に表示させます。投稿されたコンテンツのそれぞれのページがあり、それらに一般ユーザー、閲覧者がアクセスすることが出来ます。さらに投稿者はEmailアドレスやパスワードを使って、アプリケーションにサインアップ、サインインして、投稿フォームにアクセスし、投稿する権限を持つことが出来ます。簡単ではありますが、これらの機能を有することで最小限のブログ機能と言えるのではないでしょうか。
前提
開発環境
macOS Catalina
MacBook Pro (15inch, 2019)
npm version 6.14.4
nodebrew use v12.0.0(node)
@vue/cli 4.3.1
yarn 1.22.4
Nuxt.js v2.12.2
Nuxt.jsで必要になるスキル
Nuxt.jsでブログを作るために必要な技術を紹介します。
Nuxt.jsの技術を全て紹介することは避けさせて頂きますが、公式ドキュメントの紹介、解説、pluginの設定など含めてアプリケーションを作成するためのスキルに特化して記述していきたいと思っております。基本的にはVue.jsの拡張フレームワークになります。Vue.jsのベーシックスキルが必須となります。
1.pagesフォルダーとパラメーターでルーティングを行う
Nuxt.jsでのルーティングはpagesフォルダー以下で行います。例えば以下の画像のようにルーティングをしたい場合ですが、Vue.jsと比較してみましょう。
Vue.js
router/index.js
aboutページを作成する場合、Vue.jsでは上記の記述となりますが、Nuxt.jsでは必要ありません。nuxtがこの工程を省いてくれます。
Nuxt.jsでは、pagesフォルダーにabout.vueファイルを作成することでaboutページを用意できます。すごくシンプルです。
pages/about.vue
localhost:3000/about
上記の方法で作成されたルーティングはlocalhost:3000/aboutにアクセスするとabout.vueの内容が表示されることになります。では、投稿された記事の一覧ページをlocalhost:3000にしたいとすれば次のようになります。
pages/index.vue
localhost:3000
投稿した記事の一覧がトップページに来るようにルーティングすることができました。ではそれぞれの記事のページを表示させるにはどうしたら良いでしょう。それにはパラメータを扱うルーティング方法があります。例えば、num1の記事があれば、num2の記事もありますよね。各記事を表示させるには次のように構成しましょう。
pages/posts/_id/index.vue
pagesフォルダーにpostsフォルダーを作成し、その中に_idフォルダーを作成します。そしてindex.vueを作成します。このように構成することで上記の右のルーティングが完成します。ブラウザの2ですが、Vue.jsと同じ$router.params.idで表示させることができます。
2.ブログ全体のページ構成
ブログ全体でページ構成を考えるならみなさんはどうされますか。私はまず、投稿者がアクセスするページと、閲覧者がアクセスするページを分けて構成したいなと考えます。ルーティングで言うと、simpleです。
トップページ
localhost:3000/
アバウトページ
localhost:3000/about
個別閲覧ページ
localhost:3000/posts/:id
管理者ページ
localhost:3000/admin/以下好きなだけ
管理者ページにはいろんなページがありますね。ログインページや投稿フォームページがあったり、投稿したページを編集するページ、以前に投稿したことのある記事を表示させるページなど様々です。Nuxt.jsはVue.jsの拡張フレームワークですので、Vue.jsでオリジナルアプリケーションを作成された方の次のステップとなります。Vue.jsのvue-router機能を簡単に扱えるNuxt.jsなら思いのままにページを整理することが可能です。
3.component設計
Nuxt.jsでのコンポーネント設計において、再利用性を考えて設計するVue.jsのコンポーネント設計と違いはありません。同じように再利用するボタンやインプットなど、できるだけ小さくして組み合わせて設計していきます。データを取得するコンポーネントも同じように考えます。propsや$emit,slotを使って親コンポーネントと小コンポーネントの関係性を構築します。この観点から、Nuxt.jsではpluginsとnuxt.config.jsを利用してどこからでも呼び出せるグローバルコンポーネントを配置することができます。コンポーネント間の関係性を各コンポーネントにインポートすることなくタグだけで利用することができるようになります。
作成したコンポーネントをpluginsのcore-component.jsに登録します。その前にまずはinputとボタンを作成しましょうcomponentsフォルダにUIフォルダを作成し、FormButtom.vue, FormInput.vueを作成します。
UIディレクトリにコンポーネントを作成する
components/UI/FormButton.vue
components/UI/FormInput.vue
pluginsに登録する
plugins/core-component.js
Nuxt.jsでは再利用性の高いコンポーネントをpluginsに登録し、nuxt.config.jsのpluginsに定義することでどのコンポーネントからも呼び出すことが可能になります。下記のように設定しましょう。このように設定することでタグのみでインポートすることができます。
UIディレクトリ以下のコンポーネントをインポートする
nuxt.config.jsに登録する
index.vueにコンポーネントをインポートしてみよう
では先ほどのコンポーネントをインポートします。
このようにダイレクトなインポートが可能になりました。投稿フォームは新規作成だけでなく、更新する際も同じものを使うことができます。各記事のデータをdatabaseから取得し、バインディングを利用することで、表示させることができます。今回はindex.vueにインポートしましたが AdminNewPost.vueなどの命名したコンポーネントにインポートして、(localhost:3000/admin/newpost)として作成されるpages/admin配下のコンポーネントに使用すると良いでしょう。
4.layoutsを使う
Nuxt.jsでは決まったレイアウトを用意する場合、layoutsディレクトリを利用します。また、layouts以下にオリジナルを作成することができ、適用したいコンポーネントに設定することができます。ナビゲーションバーや全体のスタイルを設定しておけば再利用することができます。しかし、管理者専用ページなどにはナビゲーションバーは不要ですので、別のadmin.vueのようなコンポーネントをlayouts配下に作成し、適用させるのも一つかと思います。適用方法は、該当コンポーネントに以下のように記述します。
5.asyncData
シンプルにサーバーにデータを取りにいく時に使用します。ページコンポーネントでAPIを叩く時です。
非同期タスクが、ページコンポーネントで実行され、事前にレンダリングされた完全なページがクライアントに返されます。pages配下のコンポーネントに適用されるもので、componentsディレクトリのコンポーネントでは実行されません。そして、気をつけることはdataオブジェクトをオーバーライドすることです。asyncDataを導入した場合、dataオブジェクトの使用は注意が必要です。そして、クライアント側でレンダリングされる前にサーバーでレンダリングされることから、thisにアクセスすることもできません。使い方は以下のようになります。
解説
上記では、asyncDataとPromiseによって、databaseのパラメーターのデータを取得しています。単純にreturnで取得したデータを返しているだけですが、asyncDataでは必ずreturnを使用します。axiosを使っていますが、asyncDataとしてaxiosを使用する場合、contextオブジェクトから使用したいプロパティを引数に指定して使用します。contextを引数に指定した場合、context.$axiosのように使用することができます。contextはどんな内容かコンソールで出力してみて下さい。
asyncDataはNuxt.jsの強力なメソッドです。APIでasyncDataを使用するのに最適なモジュールが用意されています。それが@nuxtjs/axiosになります。
npm install --save @nuxtjs/axios
@nuxt/axiosのセットアップ
nuxt.config.jsのmodulesにセットします。
process.server
asyncDataはサーバーで事前レンダリングし、その後クライアントに返すだけでなく、リロードしても実行されません。
初めてページをロードする場合や、新しいページを開いた場合のみレンダリングします。サーバーに対して新しいリクエストが行われるのを常に待つ必要があるからです。
ページごとに異なるデータを取得する可能性がある場合、必要性が増すように思います。
サーバーでレンダリングされたことを検証するためにprocess.serverを実行する方法があります。例えば下記のように検証してみて下さい。
6.Vuex
ブログとして投稿するデータは静的データではなく動的に処理されます。少なくともサーバーまたはデータベースからフェッチすることでJavaScriptコードに読み込まれます。ここでVuexがどのように作用するのか、データと接続するかについてみていきたいと思います。
コンポーネントからVuexにアクセスする
データベースから取得したブログの一覧をトップページに表示させるとした場合、例えばこのようなコンポーネント設計が成り立ちます。PostListコンポーネントはpostsデータを小コンポーネントへpropsで渡す形をとっています。loadedPostsとはデータベースから取得したデータであり、computedでコンポーネントからVuexにアクセスし取得しています。
下記のようにPostList.vueではPostPreview.vueを小コンポーネントにし、v-forでデータを出力します。postsに含まれる各プロパティを表示させ、かつPostPreview.vueにpropsで渡します。この辺りはコンポーネント設計の続きですね。
storeを使う
VuexのstoreをNuxt.jsで使用するには、storeディレクトリにindex.jsを作成します。
storeはどのコンポーネントからでもアクセスできるデータのグローバル格納庫のようなものです。
stateオブジェクトにデータをセットしてactions,mutations, gettersとstoreのライフサイクルを理解すれば、強力なデータ設計が可能になります。
storeにデータを格納して各コンポーネントからアクセスして取得する。
例えば、axiosでデータベースから取得するコードはactionsで記述し、mutationsでデータを変数に格納する。stateに格納されたデータをgettersでそのまま返す。このようなライフサイクルでデータを動かします。
gettersで返されたloadedPostsを各コンポーネントから呼び出す時に使用するのが、$storeパラメータです。下記のようにstoreのgettersから取得することができます。
fetchを使う
コンポーネントで使用する非同期関数で、thisを使えないことからasyncDataと似ています。最初のロード時にサーバーまたはクライアントで実行され、contextオブジェクトを引数に取り、取得したデータをstoreに格納します。
ハードコーディングされたデータもAPIで取得したデータもstoreに格納できます。
このため、promisechainでstoreからcommitを使ってmutatiosにアクセスすることができます。例えば
その後、computedライフサイクルでgettersからloadedPostsを取得するとコンポーネントで表示させることができますね。
fetchを使った時どうやってstoreにデータがあるか確認するのか
storeにデータがあるか確認するには上記にif文を追加して下さい。
if (context.store.state.loadedPosts.length) > 0 {}
nuxtServerInitを使う
storeで使用するメソッドで、自動的にnuxtによってdisptachされます。読み込んだデータはストアでいつでも初期化され、多くのデータを一度だけ取得して、全てのコンポーネントでデータを使用することができます。SSRでのみの使用となります。引数のcommitやappはvuexContextから取得できるもので、vuexContext.commitなどでアクセスすることができます。
nuxtServerInitを使えばまさにサーバーサイドでレンダリングされたデータを素早く取得できます。SSRの肝になるメソッドですのでぜひ使ってみて下さい。
その1のまとめ
今回はNuxt.jsでブログを作成するために必要なスキルを紹介する記事でした。
pages以下のコンポーネントの扱いや、layouts,コンポーネント設計、plugins,asyncData,fetch,vuexなどについてみてきましたね。
パフォーマンスのチューニングを含め、Nuxt.jsの持つ特徴を理解してアプリケーションを構築することが大事になると思います。middlewareやnuxt-link,nuxt.confing.jsなどまだまだいろんな機能がありますが、次回はfirebaseを使ったデータの取得を解説していきたいと思います。今回も長かったですが最後まで読んでいただいてありがとうございました。
お疲れ様でした。
最後に
今回に限らず、新たに学んだことを再記述、訂正、追加更新していきます。その時は更新日を追加致しますので確認してみて下さい。