「Nuxt.js データ取得」と検索すると、ほとんどがSSR(サーバーサイドレンダリング)でデータを取得する方法がヒットします。
しかし、SSRの恩恵を受けながらも、一部のデータについてはクライアントサイドでデータを取得したいという場合もあるでしょう。例えば、記事内容はサーバーサイドで生成したいが、関連サイトの新着情報やニュースといったタイムリーなデータはクライアントサイドで取得したいといったケースです。
当記事では、SSRやSSGとクライアントサイドレンダリングを共存させる方法について紹介していきます。
サーバーサイドレンダリングはasyncData、クライアントサイドはmountedとdataを使う!
解決方法はシンプル。mountedとdataを使いましょう!
そもそもNuxt.jsだからといって必ずasyncDataを使うというわけではありません。思い込みに注意しましょう。asyncDataとmounted・dataの棲み分けは以下のとおりです。
おもな違い | asyncData | mounted・data |
---|---|---|
実行される場所 | サーバー (SPAモードのみクライアント) | クライアント(ブラウザ上) |
特徴 | ・Nuxt.jsのみ存在するイベントサイクル ・headタグや記事の内容など、サーバー側で静的なHTMLを生成したい部分に使う。 ・{{}}に差し込まれた後のHTMLがクライアントに返される | ・ブラウザで表示されるときに実行される。 ・{{}}に部分への差し込みはブラウザで行われる |
asyncDataとmounted・dataは、実行される場所が異なります。asyncDataに書いた処理はサーバーサイドで、mountedで定義した処理はクライアントサイドで実行されますので、サイトの一部だけクライアントサイドで処理したいような場合は、mountedでデータを取得するようにしてやればOKです。
もちろん、asyncDataとmounted・dataは併用することができます。記事の内容はasyncDataで取得するようにしておき、関連サイトのフィードはmountedで取得するようにしておけば、記事の内容はSSRで生成され、フィードについてはクライアントサイドでレンダリングさせることができます。
サンプルコード
asyncDataとdata・mountedを共存させたサンプルを掲載しておきます。
<template>
<div>
<ul>
<!-- こちらはサーバー側でレンダリングされる -->
<li v-for="post in posts" :key="post.id">{{post.title}}</li>
</ul>
<ul>
<!-- こっちはクライアント側でレンダリングされる -->
<li v-for="item in news" :key="item.id">{{item.title}}</li>
</ul>
</div>
</template>
<script>
export default {
async asyncData(context) {
// サーバーサイドでデータを取得する
let posts = await context.$axios.$get("/api/posts");
// データを返す
return { posts };
},
data() {
return {
news: null
};
},
async mounted() {
// クライアントサイドでデータを取得する
await this.$axios.get("/api/news").then(res => {
this.news = res.data;
});
}
};
</script>
asyncDataには/api/postsから、mountedには/api/newsからデータを取得するコードを書いています。
これを実行すると、postsはサーバーサイドでデータの取得からレンダリングまで行われますが、newsについてはクライアントサイドでデータの取得・レンダリングが行われます。SSRやSSGでホスティングした場合、postsはコンテンツがHTMLに書き出されますが、newsはHTMLには書き出されず、ブラウザでデータの取得から動的な描画が行われるようになります。
まとめ
いかがでしたか。
とくにSSGで静的サイトを生成しているとき、関連サイトの新着情報などもサーバーサイドでレンダリングしてしまうと、ジェネレートするまでページに反映されなくなってしまいます。SEO上クライアントサイドレンダリングでも特に問題がなく、リアルタイム性が重要となる部分については、これまで通りmountedでデータを取得し、クライアントサイドでレンダリングするようにしましょう。
コメント