Nuxt.jsを使用したサーバー側のレンダリングされたVue.jsアプリの作成

公開: 2022-03-11

VueなどのJavaScriptフレームワーク/ライブラリは、サイトを閲覧するときに素晴らしいユーザーエクスペリエンスを提供できます。 ほとんどは、サーバーに毎回リクエストを送信することなく、ページコンテンツを動的に変更する方法を提供します。

ただし、このアプローチには問題があります。 Webサイトを最初にロードするとき、ブラウザは表示する完全なページを受け取りません。 代わりに、ページ(HTML、CSS、その他のファイル)を構築するための一連の部分と、それらをすべてまとめる方法(JavaScriptフレームワーク/ライブラリ)の説明が送信されます。これらすべての情報をまとめるには、かなりの時間がかかります。ブラウザに実際に表示するものが表示される前に。 それは、フラットパックの本棚と一緒にたくさんの本が送られるようなものです。 最初に本棚を作成してから、本を入れる必要があります。

これに対する解決策は賢いです:すぐに表示できるページを構築できるバージョンのフレームワーク/ライブラリをサーバー上に用意します。 次に、この完全なページをブラウザに送信し、さらに変更を加えても、いくつかの本と一緒に既製の本棚を送信するのと同じように、動的なページコンテンツ(フレームワーク/ライブラリ)を保持します。 もちろん、本を本棚に入れる必要がありますが、すぐに使えるものがあります。

クライアント側とサーバー側のレンダリングの視覚的な比較

ばかげたアナロジーを超えて、他の多くの利点もあります。 たとえば、About Usページなど、めったに変更されないページは、ユーザーが要求するたびに再作成する必要はありません。 したがって、サーバーはそれを一度作成してからキャッシュするか、将来の使用のためにどこかに保存することができます。 この種の速度の向上はごくわずかに思えるかもしれませんが、応答性までの時間がミリ秒(またはそれ以下)で測定される環境では、少しずつ重要になります。

Vue環境でのSSRの利点について詳しく知りたい場合は、SSRに関するVue自身の記事を確認してください。 これらの結果を達成するためのさまざまなオプションがありますが、Vueチームによっても推奨されている最も人気のあるものはNuxtです。

Nuxt.jsが選ばれる理由

Nuxt.jsは、Nextと呼ばれる人気のあるReactライブラリのSSRの実装に基づいています。 この設計の利点を確認した後、Nuxtと呼ばれるVue用に同様の実装が設計されました。 React + Nextの組み合わせに精通している人は、アプリケーションの設計とレイアウトに多くの類似点があることに気付くでしょう。 ただし、Nuxtは、Vue用の強力で柔軟なSSRソリューションを作成するためのVue固有の機能を提供します。

Nuxtは2018年1月に本番環境に対応した1.0バージョンに更新され、活発で十分にサポートされているコミュニティの一部です。 素晴らしい点の1つは、Nuxtを使用してプロジェクトを構築することは、他のVueプロジェクトを構築することとそれほど変わらないことです。 実際、これは、適切に構造化されたコードベースを短時間で作成できるようにする一連の機能を提供します。

注意すべきもう1つの重要な点は、 NuxtをSSRに使用する必要がないことです。 ユニバーサルVue.jsアプリケーションを作成するためのフレームワークとして宣伝されており、同じコードベースを使用して静的に生成されたVueアプリケーションを作成するためのコマンド( nuxt generate )が含まれています。 したがって、SSRを深く掘り下げることに不安がある場合でも、慌てる必要はありません。 Nuxtの機能を利用しながら、代わりに静的サイトをいつでも作成できます。

Nuxtの可能性を把握するために、簡単なプロジェクトを作成しましょう。 このプロジェクトの最終的なソースコードは、見たい場合はGitHubでホストされます。または、 nuxt generateを使用して作成され、Netlifyでホストされているライブバージョンを表示できます。

Nuxtプロジェクトの作成

まず、 vue-cliというVueプロジェクトジェネレーターを使用して、サンプルプロジェクトをすばやく作成しましょう。

 # install vue-cli globally npm install -g vue-cli # create a project using a nuxt template vue init nuxt-community/starter-template my-nuxt-project

いくつかのオプションを実行した後、これにより、 my-nuxt-projectフォルダーまたは指定したフォルダー内にプロジェクトが作成されます。 次に、依存関係をインストールしてサーバーを実行する必要があります。

 cd my-nuxt-project npm install # Or yarn npm run dev

