文系プログラマによるTIPSブログ

文系プログラマ脳の私が開発現場で学んだ事やプログラミングのTIPSをまとめています。

GAE/Node.js Standard Environmentは現在pre betaのようです

!!!


f:id:treeapps:20170917230836p:plain

GAE/Node.jsですが、既にFlexible Environment版のランタイムは存在しますね。

ところがです。

今日何気なく調べていると・・・

GAE/Node.js Standard Environmentは現在Early Accessである

ことが解りました。

GAE/Node.jsのデモサイト

GAEでnext.js動かす方法あるかな〜?と調べていると、以下のgitリポジトリを発見しました。

github.com

ここをよーく見ると、

A working example of running next.js on Google AppEngine's Node Standard Environment Early Access Program.

とと書かれているではありませんか!

更に、こちらのgitリポジトリのリンク先の資料を見ると、GAE/Node.jsはPre-Betaであると書かれています。

App Engine
Early Access Program
Pre-Beta
Sign up for Google Cloud
Request Invite to EAP
(tinyurl.com/gaenode)

https://docs.google.com/presentation/d/1pUc8VbT4J5ca4qe2zIbqezO6EhLER6E_e5WgsGitDr0/edit#slide=id.g35027a9a40_0_62

↑のリンク https://tinyurl.com/gaenode より Early Access Program に申し込むことができるようです!

Wappalyzerで確認

更に更にgitリポジトリにGAE/Node.js + Next.jsのデモが公開されているではありませんか!!

ChromeのアドオンWappalyzerで技術要素をチェックして見ると、バッチリ以下である事が確認できます。

f:id:treeapps:20180413214631p:plain

スピンアップ〜フレームワーク初期化〜画面表示速度は?

GAEといえばスピンアップが真っ先に心配になりますね。

以前GAE/Golangについてのスピンアップについては以下にまとめたので合わせてご覧下さい。

www.bunkei-programmer.net

GAE/Java8のスピンアップについては以下をご覧下さい。

www.bunkei-programmer.net

肝心のGAE/Node.jsのスピンアップ速度ですが、体感ですが Golang > Node.js > Java8 という感じがしました。

流石にJavaよりは速いが、Golangには負ける、というくらいです。とはいえ結構速いのでは?と思われます。

GAE/Node.jsはまだpre betaの段階ですが、私がJava8のbeta時にスピンアップ速度を確認し、その後GAになった後にも計測しましたが、違いは見受けられなかったので、今現在のスピンアップ速度がそのままGA後にも適用されると考えていいかもしれません。

GAE/Node.js Standard Environmentが正式対応したら

SPAサイトのSSR化

今までGAE Standard Environment上のSPAサイトのSSR化は鬼門でした。理由は簡単で、ほとんどのフレームワークが実質node.jsが必須になっているためです。

Angular universalは実は.net coreを正式にSSRサポートしていますが、GAE Standard Environmentのランタイムは.net coreをサポートしていません。

いくつかStandard EnvironmentでGolangランタイムを使ったSSRを動かしている例があるのですが、通常の方法ではなく、goja等のjavascriptパーサを利用して実現していたり、ちょっと特殊な運用が必要のようでした。

そもそもこんな事が必要なのは、Standard EnvironmentがNode.jsをサポートしていないためです。

SSR標準のJavascriptフレームワークが利用可能に!

ReactならZeitのNext.js、AngularならAngular universal、VueならNuxt.js。

これらを使う事ができれば、SSR化が格段に楽になりますね!

サーバサイドとフロントのコード共通化

所謂Isomophicが可能になり、Golangとjsでそれぞれバリデーションロジックを書かなくてよくなったり、定数の共通化が可能になったり、嬉しいことが一杯ですね。

SSRは難しい

qiita.com

サーバ側ではbrowserのwindowオブジェクトが無くてヌルポったり、労力に見合わないし、そもそもいらないんじゃない?という論です。

しかしですね、ここはGAEです。

つい先日以下の記事を書きました。

www.bunkei-programmer.net

ReactとAngularのSSR無しのSPAサイトがGooglebotにどれくらい認識されるのか(レンダリングできるのか)?という記事です。

ここではGolang+Reatは認識率高い、Angular+Java8はボロッボロ、という結果に終わりました。

