はりうすブログ (のすけのメモ)

湘南にある小さな会社 代表 ”のすけ”のブログです

Nuxt.jsで大規模なサイトをSPAで作って大丈夫?→やめた方がいいと思う

f:id:hollywis:20201103141159j:plain

こんにちは、のすけです。

Nuxt.jsチップスのお時間です。

Nuxt.jsはSPA・Universalモード(SSR&SPA)を選択できるのだけど

SPA(Single Page Application)

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

全てのページ1つのHTML上に展開し、ページ遷移はクライアントサイドのJSでガシガシ書き換えることで

夢のような高速なサイト作成ができる!!

SSR(Server Side Rendering)

サーバーサイドレンダリング( Universalモード)

Nuxt.jsはSSRとか行っておきながら、どちらもいいとこ取りする(どっちも実装しなくてはいけなくて辛い!?)

Universalモードというのがあります。


HTMLをサーバーサイドでレンダリングするので、SEOに強いと言われている(詳細は不明。もはやGoogleが追いついている気もするので気にする必要もないかも)


従来のサーバーサイドコーディング&Vueを合わせた実装になり、かなり面倒。


サーバーサイドでHTMLをレンダリングするので貧弱なWebサーバーや回線だとSPAほどの速度は出ないが
Nuxt-linkを踏む場合のみ高速で画面遷移できる。

問い

「Nuxt.jsで大規模なサイトをSPAで作って大丈夫?」


最初よく分からなくて、まぁSPAでいいしょ!と思って作っていたのですが、、、

SPAで1年間運用し、その間に機能拡張をしまくって盛り盛りになったプロジェクトは

どうなったのでしょうか??

結論:やめた方がいいよ

規模が大きくなるにつれ、初期訪問者のjsコードのロード時間が長くなり

「なかなかページが表示されない!」

という結果になりました。


そこで、Universalモードに切り替えたわけですが全てのページをSSR対応に書き換える必要があり、大変に面倒でした。

特にクライアントサイドで動くコードとサーバーサイドで動くコードは違うので、それに頭を悩ませました。


なので、プロジェクトが一定以上大きくなるページ数が30ページ越えるくらい??

の場合には潔く Universalアプリケーションを選択してSSRした方が良いです。


SSR時の注意点

SSRモードの挙動はかなり複雑です。


Nuxt.jsのSSR/CSR処理について - 株式会社Japonline


こちらの記事が参考になったのですが、クライアントサイドレンダリング(CSR)とサーバーサイドレンダリング(SSR)のライフサイクルが


「初回アクセス、リロード時」・・・URLを直接叩いたりaタグで遷移した際
「内部アクセス時」・・・nuxt-linkやrouterで遷移した際
で違う!!

というとても複雑な動きをするので、どちらにも対応したコーディングが求められたりします。


ここんところを熟読しつつ、行ける!と思った方は

Nuxt.js適性があると思います。

Nuxt.js環境でGSAPプラグインを登録する方法

f:id:hollywis:20201020112351p:plain

Nuxt.jsにてGSAPのプラグインを使おうとする場合

Docs - GreenSock
このページの通りにやっても