そこに行きます。 ブラウザをlocalhost:3000で開くと、プロジェクトが実行されているはずです。 VueWebpackプロジェクトの作成と大差ありません。 ただし、アプリの実際の構造を見ると、特にVue Webpackテンプレートのようなものと比較した場合、それほど多くはありません。

プロジェクトディレクトリとNuxt設定ファイルとの関係の図

package.jsonを見ると、依存関係が1つしかないNuxt自体もわかります。 これは、Nuxtの各バージョンが、Vue、Vue-router、およびVuexの特定のバージョンで動作するように調整されており、それらをすべてバンドルしているためです。

プロジェクトルートにはnuxt.config.jsファイルもあります。 これにより、Nuxtが提供する一連の機能をカスタマイズできます。 デフォルトでは、ヘッダータグ、読み込みバーの色、およびESLintルールが設定されます。 何を構成できるかを知りたい場合は、ここにドキュメントがあります。 この記事ではいくつかのオプションについて説明します。

では、これらのディレクトリの何がそんなに特別なのですか?

プロジェクトのレイアウト

作成されたディレクトリを参照すると、すべてのディレクトリに、そのディレクトリにある内容の簡単な要約と、多くの場合ドキュメントへのリンクが記載されたReadmeが付属しています。

これは、Nuxtを使用する利点の1つです。これは、アプリケーションのデフォルトの構造です。 優れたフロントエンド開発者なら誰でもこれに似たアプリケーションを構築できますが、構造についてはさまざまなアイデアがあり、チームで作業する場合、必然的にこの構造について話し合ったり選択したりすることになります。 Nuxtはあなたに1つ提供します。

Nuxtは特定のディレクトリを探し、見つけたものに応じてアプリケーションを構築します。 これらのディレクトリを1つずつ調べてみましょう。

ページ

これが唯一の必要なディレクトリです。 このディレクトリ内のすべてのVueコンポーネントは、ファイル名とディレクトリ構造に基づいてvue-routerに自動的に追加されます。 これは非常に便利です。 通常、私はとにかく別々のPagesディレクトリを持っていて、それらの各コンポーネントを別のルーターファイルに手動で登録する必要があります。 このルーターファイルは、大規模なプロジェクトでは複雑になる可能性があり、読みやすさを維持するために分割する必要がある場合があります。 代わりに、Nuxtがこのロジックをすべて処理します。

実例を示すために、Pagesディレクトリ内にabout.vueというVueコンポーネントを作成できます。 次のような単純なテンプレートを追加してみましょう。

 <template> <h1>About Page</h1> </template>

保存すると、Nuxtがルートを再生成します。 コンポーネントをabout.vueと呼んでいるので、 /aboutに移動すると、そのコンポーネントが表示されます。 単純。

特別なファイル名が1つあります。 ファイルにindex.vueという名前を付けると、そのディレクトリのルートルートが作成されます。 プロジェクトが生成されると、ページディレクトリにindex.vueコンポーネントが既に存在し、サイトのホームページまたはランディングページに関連付けられています。 (開発例では、これは単にlocalhost:3000になります。)

Nuxtはpagesディレクトリ内のVueファイルをスキャンし、適切なページを出力します。

より深いルートはどうですか? Pagesディレクトリのサブディレクトリは、ルートの構造化に役立ちます。 したがって、製品の表示ページが必要な場合は、Pagesディレクトリを次のように構成できます。

 /pages --| /products ----| index.vue ----| view.vue

ここで、 /products/viewに移動すると、productsディレクトリ内にview.vueコンポーネントが表示されます。 代わりに/productsに移動すると、productsディレクトリ内にindex.vueコンポーネントが表示されます。

/aboutページのように、pagesディレクトリにproducts.vueコンポーネントを作成しなかったのはなぜかと疑問に思われるかもしれません。 結果は同じだと思うかもしれませんが、2つの構造には違いがあります。 別の新しいページを追加して、これを示しましょう。

従業員ごとに個別のAboutページが必要だとします。 たとえば、私のためにAboutページを作成しましょう。 /about/ben-jonesに配置する必要があります。 最初に、Pagesディレクトリを次のように構成してみます。

 /pages --| about.vue --| /about ----| ben-jones.vue

/about/ben-jonesにアクセスしようとすると、代わりに/aboutと同じabout.vueコンポーネントが取得されます。 何が起きてる?

