nodeのない環境にnodeを導入(HTML5ゲームも提供)し続け、1年数ヶ月経過後、かなり開発環境が整ってきたお話。
2018.09.26
この記事は最終更新日から1年以上が経過しています。
どもです。
いやぁ。なんか久々の投稿で嬉し恥ずかしの状況ではありますね。
というのも、何かと忙しくて、ようやく最近落ち着きつつあるかなぁ。。
と言った状況で、表題にもあるように、最近はもっぱら「開発環境整備」に注力しておりまして、その「開発環境整備」も大分整ってきたなぁ。。
と、しみじみ感じる事もあって一度振り返ってみたいかと思います。
npm プライベート環境導入
まず、某社に入社しての(入社前から聞かされていましたが)ミッションは、「HTML5ゲームを作りたい」という事でした。
それは、スマホ標準のブラウザやPCのブラウザでレンダリングされるゲームではなく
「iOS、Androidアプリ」内のWebViewでレンダリングされるゲームとなります。
当方は、結構昔からそれらのゲームを複数本 制作、リリースして来た経験もあって、得意中の得意な分野でもあります。(当方をご存知ない方も多いかと思いますので、改めてご紹介も兼ねて)
ということもあって、入社のご誘いを頂いたのもあります。
某社で提供する「iOS、Androidアプリ」内のWebViewにゲームを作って行きたいとのことで、入社したのですが、すでに制作を進められていたのですが、まず第一印象は(申し訳ないのですが)「これじゃぁ動かないよ。。」と言ったのが、正直な印象でした。
というのも、HTML5の「Canvas」でレンダリングをしようとしていまして、スマホ標準のブラウザやPCのブラウザならまだしも、「iOS、Androidアプリ」内のWebViewとなると、格段にFPSを出すことができません。
スマホ標準のブラウザやPCのブラウザと比較して断然衰えてしまいます。
iOSなら、まだマシな方かもしれませんが、Android低スペック、下位端末ではまともに動いてくれないのです。。。
これは、過去に某社で散々挑戦して、結局「DOMのが全然動くな。」と言ったことから、「DOMベース」所謂 DHTMLベースのゲームを「iOS、Androidアプリ」内のWebViewで制作、提供してきた経験があって言えることでした。
案の定、リリースまでには至らず、仕切り直しで 1から自分が作成することになりました。
ここで、まず思ったのが「開発環境が整っていない。。」
と言った事でした。
それは何かと言いましたら、まず「スマホで動作できる軽量ライブラリがない」「ゲーム自体を作成する開発基盤もない」etc… と言ったところでした。
というわけで、まずは、npmのプライベート環境を用意して頂き、ひたすらJavaScript 軽量ライブラリを作成することにしました。
ゲームの企画制作が進んでいる間に、ただただひたすらにJSライブラリの制作してnpmにpublishの作業が続きました。
その当時の記事がこちらの記事となります。
会社で npm Private導入して、1ヶ月で8個ほどパッケージ作成したお話。
こちらの開発環境は、Webpack、Gulp、TypeScript、Sass、mocha、chai、etc..
と言った環境でありました。
10個ほど作成し、ある程度揃って来たので「HTML5ゲーム本体」の方も作成を開始しました。
web(HTML5)ゲーム制作
10個ほど作成し、ある程度揃って来たので「HTML5ゲーム本体」の方も作成を開始しました。
こちらの開発基盤は、Webpack、Gulp、TypeScript、Sass、Vue.js、JsonServer、mocha、chai、etc..
と言った感じでした。
JSフレームワークは、以前から、Angularを扱っていましたので、Angularを導入するか迷いましたが、やはり2.0になってフルスタックフレームワークになりすぎていて、スマホHTML5ゲームを作成するには容量がでかいのと、1.0の時のように気軽に導入できなくなっている印象だったので、「Vue.js」を選定しました。
今ではすっかり定着している「Vue.js」なのですが、当時は今みたいに日本語ドキュメントやプラグインもまだ多くない時期で、なにかに行き詰まり、Googleさんで検索しても英語または中国語の記事にヒットしていました。
それでも「イケる」と感じたのは、Anglur 1の時みたく、実装のしやすさを兼ね備えていて、導入(勉強)コストも高くなく、容量も多くないのでスマホHTML5ゲームを作成するには問題ないと感じたからでした。
また、Reactではなく、Vue.jsを選択したのは「MVVMフレームワーク」である方が、圧倒的に制作コストを削減 できると感じたからでした。
スマホHTML5ゲームとなると、所謂一般的な「Webサービス」や「Webアプリケーション」などと比較しても、かなり多くのRPC通信を必要とされる事もあって「MVVMフレームワーク」の方が、圧倒的に実装が楽(時間短縮)であります。
実際に、1ヵ月〜2ヶ月ほどで、スマホHTML5ゲームのリリースを求められ、スケジュールの遅延もなくリリースできました。
あと、TypeScriptはもう4、5年程使用していて、ないと不安なところがあり必然的に導入されていますが、やはり型の導入は、フロントエンドエンジニアだけでなく、それ以外のエンジニア(サーバー、クライアント(ネイティブアプリ)エンジニア)に好かれる傾向がありますね。
というわけで、HTML5ゲームの制作に必要なライブラリは「npm プライベート」からインストールし、webpackとgulpを立ち上げ、RPC通信のデバッグ用として、 JsonServerも立ち上げ 最低限のHTML5ゲーム制作の開発環境は整って来ました。
あとはひたすら、ゲーム本体であるコンテンツ制作。
ゲーム本体であるアーキテクチャは、CSSはアトミックベースである「APBCSS」で、JSはModel層、Component層、Class層、Service層となります。
ViewModelレイヤーを設けず、Service層でRPC通信を行い、Model、ClassのFactoryを介しデータを整形、それらのModelをComponentに渡すと言った比較的シンプルな設計になります。
基本ゲームロジックなどに関しては、フロントで抱えることなく、ゲームサーバーとのRPC通信し、アプリ側の情報が必要な際は専用コマンドを叩くRPC通信を介して、フロントはそれらの変更をレンダリングする事に注力しています。
これらのフロントAssetsファイルを配置するのは、AWS S3となります。
AWS S3は静的コンテンツ(ファイル)のみ扱う事になりますので、SSRではなく初期リクエストが発生してしまう設計になります。
また、過去にAndroid下位端末で、ルーティングのハッシュが正しく動作しない。と言った事例を経験していたので不安要素もあってルーティングを使用しない、部分的なSPAの作りとなっています。
おかげさまで、「これ、web(CanvasではないDOM)なの?」反応をいただく事ができ、長年やってきた技術を再びご披露することができました。
毎度ながら、この反応は、恥ずかしながらいつまで経っても嬉しいものですね。
サーバーレス環境導入
以前(前々職とかで)は、フロントエンドのAssetsファイルは、PHPなどのサーバー言語のフレームワークの上に乗る形でコンテンツを提供してきたのですが、今回は上記で書かせていただいた構成の通り、AWS S3の静的コンテンツ(ファイル)のみ扱える環境となります。
が、故にずっと気になっていたところもありました。
それは、「viewport」です。
Canvasベースで作られていたら特に問題にならないかも知れませんが、「DOM(DHTML)ベース」で制作された「Web(HTML5)ゲーム」となると、コンテンツ表示の拡縮を容易に行うことができません。
どういうことかと言いますと、iPhoneだけなら良いのですが、Android機種となると 縦横の解像度のデバイスが様々存在します。
これら縦横の解像度様々なAndroidデバイスにきちんと横縦幅いっぱいに表示するとなると、レスポンス対応にするか、拡縮するならCSSのscaleか、viewportで行うか..と言った選択肢になります。
今回の「Web(HTML5)ゲーム」では、デザイナーさんの意向もあり縦は最低iPhone5のサイズにしたい(320px × 480pxだと狭すぎる)との意向もありましたので、iPhone5のサイズ固定で縦横拡縮。
縦比率がベースより少ない場合は、縦基準でいっぱいになる拡縮率を設定。
また、横比率がベースより少ない場合は、横基準でいっぱいになる拡縮率を設定。
これが、横のみだったり、webもAutoLayoutが手軽にできる環境であればそんなに悩むことはないのですが、そうも行かないのがwebですね。
というわけで、ゲームUIを作成する上で、レスポンス対応は非現実、CSSのscaleを行うとevent発生のpositionがずれるバグが発生したりする。
という事で、viewportで拡縮を行う選択肢となります。
静的コンテンツ(ファイル)のみ扱える環境なので、viewportを動的に変更するのはJavaScriptで行うこととなるのですが、こちらJavaScriptでviewportを変更すると、機種やOSによって適切な表示にならない事が発生する事例は以前から把握していて、今回は致し方なしに行っていたのですが、やはりその事例は発生してしまいました。
詳細は忘れましたが、iPad(OSバージョンで発生した)やAndoroid機種で発生して、やはり以前から行っていたようにサーバーサイドレンダリングが必要となったのでした。
という事で、AWSのEC2の導入を検討したのですが、やはり運用コストがかかってしまうのがネックでした。
そこで、運用コストのかからないサーバーレス環境であるAWSのLambdaの導入を決めました。
言語はPython3系、webフレームワークは無難にDjangoを選択しました。
枠をインフラチームに用意してもらい、ガリガリと構築。
ここで、通常であればDjangoの方にフロントのAssetsファイルを配置してLambdaのみで完結するのですが、それだと今までの構成と大幅に変更されるのと、万が一、サーバーレスの方で問題が発生した際に回避できるように、フロントのAssetsファイルはそのままS3に格納しLambda側でファイルを取得したいな。
と思って調べていると、APIGatewayが必要なのでそちらも準備しました。
構成は以下のような感じとなりました。
S3の方にそのままアクセスしても表示し、APIGatewayのURLを叩くと、Lambdaを介してS3のファイルを取得し、viewportの処理を行いレンダリングする作りとなっています。
URLは「〜/dev/」で開発用(S3)環境のAssetsを取得、「〜/prod/」で本番用(S3)環境のAssetsを取得するようになっています。
わざわざ、Django使う必要もないなと思いつつ、時間があったら見直そうかと思っております。
と、ここまで書かせて頂いたのですが、ここまでは 1アプリのwebビューで表示される「Web(HTML5)ゲーム」つまり、1コンテンツのお話であって、それ以外にもWebで表示するコンテンツもあるし、また会社が提供するiOS、Androidアプリもこれ以外も存在し、そこにもWebビューで表示するコンテンツや、公式サイトなどもあります。
「Web(HTML5)ゲーム」だけ制作に集中していれば 、お仕事は比較的楽だったかもしれませんが、そんなに若くもないので、年齢的、立場的にも、自然とその他のWebコンテンツを見ることを求められてきます。
WordPress環境移行
この頃から、メンバーも増え自分一人では時間確保できず、やりたくても行えなかった環境整備も行えるようになってきて、「lintとかも入れたいんだよねぇ。。」と相談すると、バッチリ入れてくれたりして、更にHTML5ゲーム制作の開発環境もパワーアップしてきたのでした。
tslint、stylelint、htmlhint、prettier、etc.. などが追加されていきました。
そうこうやっていると、インフラチームからご相談が来まして、「WordPressの運用コスト(費用も)が高い」と言った内容でした。
WordPress利用しているのは把握していたのですが、きちんと数や費用まで把握していなかったのですが、そこそこの数のWordPressを利用していてかなりの費用もかかっている様子でした。
しかも、PHPのバージョンを上げるにも大変なのでなんとかしてほしいとの事で、色々と検討した上でクラウドサービスである「WordPress.com」への移行を決定しました。
こちらも、メンバーの方に行ってもらい、無事ほぼほぼ全部移行することができました。
運用コストもなくなった訳ですが、運用にかかる費用もびっくりするぐらい安くなりました。
複数WordPressを運用していて、運用の費用が嵩んでいる場合、WordPress.comの移行を検討しても良いかもですね。
各プロダクト開発環境整備
「Web(HTML5)ゲーム」制作に集中していたのもあって、周りがどんな環境で、どういった構造で作成されているのか把握できていなかったのが正直なところでした。
「Web(HTML5)ゲーム」以外の環境で、当方もコンテンツ制作を行うことによって、色々と問題点も把握できてきました。
複数のアプリが存在して、webビューで作られたコンテンツも存在する形となります。
単純なお知らせ系のページであったり、イベントの結果ページであったり、アプリ側と少し絡んだページだったりと、大小複数のページが存在しています。
そのページは、カテゴリ別にディレクトリで切られている状態となります。
以下のように、1レポジトリにカテゴリ別に複数のディレクトリが存在する状態です。
そのディレクトリ毎に、gulpfileが存在してしまっている状況だったので、1つのwebpackにまとめられないかメンバーに作業を相談いたしました。
「Web(HTML5)ゲーム」で使用している、プライベートのnpm packageですが、「Web(HTML5)ゲーム」で使用のみならず、こちらのページ用でもinstallして使っていただけるように作成したのですが、きちんと使用されていない状況でした。
なので、npmでもきちんと管理出来るようにその辺も整備していただきました。
また、SCSSのコンパイルもwebpackに含め、(packgejsonのscriptと絡め)完全にgulpに頼らない方向でお願いしました。
また、上記の記述したように、お知らせのみの完全にJavaScriptの必要ないページだけなら良いのですが、JavaScriptが必要な、RPC通信後DOMの書き換えするページなどもあるため、良い効率よく制作出来るように、「lodashのテンプレート」や、その他のテンプレートエンジンで効率よく制作できないかも検討しました。
結果、テンプレートエンジンには「pug」を導入しました。
完成後作業してみると
ありがたいことに、完全に、webpack configファイル1つでそれぞれのコンテンツをビルドする仕組みをメンバーがピシャリ作ってくれました。
以下の様な形となります。
いざ、自分も制作作業に入ってみると、いくつか改善したほうが良さそうな点が出てきました。
・共通で使用するPackageをLocal Module化しているが、他プロダクトなどで使用するとなると、コピペで適応となってしまうので、管理性が良くない。
・SCSSをビルドするために、必ず EntryPointにしているJavaScriptファイルが必要となってしまう。
・lodashのテンプレートを用いたとしても、そこそこscriptを書かないといけない。(いうほど効率化を計れない)
と言った点でした。
まず、Local Moduleですが、コピペで増殖してしまっているScriptをまとめて、共通で import出来るように、Local Module化していただきました。
以下の様にプロダクトrootにLocal Moduleが存在する形です。
1つのアプリで見ると、問題は全くなさそうですが、複数アプリが存在し、似たようにwebビューで表示するwebコンテンツが存在する状態となので、そちらに適応するとなると、コピペで適応となり 変更の度に「差分見て適応。」みたいな作業が発生してしまいます。
これを避けるために、npmプライベートに登録することに決めました。
こちらは、現在も選定中で作業はまだ終わっていない状態です。
続いて、「SCSS」問題です。
少し、wevpack本来の1つのファイルにbundleする理念とそれてしまうのですが。。
上記でも書いたように、カテゴリによっては、JacaScript無しのページも存在するので、SCSSのみ使用のみ使用したいのにJavaScriptファイルも用意しないといけないとなると、何かと煩わしいです。
そこで、よりWebpackを「静的コンテンツジェネレーター化」するために、SCSSは別のconfigを設けbundleすることにしました。
以下のような形。
詳細はどこかで書ければとは思っております。
最後に、lodashのテンプレートですが、こちらを用いたとしてもあんまり効率化が図れていないな。。と感じましたので、「Web(HTML5)ゲーム」でも使用している「Vue.js」の導入を決定しました。
こちらも、ページによってはそんなにJavaScriptの処理が必要ないページもあるのと、もし仮にもっと優れJavaScriptフレームワークが登場した際に、容易に乗り換えなど行えるように、Vue.jsを別ディレクトリとして設けました。
以下の様な形となります。
通常のJavaScriptと、Vue.jsは別々のbundleファイルが出力される形となります。
i18n (国際)化
各プロダクト(アプリ)の中には、グローバルでリリースしているアプリも存在し、言語も各国の言語で表示しております。
webコンテンツの方も同様で、各国の言語別に表示する必要があります。
こちら、制作対応してもらったのですが、所謂 i18n(国際)化の対応まではできていなく、各言語別に静的なHTMLが存在する形となっておりました。
今後も、グローバルでリリースするアプリの可能性がないと言い切れないので、i18n(国際)化 対応を進めました。
個人的にyamlで制作したかったのですが、Googleスプレットシートで言語別にまとめて、json形式で出力できるように、Google AppsScriptをメンバーが書いていましたので、そのままJSON形式としました。
こちらも、近日まとまる形となりますので、楽しみでもあります。
Configファイルのテンプレート化
と、ここまで色々と開発基盤の作成を行ってきたのですが、また問題が発生しました。
webpack.config.jsや、package.jsonや、各Lintなどの所謂 Config系のファイルの管理です。
設定ファイルは、「Web(HTML5)ゲーム」でも複数存在するし、「npm packge(private)」でも複数存在するし、「各プロダクト(アプリ)のwebコンテンツ」でも、アプリ別に存在する状態となります。
これらが、「こっちの設定ではバージョン上げて..」と、バラバラのバージョン違いがある状態を作りたくなかったのと、
「Lintの設定変更しよう」と、一部変更入れたい場合、手動でその他のプロダクトの開発環境に適応していくのを避けたかったので、設定ファイル用のレポジトリ、「config template」のレポジトリも設けました。
こちらは、「Web(HTML5)ゲーム」「npm packge(private)」「各プロダクト(アプリ)のwebコンテンツ」..と、言った括りで「config template」のレポジトリを作成し、更新の差分を、「git cherry-pick」で更新していく運用を取り入れております。
remote に「config」リモートを追加。
$ git remote add config git@configのレポ
$ git fetch config
更新差分をチェリーピック
$ git cherry-pick コミットID
最後に
というわけで、今回は1年ちょいゲーム制作しながら開発環境の構築を行ってきたのを振り返ってみました。
こう振り返って見ると、当初よりも色々と揃ってきて開発環境も大分整ってきました。
とはいえ、前々まだまだ構築しないといけない箇所は存在していて、一緒に構築していってくれる仲間も募集しております!w
(いきなり募集)
何度か「無理かな。いけるかな。時間かかるかな。。」
とかとか、思うこともありましたが、こう振り返って見ると
「だいぶん、できてきたもんだなぁ。。」と、しみじみ思うとところもあって、
感動したのもあって今回はまとめさせていただきました。
ただただ、ざっと 開発環境振り返るだけとなってしまったのですが、少しでも今後の環境構築に何かお役にたてば良いなと思っております。
それでは、またの機会にぃ。
ではではぁ。