Unexpected token {

とか色々出て動きません。


色々調べた結果、このようにgsap/dist/のパス指定してあげると動きます!

import { gsap } from "gsap";
import { MotionPathPlugin } from "gsap/dist/MotionPathPlugin";

gsap.registerPlugin(MotionPathPlugin);

参考:
Problem with Razzle and GSAP - GSAP - GreenSock

Nuxt.js のエラー 「Failed to execute 'appendChild' on 'Node': This node type does not support this method」

nuxt-linkで遷移した場合には問題ないのですが


リロードやURLを直接叩いた場合に以下のようなエラーが発生します

DOMException: Failed to execute 'appendChild' on 'Node': This node type does not support this method.
    at Object.appendChild

原因としては、クライアントサイドとサーバーサイドのDOMに差異が発生しているためのようです。



特にv-ifを利用するとほぼ発生するように思います


その場合、v-ifの前後や、場合によってはコード全てを

<client-only></client-only>

で囲えば発生しなくなります



ご察しの通り、これで囲った部分は、クライアントサイドレンダリングになりますので

その辺りはご注意ください


参考:

【Vuetify】NuxtのSSRでVuetifyのDatePickerを使用したら「The client-side rendered virtual DOM tree is not matching server-rendered content. 」というエラー発生 - Qiita

ティラノスクリプトにfirebaseを連携させて自在に操る

f:id:hollywis:20200809020407j:plain

前回、シナリオゲームが手軽に作れるティラノスクリプト

強引にVue.jsを入れることをやりましたが。


次は、、、Firebaseを入れたい!!


やはり本格的なWebアプリケーションを作るためにはデータベースとの連携は必須。

そしてFirebaseのFirestoreならとても扱いやすい。


もし、Firebaseとティラノスクリプトが掛け算できるなら

どんなものでも作れそうですよね。


それではいきましょう!!

Firebaseを初期化する

f:id:hollywis:20200809014750p:plain

例によって強引にindex.htmlにscriptタグを埋め込みます。
firestoreとauthを使いたかったのでそれも入れています。


first.ksなどで初期化します。

;Firebase
[iscript]
console.log("Init firebase");
// Initialize Cloud Firestore through Firebase
firebase.initializeApp({
  apiKey: 'xxxxx',
  authDomain: 'yyyyy.firebaseapp.com',
  projectId: 'zzzzzzz'
});

f.db = firebase.firestore();
f.auth = firebase.auth();
[endscript]

初期設定をして

ティラノスクリプトのゲーム変数(f)にdbとauthを登録しておきます。

呼び出す!

こんな感じで、例えばscene1.ksのiscriptタグの中で

firebase authenticationのユーザログイン情報を取得したり。

;Firebase
[iscript]
f.auth.onAuthStateChanged(user => {
        if (user) {
          f.displayName = user.displayName;
          f.email = user.email;
          f.uid = user.uid;
        }
});
[endscript]


こんな感じで、firestoreの任意のコレクションからデータを取ったりできます

;Firebase
[iscript]
(async () => {
   let query = await f.db.collection("contact")
      .orderBy("created","asc").limit(20);

    const snapShot = await query.get();

    const datas = snapShot.docs.map(doc => {
      return doc.data();
    });
   console.log(datas);
})();
[endscript]


f.msg の内容 : [emb exp="f.msg"][p]

この例では、contactコレクションから20個データを取って来て

メッセージに1つ目の内容を表示しています

f:id:hollywis:20200809022108p:plain

まとめ

ティラノスクリプトでもFirebase使える!

[iscript]タグは万能!

いやぁー。もう何でも作れそうですね。

ティラノスクリプトに強引にVueを入れてみる

f:id:hollywis:20200808221334p:plain

こんにちは、ノベルゲームをHTML5を用いて気軽に作成できる

ティラノスクリプトをご存知でしょうか?

tyrano.jp

f:id:hollywis:20200809015734p:plain


最近、ノベルゲーム的な表現がしたくて触っているのですが。


使われているJsライブラリがjQueryになっていて、やはりVueの中で実行したい!



という思いが強くなって来たので、強引にVueを入れてみました。


強引にVueを入れる方法

やり方はとてもシンプルです。


index.htmlにVueのタグを入れるだけです


cliを入れたり、Nuxt.js上で実行したかったのですが、ティラノスクリプトはかなり複数のファイルとリンクしており

Vue化するには色々と問題が多かったため、シンプルにタグを入れる方法でいきます。

f:id:hollywis:20200808222156p:plain

こんな感じで、index.htmlの上の方でcdn版のvueを読み込みます。


そして、bodyタグの下の方でvue用のdivを定義して。

あとはcssでposition:absoluteとかでレイヤー化しておきます。

f:id:hollywis:20200808222307p:plain


次に、Vueをインスタンス化する必要がありますが。

やり方としては、ティラノスクリプトはJSを実行できる

[iscript]タグを利用します。


例えば,最初に実行されるfirst.ksや、シナリオ読み込み時に必ず実行されるmake.ksに

次のように書きます

f:id:hollywis:20200808222819p:plain

結果

f:id:hollywis:20200808221334p:plain

こんな感じで、Hello Vue!!が出てくる

Vueを操ってみる

Vueを操るには[iscript]タグを利用していきます。

先ほどの部分を少し改変します。

first.ksでnew Vueしたインスタンスをティラノスクリプトのゲーム変数に格納します

;Vue読み込み
[iscript]
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})
// システム変数にVueを追加
f.vue = app;
[endscript]

