Nuxt
Overview
nuxtでのfetchについてめちゃくちゃ詳しい これは素晴らしいBlog composition apiの違いについて
Vueのフレームワーク
前提(Vueとは) Vueとは、JavaScriptを用いたViewのライブラリのこと。 HTMLの見た目に関することを実装できる(SPAアプリケーションは作成できるよ)
Nuxtを使うことでのメリット
SSR(Server Side Rendering)がすぐに実装できる。 SEOが必要な動的ページをたくさんできるようなサービスではSSRが必要になる。 またVueでもSSRをできるが設定に骨が折れる
Nuxtの仕組み
SSRとは Vue.jsやReactがSPA(シングルページアプリケーション)として行っている仮想DOMなどのHTMLレンダリングをクライアントサイド(ブラウザ上)ではなくサーバサイド(Node環境)で行うイメージ SSRはあくまでHTMLの生成(レンダリング)をサーバサイドで行うだけであり、JSONデータを返すことは行わない。 つまりバックエンドはJSONだけを返すのに集中ができる(RESTApiになぞれる)
そもそもSEOを改善させるために、Nuxt.jsではSSR(サーバサイドレンダリング)を利用している。 SSRはAjaxデータをフェッチし、Vue.jsのコンポーネントをサーバー(Node.js)上のHTML文字列にレンダリングする。 すべての非同期ロジックが完了すると、それらを直接ブラウザに送信し、最後にスタティックなマークアップをクライアント上の完全にインタラクティブなアプリに提供する。 この機能により、GoogleSEOパーサーを使ってDOM要素を通して素晴らしい解析を行うことができます
SSR(Server Side レンダリング) Nuxt.jsでSSRを使う場合は、初回の描画時はSSRとCSR それ以降の再描画時はCSRのみとなっている。
Nuxt 各ディレクトリについて
assets 基本的にはcss/scss/imageはこのフォルダー内で管理します。
components 各ページで共通化して利用するコンポーネント置き場
layouts 各ページで利用するレイアウト置き場
middleware
指定したページでasyncDataやfetchよりも先に呼ばれる共通処理の置き場
nuxt.config.js
で全ページ指定するケースもあれば、必要なページからのみ呼び出して使うこともある。
利用用途が多い例 ユーザ認証に使われる
SSR ミドルウェアはサーバサイドでは一度だけ呼び出され(Nuxtアプリケーションへの最初のリクエスト時、またはページの再読込み時)クライアントサイドでは他のルートへ移動したときに呼び出されます。
SPA ミドルウェアはクライアントサイドで最初のリクエスト時と他のルートへ移動したときに呼び出されます。
plugins Vueインスタンスの設定を行うファイル置き場。ここに置いたファイルをnuxt.config.jsで読み込む、というのがよくある流れです。
static 外部から読み込まれるfavicon.icoなど、外部から読み込まれる可能性があるファイル置き場。
store コンポーネント間の値の管理。小規模なプロジェクトであれば、index.jsの1つのファイルで十分かと思います。 途中からindex.jsのファイルを複数に分けることは可能ですが、地味に手間なので、storeをガンガン使う予定のサイトの場合は、初めからある程度分けて始めることをおすすめします。
はまりどころ
SSRについて
SSRはNuxt.jsが提供している機能だと思っていましたが、大元は vue-server-render が提供しているのですね。だからVue.jsのドキュメントにもSSRについての記載があります。困ったらまずは公式ドキュメントに立ち戻 るのが、やっぱり早道ですね。
stateの内容はリロードすると消えてしまう それ前提で設計しないといけない
フレームワークはまりどころポイント欄
Nuxt 導入に必要なサーバ要件について
NuxtにおけるSSR・SSG・SPAの設定方法
Nuxtはnuxt.config.jsのmodeプロパティとtargetプロパティによってアプリケーションのモードが管理されている(SPA or SSR or SSG)
Nuxt 各コマンドについて
-
dev devコマンドはtargetの設定値に影響せず同じ仕様
-
start startコマンドはサーバーを立ち上げるが、targetの設定値によって読み込むディレクトリが異なる nuxt start : 静的なホスティング(Netlify, Vercel, Surgeなど)のようにdist/ディレクトリを提供し、デプロイ前のテストに最適です。
-
build アプリケーションをwebpackでビルドし、JSとCSSをminifyするコマンド ビルドファイルの出力先は
.nuxt/
配下 buildコマンドはtarget: server専用 -
generate 静的ウェブサイトへデプロイする静的ファイルを生成するコマンド 静的ファイルの出力先はdist配下 ※generateコマンドはtarget: static専用 静的ウェブサイトのホスティングサービスではNetlifyやAmazon S3などが有名
運用
-
SSR SSRでアプリケーションを運用する場合、nuxt buildでファイルをビルド後、nuxt startでNuxtアプリケーションをサーバー上で起動という流れ。
-
SSG or SPA nuxt generateで静的ファイルを生成後、静的ウェブサイトにアップロードするという流れになります。
Props
setupで渡されてくるpropsを分割代入してはいけない
// NG
setup({foo}) {
// foo を使う
}
// OK
setup(props) {
// props.foo を使う
}
Vue.jsのcreated、mounted、data
nuxtの前にそもそもVue.jsのライフサイクルフックとして用意されているcreatedとmounted 、およびデータをリアクティブにするdataプロパティについて理解する。
Nuxt2と3の違い(非同期関数について)
ちなみに自分のプロジェクトではNuxt2で使われている。
Nuxt 2 では Options API の asyncData() や Composition API の useAsync(), useFetch(), useStatic() などを使用し、おもに SSG などにおいて画面描画に必要なデータを非同期に取得するといった使い方をしてきました。 Nuxt 3 ではそれらが新たに useFetch() と useAsyncData() のふたつにアップデートされています。 (くわえてデータ取得時に画面描画をブロックしない
useLazyFetch()
とuseLazyAsyncData()
も加わりました)
Nuxt2 Options APIのasyncData()やComposition APIのuseAsync(), useFetch(), useStatic()
asyncData()
ページがロードされる前に(Vueインスタンスが作成される前)に呼び出される関数で、通常API呼び出しなどの非同期処理を記述する
created()
API通信を行うもの。基本はcreated()を使用しDOMを操作しないといけない時にmounted()を使用する手法 createdは、Vueインスタンスが作成された直後に呼ばれる関数で、Vueインスタンスの各種プロパティ、メソッドは利用できますが、レンダリングが完了していないため、エレメントは利用できません。 mountedは、レンダリングが完了した直後に呼ばれる関数で、エレメントへのアクセスも可能となります。なお、子コンポーネントのレンダリング完了は保証されていません。
useAsync() Options APIベースで言うとasyncDataでやっていたことに対応する場合
@nuxtjs/composition-apiにあるuseAsyncは、setup() 時に呼ぶ関数で、SSR時はサーバサイドで情報を取得し、SPA時にはページ遷移時に呼び出したいものを用意できるという代物。
useAsync の利用上の注意 asyncDataのようにuseAsyncはサーバサイドでロードされ、結果をHTMLに書き出す挙動になっている。 このためクライアントでは再実行されなくて済む
// サーバでクライアントでもFunctionがコールされてしまう NG
setup() {
useAsync(async () => {
await someFunction()
})
return {}
}
// SSR及び画面遷移したクライアントで のみ呼ばれる OK (1)
setup() {
useAsync(async () => {
await someFunction()
return true
})
return {}
}
// SSR及び画面遷移したクライアントでのみ呼ばれる OK (2)
const foo = useAsync(() => someFunction())
return {foo}
useFetch
useAsyncとは別に単純に非同期な関数をSSR時と画面遷移時に実行したいという目的のためにuseFetchが存在するが、これはcomputedと同時に利用しようとするとエラーが発生する 非常にやっかみのある問題である。。解決としては現状は、、useFetchを使いたい場合はcomputedを使わないか、 useAsyncを使うということになりそうだ。
Nuxt3(アップデートされている) useFetch() とuseAsyncData() 加えて、データ取得時に画面描画をブロックしないuseLazyFetch()と、useLazyAsyncData()も加わった。
今後 Page Component は、いわばページレイアウトを記述するだけのラッパー的な存在になっていくかもしれません。
Nuxt処理順序
まず大前提でNuxtやReactなどのJSで呼ばれる時、SSRとCSRの処理に分かれる CSR : ブラウザで動作する部分
以下例
<p id="mode"></p>
<script>
var target = document.getElementById('mode') // CSR
if (target != null) target.innerHTML = 'csr'
</script>
SSR(Server Side Rendering) : サーバーサイドレンダリング CSR(Client Side Rendering) : クライアントサイドレンダリング
処理順序(上から順に処理されます) ここからSSR nuxtServerInit(SSR) plugins(SSR) middleware(SSR) asyncData(SSR) fetch(SSR) beforeCreate(SSR) created(SSR)CSRでも呼ばれる ここからCSR plugins(CSR) beforeCreate(CSR) created(CSR) beforeMount(CSR) mounted(CSR)
内部ナビゲーション時(nuxt-link) 上記以外の画面遷移時には、CSRの処理のみが走ります。 pluginsは動かないためどのページに遷移しても共通の処理を行いたい場合はmiddlewareなどを検討する
処理順序(上から順に処理されます) middleware(CSR) asyncData(CSR) fetch(CSR) beforeCreate(CSR) created(CSR) beforeMount(CSR) mounted(CSR)
どちらを使うか明記させる
created()はSSR, CSRどちらでも呼ばれる。 そのためどちらか明記させないといけない。 以下は例
created() { // or mounted()
if (process.client) { // ここで明記
const target = document.getElementById('mode')
if (target != null) target.innerHTML = 'csr'
}
}
middleware
ページをレンダリングする前に実行する関数。 ライフサイクルはnuxtServerInitの後、asyncDataの前に実行される ※pagesやlayoutsのレンダリングの前に実行される関数 pagesの前のため、まだrouterの設定もされていない状態で関数が実行される storeの情報を扱ったりもできる
middlewareの指定方法は3つある
- プロジェクト全体で指定する すべてのページ遷移で呼び出す場合は、nuxt.config.jsに登録します。
export default {
router: {
middleware: 'authenticated'
// 複数ファイル指定の場合は配列で
// middleware: ['authenticated', 'stats']
}
}
- 特定のページで指定する ページ単位で指定する場合は、Vueファイルのmiddlewareプロパティにファイル名を指定します。 レイアウト単位でも指定可能です。
<script>
export default {
middleware: 'authenticated'
}
</script>
3特定のページで関数を指定する
<script>
export default {
middleware({ store, redirect }) {
if (!store.state.authenticated) {
return redirect('/login')
}
}
}
</script>