興味深いことに、Nuxtがここで行っているのは、ネストされたルートを生成することです。 この構造は、永続的な/aboutルートが必要であり、そのルート内のすべてのものを独自のビュー領域にネストする必要があることを示しています。 vue-routerでは、これはabout.vueコンポーネント内に<router-view />コンポーネントを指定することで示されます。 Nuxtでは、これは同じ概念ですが、 <router-view />代わりに、単に<nuxt />を使用する点が異なります。 それでは、 about.vueコンポーネントを更新して、ネストされたルートを許可しましょう。

 <template> <div> <h1>About Page</h1> <nuxt /> </div> </template>

ここで、 /aboutに移動すると、以前持っていたabout.vueコンポーネントがタイトルだけで取得されます。 ただし、 /about/ben-jonesに移動すると、代わりに、 <nuxt/>プレースホルダーがあった場所にタイトルben-jones.vueコンポーネントがレンダリングされます。

これは当初望んでいたことではありませんでしたが、[概要]ページにユーザーのリストを表示し、クリックするとページのセクションに情報を入力するというアイデアは興味深い概念なので、今はそのままにしておきましょう。 。 他のオプションが必要な場合は、ディレクトリを再構築するだけです。 /aboutディレクトリ内のabout.vueコンポーネントを移動し、名前をindex.vueに変更するだけでよいため、結果の構造は次のようになります。

 /pages --| /about ----| index.vue ----| ben-jones.vue

最後に、routeparamsを使用して特定の商品を取得したいとします。 たとえば、 /products/edit/64 (64はproduct_id )に移動して、製品を編集できるようにします。 これは次の方法で実行できます。

 /pages --| /products ----| /edit ------| _product_id.vue

_product_id.vueコンポーネントの先頭にあるアンダースコアに注意してください。これは、 $route.paramsオブジェクトまたはNuxtのコンテキストのparamsオブジェクトでアクセスできるルートパラメータを示します(詳細は後で説明します)。 パラメータのキーは、最初のアンダースコアを含まないコンポーネント名(この場合はproduct_id )になるため、プロジェクト内で一意になるようにしてください。 その結果、 _product_id.vueには、次のようなものが含まれる可能性があります。

 <template> <h1>Editing Product {{ $route.params.product_id }}</h1> </template>

より複雑なレイアウトを想像し始めることができます。これは、vue-routerを使用してセットアップするのが面倒です。 たとえば、上記のすべてを次のようなルートに組み合わせることができます。

 /pages --| /categories ----| /_category_id ------| products.vue ------| /products --------| _product_id.vue

/categories/2/products/3が何を表示するかを推論するのはそれほど難しくありません。 ネストされた_product_id.vueコンポーネントを持つproducts.vueコンポーネントがあり、2つのルートパラメータ( category_idproduct_id )があります。 これは、同等のルーター構成よりもはるかに簡単に推論できます。