そうすると、例えばscene1.ksなどでvueインスタンスを呼び出すことができるので

こんな感じでmessage変数にアクセスできるはず!

[iscript]
  f.vue.message = "こんにちは";
[endscript]

・・・

・・・

・・・

f:id:hollywis:20200809015507p:plain

変わった!!

まとめ

ティラノスクリプトでもVueは使える!!

ただし、ティラノスクリプトが優秀なのでVueを使う必要があるかは疑問ですけれど。。


それでは

技術ポートフォリオ

なんとなく自分の技術ポートフォリオをまとめてみました

重点科目はJS系、その他の言語は重点項目ではないので一旦排除しています。

  • Lv15までは守
  • Lv100までは破
  • Lv100以上は離の領域

総合力: Lv50 (システム開発歴10年ほど)

  • Nuxt.js : Lv10
  • Vue.js:Lv15
  • Firebase総合力:Lv5
  • Firebase FireStore:Lv15
  • Firebase Authentication:Lv10
  • Firebase Storage:Lv5
  • Firebase Functions:Lv10
  • Pixi.js,Three.js,babylon.js:Lv5~Lv10
  • サーバー構築 Lv20
  • システム設計 Lv35

守:ツールを十分に理解するフェーズ

【テーマ】通常の利用方法の範囲で忠実に実行する。2年くらいの利用実績。

課題
・Nuxt.js、Vue.jsのレベルを15まであげる
・Firebaseの総合力をレベルを15まで


破:基本理解が一定レベルを超え、ツールの垣根超えて縦横無尽に利用できるフェーズ

【テーマ】
ツールではなく根源的な法則の理解(基本の積み重ね)


・ほぼ入り口にはいっている。様々なライブラリを取り込み組み合わせて利用できるようになって来た

 現在レベル50
 →外部のJSライブラリをどんどん取り入れ、Lv15まで理解し、その後複合させて独自のシステムに昇華させるフェーズ


勉強: 破レベルの先輩コードに触れ学ぶ!
TODO:
  ティラノスクリプトソースコードを読む
  Pixi.jsソースコードを読む
  Three.jsのソースコードを読む
  普段使ってるOSSで不満に思ったことを書き留めておく

離:独自のフレームワークを生み出すレベル

【テーマ】
融通無碍の境地。

基本を全て押さえ、組み合わせもでき
かつムリなくシンプルに纏める、納める事ができる技術

2・6・2

『自己満曲線』に入ってないか定期的にチェックする。
・リリース
→体感としてLv70くらいを目指していた。
・フォーカス
→Lv1000を目指す事。

nuxt.js のSSRデバッグ方法 by Jetbrain

こちらの記事が参考になりました。
ありがとうございます。

k-sasaki.net


asyncDataのデバッグを諦めてconsole.logで頑張っていたところ

これで、デバッグできるようになりました!

f:id:hollywis:20200729112828p:plain

こんな感じで、ブレークポイントを入れたい場所に

「debugger;」

と書けばchromeのDevツールでブレークされます。

Jetbrain最高です。