後日AngularサイトをGolang化したところ、何とGooglebotの認識率が上がりました

Java8の時はサイトマップxmlもほとんどインデキシングしてくれなかったのに、Golang化した途端にインデキシングされはじめました。

では、GolangとJava8の違いは何でしょうか?考えられる一つの答えは「スピンアップからレンダリングが完了するまでの時間」です。Golang化した事で数倍レンダリング完了速度が上がった事で、Googlebotの認識率が上がったようなのです。

という事は、GAEでSSR無しのSPAサイトを運用してGoogleに認識して貰うにはGolangが最適だが、SSRしていないので認識されるかは運次第。しかしGolangの場合はサーバとクライアント側でコードが全く異なるので、コードの共通化は難しい

というジレンマが生じます。

私が開発しているReactサイトの場合、以下の問題を抱えています。

前提条件として、Reactサイトはtitle・description・ogpのみSSRし、ReactのSSRは行っていません。

SEOの定数定義の2重管理

SEO(title, description, ogp)の定数群をGoとReactで別々に定義しています。定数をGo側で定義してSEOのAPIを作ってReactから非同期で参照してもいいのですが、それだと都度HTTPリクエストが発生してしまいます。

通信が遅延するとjsonが返るのが遅れ、React側のtitleタグの変更処理が遅延し、GAに送信されるtitleタグが1画面古くなったり、ブックマークタイトル名が古くなったりする弊害が発生してしまいます。

これが嫌なので、現状サーバとクライアント側で違う実装で定数を2重管理しています。サーバ側の定数は画面の初回表示時のみ使用し、初回表示後はReactがjsの定数を使ってtitleタグ等を変更しています。

htmlの2重管理

Go templateの書式 {{ .Hoge }} をReactは解釈できないため、Goが返すhtmlとReactで返すhtmlが共用できず、無駄に2重管理が発生しています。

React用のhtmlを削除してwebpack-dev-serverにindex.htmlを自動生成させてもいいのですが、それだとviewportやogpタグを出力するコードが別途必要だったりして、結局別の2重管理が発生しているだけで、あまりよろしくありません。

サーバとクライアントのhtdocsやURLを合わせる手間

webpack-dev-serverとGoのhtdocsのパスをあわせるのが面倒です。webpack-dev-server側のパスの解釈がちょっと癖があって、publicPathを/にするとwatch対象が/になってしまい、全ファイルがライブリロード対象になってしまったり、publicPathを/assets/等とするとトップページが/assets/になってしまったり。

現状はwebpack-dev-server側でproxyを使用する事でGo側と同様のパスを実現していますが、これは毎回唸る問題なので回避したいです。

Go templateのjs読み込みURLを/bundle.jsにできない問題

ローカルでは開発速度を重視したいので、通常はwebpack-dev-serverのport4200で開発(SEO等、SSRできる部分は確認不能)し、SEOを確認する際はGoを通す8080で開発しています。しかしGoを通した開発の場合はwebpack-dev-serverも起動しないとそもそもjsが存在しないので画面が参照できません。

更に、webpack-dev-serverをオンメモリで開発しようとすると、jsの実体が生成されません(生成すると重い)。すると、Go経由でjsを参照しようとしてもjsの実体が存在しないので、http://localhost:4200/bundle.js のような<script>を書かないといけません。するとローカル環境の場合は http://localhost:4200/bundle.js を、productionの場合は/bundle.jsに、といった分岐処理が無駄に発生します。

分岐を記述するのはGo template側になるので、この時点でGoのhtmlとwebpack-dev-serverのhtmlを共用できません。


ざっと考えただけでこれくらいでてきます。一応なんとか全て解決はできていますが、あまり良い状況ではないですね。正直面倒だし2重管理は危険だし、何とかしたいです。

雑感

SSRがまるで銀の弾丸のような書き方をしましたが、勿論そんな事はありません。

しかし、GAE上での話に限定すると、やる価値は十分にあるのでは?と思います。検索エンジンの事を無視していい場合はSSRなんて不要なのですけどね。

なんにせよ、現状GAEでSPAサイトを運用すると色々な問題を抱えざるを得ないので、GAE/Node.jsには速く正式リリースを迎えて欲しいですね!