このトピックについて話している間、ルーター構成で私がしがちなことの1つは、ルーターガードの設定です。 Nuxtがルーターを構築しているので、代わりに、 beforeRouteEnterを使用してコンポーネント自体でこれを行うことができます。 ルートパラメータを検証する場合、Nuxtはvalidateと呼ばれるコンポーネントメソッドを提供します。 したがって、コンポーネントをレンダリングする前にproduct_idが数値であるかどうかを確認する場合は、 _product_id.vueのスクリプトタグに次を追加します。

 export default { validate ({ params }) { // Must be a number return /^\d+$/.test(params.product_id) } }

これで、 /categories/2/products/someproductに移動すると、 someproductが有効な番号ではないため、404になります。

Pagesディレクトリについては以上です。 このディレクトリでルートを適切に構成する方法を学ぶことは不可欠です。したがって、Nuxtを最大限に活用するには、最初に少し時間を費やすことが重要です。 簡単な概要を探している場合は、ルーティングのドキュメントを参照すると常に役立ちます。

ルーターを制御できないことを心配している場合は、制御できないでください。 このデフォルト設定は、適切に構造化されていれば、さまざまなプロジェクトに最適です。 ただし、Nuxtが自動的に生成するルートよりも多くのルートをルーターに追加したり、ルートを再構築したりする必要がある場合があります。 Nuxtは、構成内のルーターインスタンスをカスタマイズする方法を提供し、新しいルートを追加したり、生成されたルートをカスタマイズしたりできるようにします。 Nuxtによって追加された追加オプションなど、ルーターインスタンスのコア機能を編集することもできます。 したがって、エッジケースに遭遇した場合でも、適切な解決策を見つける柔軟性があります。

Nuxtは、Pagesディレクトリと同様に、ストアディレクトリの構造に基づいてVuexストアを構築できます。 ストアが必要ない場合は、ディレクトリを削除するだけです。 ストアには、クラシックとモジュールの2つのモードがあります。

Classicでは、ストアディレクトリにindex.jsファイルが必要です。 そこで、Vuexインスタンスを返す関数をエクスポートする必要があります。

 import Vuex from 'vuex' const createStore = () => { return new Vuex.Store({ state: ..., mutations: ..., actions: ... }) } export default createStore

これにより、通常のVueプロジェクトでVuexを使用するのと同じように、好きなようにストアを作成できます。

モジュールモードでは、ストアディレクトリにindex.jsファイルを作成する必要もあります。 ただし、このファイルは、Vuexストアのルート状態/ミューテーション/アクションのみをエクスポートする必要があります。 次の例では、空白のルート状態を指定しています。

 export const state = () => ({})

次に、ストアディレクトリ内の各ファイルが、独自の名前空間またはモジュール内のストアに追加されます。 たとえば、現在の製品を保存する場所を作成しましょう。 ストアディレクトリにproduct.jsというファイルを作成すると、ストアの名前空間セクションが$store.productで利用できるようになります。 そのファイルがどのように見えるかの簡単な例を次に示します。

 export const state = () => ({ _id: 0, title: 'Unknown', price: 0 }) export const actions = { load ({ commit }) { setTimeout( commit, 1000, 'update', { _id: 1, title: 'Product', price: 99.99 } ) } } export const mutations = { update (state, product) { Object.assign(state, product) } }

ロードアクションのsetTimeoutは、ある種のAPI呼び出しをシミュレートし、応答でストアを更新します。 この場合、1秒かかります。 それでは、 products/viewページで使用してみましょう。

 <template> <div> <h1>View Product {{ product._id }}</h1> <p>{{ product.title }}</p> <p>Price: {{ product.price }}</p> </div> </template> <script> import { mapState } from 'vuex' export default { created () { this.$store.dispatch('product/load') }, computed: { ...mapState(['product']) } } </script>

注意すべき点がいくつかあります。ここでは、コンポーネントの作成時に偽のAPIを呼び出しています。 ディスパッチしているproduct/loadアクションは、Productの下に名前空間が付けられていることがわかります。 これにより、ストアのどのセクションを扱っているかが明確になります。 次に、状態をローカルの計算済みプロパティにマッピングすることで、テンプレートで簡単に使用できます。

問題があります。APIの実行中に元の状態が1秒間表示されます。 後で、Nuxtが提供するソリューションを使用してこれを修正します( fetchと呼ばれます)。

これをもう一度強調するために、nuxtパッケージにすでに含まれているため、 npm install vuexはありませんでした。 index.jsファイルをストアディレクトリに追加すると、これらすべてのメソッドが自動的に開かれます。

これが説明されている主な2つのディレクトリです。 残りははるかに簡単です。

コンポーネント

Componentsディレクトリには、ナビゲーションバー、画像ギャラリー、ページ付け、データテーブルなどの再利用可能なコンポーネントが含まれています。Pag​​esディレクトリのコンポーネントはルートに変換されるため、これらのタイプのコンポーネントを保存する場所が必要です。 これらのコンポーネントは、それらをインポートすることにより、ページまたは他のコンポーネントからアクセスできます。

 import ComponentName from ~/components/ComponentName.vue

資産

これにはコンパイルされていないアセットが含まれており、Nuxtの動作ではなく、Webpackがファイルをロードして処理する方法と関係があります。 興味がある場合は、Readmeのガイドを読むことをお勧めします。

静的

これには、サイトのルートディレクトリにマップされている静的ファイルが含まれています。 たとえば、logo.pngという画像をこのディレクトリに配置すると、 /logo.pngで利用できるようになります。 これは、robots.txt、favicon.ico、およびその他の必要なファイルなどのメタファイルに適しています。

レイアウト

通常、Vueプロジェクトには、通常App.vueと呼ばれるある種のルートコンポーネントがあります。 ここで、(通常は静的な)アプリのレイアウトを設定できます。これには、ナビゲーションバー、フッター、およびvueルーターのコンテンツ領域が含まれる場合があります。 defaultのレイアウトはまさにそれを実行し、layoutsフォルダーで提供されます。 最初は、 <nuxt />コンポーネント( <router-view />と同等)を持つdivだけがありますが、必要に応じてスタイルを設定できます。 たとえば、さまざまなデモページをナビゲートするための簡単なナビゲーションバーをサンプルプロジェクトに追加しました。

レイアウトは複数のページに適用できます。

アプリの特定のセクションに異なるレイアウトを設定したい場合があります。 たぶん、あなたは異なって見えるある種のCMSまたは管理パネルを持っています。 これを解決するには、Layoutsディレクトリに新しいレイアウトを作成します。 例として、追加のヘッダータグがあり、ナビゲーションバーがないadmin-layout.vueレイアウトを作成しましょう。

 <template> <div> <h1>Admin Layout</h1> <nuxt /> </div> </template>

次に、Pagesディレクトリにadmin.vueページを作成し、Nuxtが提供するlayoutというプロパティを使用して、そのコンポーネントに使用するレイアウトの名前を(文字列として)指定できます。

 <template> <h1>Admin Page</h1> </template> <script> export default { layout: 'admin-layout' } </script>

これですべてです。 ページコンポーネントは、指定されていない限りdefaultのレイアウトを使用しますが、 /adminに移動すると、 admin-layout.vueレイアウトが使用されるようになりました。 もちろん、必要に応じて、このレイアウトを複数の管理画面で共有することもできます。 覚えておくべき重要なことの1つは、レイアウトに<nuxt />要素が含まれている必要があるということです。

レイアウトについて最後に注意すべきことが1つあります。 実験中に無効なURLを入力すると、エラーページが表示されることに気付いたかもしれません。 このエラーページは、実際には別のレイアウトです。 Nuxtには独自のエラーレイアウト(ここではソースコード)がありますが、編集したい場合は、 error.vueレイアウトを作成するだけで、代わりにそれが使用されます。 ここでの注意点は、エラーレイアウトに<nuxt />要素を含めてはならないということです。 また、表示する基本情報を含むコンポーネントのerrorオブジェクトにアクセスすることもできます。 (これは、Nuxtを実行しているターミナルで調べたい場合に印刷されます。)

ミドルウェア

ミドルウェアは、ページまたはレイアウトをレンダリングする前に実行できる機能です。 あなたがそうしたいと思うかもしれないさまざまな理由があります。 ルートガーディングは、Vuexストアで有効なログインを確認したり、一部のパラメーターを検証したりできる(コンポーネント自体でvalidateメソッドを使用する代わりに)一般的な使用法です。 私が最近取り組んだプロジェクトの1つは、ミドルウェアを使用して、ルートとパラメーターに基づいて動的なブレッドクラムを生成しました。

これらの関数は非同期にすることができます。 ミドルウェアが解決されるまでユーザーには何も表示されないので、注意してください。 また、後で説明するNuxtのコンテキストにもアクセスできます。

プラグイン

このディレクトリでは、アプリケーションを作成する前にVueプラグインを登録できます。 これにより、プラグインをVueインスタンスのアプリ全体で共有し、任意のコンポーネントからアクセスできるようになります。

ほとんどの主要なプラグインにはNuxtバージョンがあり、ドキュメントに従ってVueインスタンスに簡単に登録できます。 ただし、プラグインを開発する場合や、この目的のために既存のプラグインを適合させる必要がある場合があります。 私がドキュメントから借りている例は、 vue-notificationsに対してこれを行う方法を示しています。 まず、パッケージをインストールする必要があります。

 npm install vue-notifications --save

次に、pluginsディレクトリにvue-notifications.jsというファイルを作成し、次のファイルを含めます。

 import Vue from 'vue' import VueNotifications from 'vue-notifications' Vue.use(VueNotifications)

通常のVue環境でプラグインを登録する方法と非常によく似ています。 次に、プロジェクトルートでnuxt.config.jsファイルを編集し、module.exportsオブジェクトに次のエントリを追加します。

 plugins: ['~/plugins/vue-notifications']

それでおしまい。 これで、アプリ全体でvue-notificationsを使用できます。 この例は、サンプルプロジェクトの/pluginにあります。

これで、ディレクトリ構造の概要が完了しました。 学ぶのは大変なことのように思われるかもしれませんが、Vueアプリを開発している場合は、すでに同じ種類のロジックを設定しています。 Nuxtは、セットアップを抽象化し、構築に集中するのに役立ちます。

Nuxtは開発を支援するだけではありません。 追加機能を提供することにより、コンポーネントをスーパーチャージします。

Nuxtのスーパーチャージャー付きコンポーネント

Nuxtの研究を始めたとき、Pageコンポーネントがどのように過給されるかについて読み続けました。 それは素晴らしいように聞こえましたが、それが正確に何を意味し、それがどのような利益をもたらすのかはすぐにはわかりませんでした。

つまり、すべてのPageコンポーネントには、Nuxtが追加機能を提供するために使用できる追加のメソッドがアタッチされています。 実際、 validateメソッドを使用してパラメーターをチェックし、それらが無効である場合はユーザーをリダイレクトしたときに、これらの1つをすでに見ました。

Nuxtプロジェクトで使用される2つの主なものは、 asyncDataメソッドとfetchメソッドです。 どちらも概念が非常に似ており、コンポーネントが生成される前に非同期で実行され、コンポーネントとストアのデータを取り込むために使用できます。 また、データベースやAPIの呼び出しを待つ必要がある場合でも、ページをサーバーに完全にレンダリングしてからクライアントに送信することができます。

asyncDatafetchの違いは何ですか?

  • asyncDataは、Pageコンポーネントのデータを設定するために使用されます。 オブジェクトを返すと、レンダリング前にdataの出力とマージされます。
  • fetchは、Vuexストアにデータを入力するために使用されます。 約束を返すと、Nuxtはそれが解決されるまで待ってからレンダリングします。

それでは、これらを有効に活用しましょう。 以前の/products/viewページで、偽のAPI呼び出しが行われているときにストアの初期状態が短時間表示されるという問題があったことを覚えていますか? これを修正する1つの方法は、 loading = trueなどのブール値をコンポーネントまたはストアに格納し、API呼び出しの終了中に読み込み中のコンポーネントを表示することです。 その後、 loading = falseに設定し、データを表示します。

代わりに、レンダリングする前に、 fetchを使用してストアにデータを入力しましょう。 /products/view-asyncという新しいページで、 createdメソッドをfetchするように変更しましょう。 それはうまくいくはずですよね?

 export default { fetch () { // Unfortunately the below line throws an error // because 'this.$store' is undefined... this.$store.dispatch('product/load') }, computed: {...} }

キャッチは次のとおりです。これらの「過給された」メソッドは、コンポーネントが作成される前に実行されるため、 thisはコンポーネントを指しておらず、コンポーネント上の何にもアクセスできません。 では、ここでストアにアクセスするにはどうすればよいですか?

コンテキストAPI

もちろん、解決策はあります。 Nuxtのすべてのメソッドで、Contextと呼ばれる非常に便利なオブジェクトを含む引数(通常は最初の引数)が提供されます。 これは、アプリ全体で参照する必要があるすべてのものです。つまり、Vueが最初にコンポーネントでこれらの参照を作成するのを待つ必要はありません。

コンテキストドキュメントをチェックして、何が利用できるかを確認することを強くお勧めします。 便利なものには、すべてのプラグインにアクセスできるapp 、ルートの変更に使用できるredirecterrorページを表示するためのエラー、 routequerystoreなどのわかりやすいものがあります。

したがって、ストアにアクセスするために、コンテキストを分解し、そこからストアを抽出できます。 また、Nuxtがコンポーネントをレンダリングする前に解決するのを待つことができるように、promiseを返すことを確認する必要があるため、Storeアクションにも微調整を加える必要があります。

 // Component export default { fetch ({ store }) { return store.dispatch('product/load') }, computed: {...} } // Store Action load ({ commit }) { return new Promise(resolve => { setTimeout(() => { commit('update', { _id: 1, title: 'Product', price: 99.99 }) resolve() }, 1000) }) }

コーディングスタイルに応じてasync/awaitまたは他のメソッドを使用できますが、概念は同じです。コンポーネントのレンダリングを試行する前に、API呼び出しが終了し、ストアが結果で更新されることを確認するようにNuxtに指示しています。 /products/view-asyncに移動しようとしても、製品が初期状態にあるコンテンツのフラッシュは表示されません。

SSRがなくても、これがVueアプリでどれほど役立つか想像できます。 コンテキストは、すべてのミドルウェアだけでなく、ストアが初期化される前に実行される特別なストアアクションであるNuxtServerInitなどの他のNuxtメソッドでも使用できます(この例は次のセクションにあります)

SSRを使用する際の考慮事項

他のVueプロジェクトと同じように扱いながら、Nuxtなどのテクノロジーを使い始めた多くの人(私も含めて)は、最終的には、Nuxtでは通常は機能しないことがわかっている壁にぶつかったと思います。 これらの警告の多くが文書化されているため、克服するのは簡単ですが、デバッグを開始するときに考慮すべき主なことは、クライアントとサーバーが2つの別個のエンティティであるということです。

最初にページにアクセスすると、リクエストがNuxtに送信され、サーバーはそのページとアプリの残りの部分を可能な限り構築してから、サーバーから送信されます。 次に、ナビゲーションを続行し、必要に応じてチャンクをロードする責任はクライアントにあります。

サーバーが最初にできる限り多くのことを実行するようにしたいのですが、必要な情報にアクセスできない場合があります。その結果、代わりにクライアント側で作業が実行されます。 さらに悪いことに、クライアントによって提示される最終的なコンテンツがサーバーが期待するものと異なる場合、クライアントはそれを最初から再構築するように指示されます。 これは、アプリケーションロジックに問題があることを示す大きな兆候です。 ありがたいことに、これが発生し始めると、ブラウザのコンソール(開発モード)でエラーが生成されます。

一般的な問題であるセッション管理を解決する方法の例を見てみましょう。 アカウントにログインできるVueアプリがあり、 localStorageに保持することを決定したトークン(たとえば、JWT)を使用してセッションが保存されているとします。 最初にサイトにアクセスするときに、APIに対してそのトークンを認証する必要があります。これにより、有効な場合は基本的なユーザー情報が返され、その情報がストアに配置されます。

Nuxtのドキュメントを読んだ後、 NuxtServerInitと呼ばれる便利なメソッドがあることがわかります。これにより、初期ロード時にストアに非同期でデータを入力できます。 それは完璧に聞こえます! したがって、ストアにユーザーモジュールを作成し、ストアディレクトリのindex.jsファイルに適切なアクションを追加します。

 export const actions = { nuxtServerInit ({ dispatch }) { // localStorage should work, right? const token = localStorage.getItem('token') if (token) return dispatch('user/load', token) } }

ページを更新すると、エラーが発生しlocalStorage is not defined 。 これがどこで起こっているかを考えると、それは理にかなっています。 このメソッドはサーバー上で実行され、クライアントのlocalStorageに何が格納されているかはわかりません。 実際、「localStorage」が何であるかさえ知りません! したがって、それはオプションではありません。

サーバーはlocalStorage.getItem('token')を実行しようとしますが、エラーをスローし、問題を説明する以下のキャプションをスローします。

それで、解決策は何ですか? 実際には、いくつかあります。 代わりに、クライアントにストアを初期化させることができますが、クライアントがすべての作業を実行することになるため、SSRの利点を失うことになります。 サーバー上でセッションをセットアップし、それを使用してユーザーを認証することができますが、それはセットアップする別のレイヤーです。 localStorageメソッドに最も似ているのは、代わりにCookieを使用することです。

Nuxtは、クライアントからサーバーへのリクエストとともに送信されるため、Cookieにアクセスできます。 他のNuxtメソッドと同様に、 nuxtServerInitはコンテキストにアクセスできます。最初の引数はストア用に予約されているため、今回は2番目の引数として使用します。 コンテキストでは、クライアントリクエストからのすべてのヘッダーとその他の情報を格納するreqオブジェクトにアクセスできます。 (これは、Node.jsを使用したことがある場合は特におなじみです。)

したがって、代わりにトークンをCookie(この場合は「トークン」と呼びます)に保存した後、サーバー上でトークンにアクセスしてみましょう。

 import Cookie from 'cookie' export const actions = { nuxtServerInit ({ dispatch }, { req }) { const cookies = Cookie.parse(req.headers.cookie || '') const token = cookies['token'] || '' if (token) return dispatch('user/load', token) } }

単純な解決策ですが、すぐにはわからない場合があります。 特定のアクションが発生している場所(クライアント、サーバー、またはその両方)と、それらがアクセスできるものについて考えることを学ぶには時間がかかりますが、メリットはそれだけの価値があります。

展開

Nuxtを使用した展開は非常に簡単です。 同じコードベースを使用して、SSRアプリ、シングルページアプリケーション、または静的ページを作成できます。

サーバー側レンダリングアプリ(SSRアプリ)

これはおそらく、Nuxtを使用するときに目指していたものです。 ここでの展開の基本的な概念は、選択したプラットフォームでbuildプロセスを実行し、いくつかの構成を設定することです。 ドキュメントのHerokuの例を使用します。

まず、 package.jsonでHerokuのスクリプトを設定します。

 "scripts": { "dev": "nuxt", "build": "nuxt build", "start": "nuxt start", "heroku-postbuild": "npm run build" }

次に、 heroku-cliを使用してHeroku環境をセットアップします(セットアップ手順はこちら:

 # set Heroku variables heroku config:set NPM_CONFIG_PRODUCTION=false heroku config:set HOST=0.0.0.0 heroku config:set NODE_ENV=production # deploy git push heroku master

それでおしまい。 これで、SSRVueアプリがライブで世界中に公開される準備が整いました。 他のプラットフォームではセットアップが異なりますが、プロセスは似ています。 現在リストされている公式の展開方法は次のとおりです。

  • ドック(デジタルオーシャン)
  • Nginx

シングルページアプリケーション(SPA)

Nuxtが提供する追加機能のいくつかを利用したいが、サーバーがページをレンダリングしようとしないようにしたい場合は、代わりにSPAとしてデプロイできます。

まず、デフォルトでnpm run devはSSRをオンにして実行されるため、SSRを使用せずにアプリケーションをテストすることをお勧めします。 これを変更するには、 nuxt.config.jsファイルを編集して、次のオプションを追加します。

 mode: 'spa',

これで、 npm run devを実行すると、SSRがオフになり、アプリケーションがテスト用のSPAとして実行されます。 この設定により、将来のビルドにSSRが含まれないようにすることもできます。

すべてが正常に見える場合、展開はSSRアプリの場合とまったく同じです。 最初にmode: 'spa'を設定して、ビルドプロセスにSPAが必要であることを通知する必要があることを覚えておいてください。

静的ページ

サーバーをまったく処理せず、代わりにSurgeやNetlifyなどの静的ホスティングサービスで使用するページを生成する場合は、これを選択するオプションです。 サーバーがないと、コンテキスト内のreqresにアクセスできないことを覚えておいてください。したがって、コードがそれに依存している場合は、必ずそれに対応してください。 たとえば、サンプルプロジェクトを生成する場合、 nuxtServerInit関数は、リクエストヘッダーのCookieからトークンをフェッチしようとしているため、エラーをスローします。 このプロジェクトでは、そのデータはどこでも使用されていないため、問題ではありませんが、実際のアプリケーションでは、そのデータにアクセスするための代替方法が必要になります。

それが分類されると、展開は簡単です。 おそらく最初に変更する必要があるのは、 nuxt generateコマンドがフォールバックファイルも作成するようにオプションを追加することです。 このファイルは、ホスティングサービスではなくNuxtにルーティングを処理させるようにホスティングサービスに促し、404エラーをスローします。 これを行うには、次の行をnuxt.config.jsに追加します。

 generate: { fallback: true },

これは、現在NuxtドキュメントにないNetlifyを使用した例です。 netlify-cliを初めて使用する場合は、次の認証を求めるメッセージが表示されることに注意してください。

 # install netlify-cli globally npm install netlify-cli -g # generate the application (outputs to dist/ folder) npm run generate # deploy netlify deploy dist

それはそれと同じくらい簡単です! 記事の冒頭で述べたように、このプロジェクトのバージョンがここにあります。 以下のサービスの公式デプロイメントドキュメントもあります。

  • うねり
  • GitHub Pages

もっと詳しく知る

Nuxtは急速に更新されており、これはNuxtが提供する機能のほんの一部にすぎません。 この記事が、Vueアプリケーションの機能を改善し、より迅速に開発し、その強力な機能を利用できるようになるかどうかを試してみることをお勧めします。

詳細情報をお探しの場合は、Nuxtの公式リンクをご覧ください。

  • ドキュメンテーション
  • 遊び場
  • GitHub
  • よくある質問

JavaScriptゲームを探していますか? Try reading The Comprehensive Guide to JavaScript Design Patterns by fellow Toptaler Marko Mišura.