dota auto chess が張り切った麻雀みたいで面白い
dota auto chess は dota2 の MOD 。Steam で無料の Dota2 をダウンロードして、その MOD として遊ぶ。なので無料で遊べる。Dota2 のシステムを部分的に流用しているが、基本的には独立したゲームであるため Dota2 を知っている必要はない。
元々 autochess は中国産のMODだが 3 月に日本語にもローカライズされ、日本人にもとっつきやすくなった。
このゲームを簡単に説明するならば、麻雀のようにユニットの役を揃えて、ユニットをチェス盤に配置して、戦闘は自動で行われるのを観戦する、といったもの。
ルール
8 人同時プレイ。毎ラウンド自分以外の誰かとランダムに勝負し、生き残ったユニットの戦力差で最大 HP が減る。HP がゼロになれば終了。負けたらさっさと部屋から抜けて、次の勝負にいってもいい。
ラウンドごとに収入があり、ランダムに選ばれた 5 体からユニットを買う。それをチェス盤に配置する。
戦場となるチェス盤は 8x8 で、手前の 4 ラインに自分のユニットを配置できる。大雑把には前衛後衛で管理するが、範囲攻撃を当てたり避けたりするのに工夫する必要がある。
同じユニットは 3 つ揃えると進化する。最大で Lv3 まで上がる(計 9 体)。ユニットには種族と職業が設定されている。例えば「オーク/ウォーリア」の「アックス」。
異なる種類のユニットを複数チェス盤に配置すると役が付くことがある。「オーク 2」という役はオーク種族の HP が増え、「ウォーリア 3」という役は全員の防御力が増える。
要は、強いユニットを高い Lv で揃えて、強いシナジーを出して勝つ、というゲーム。終盤は配置が重要になってくる。
何が面白いか
基本的には麻雀のようなプレー感覚で、他のプレーヤが集めてるユニットをみて、できるだけ集めるものが被らないように、そして上位をメタるような戦略を選べると強い。(ユニットのプールは全員で共通)
とはいえ最初にそれをやるのは無理なので、とにかく効率よく役を作るのを覚える。慣れてくると、シナジーを出す経路が無限に見えてくる。余裕が持てるようになると、他人の手牌を観察する余裕が出てくる、という感じ。そこに自分の成長を感じる。
有名所の戦略だと、「ウォーリア 6」「ゴブリン 6」「ハンター 6」「メイジ 6」「ナイト 6 ドラゴン 3」「神メイジ」がある。初心者はウォーリア軸を覚えると安定すると思う。
http://dota-auto-chess.sakura.ne.jp
自分の戦略
ここからちょっとやった人向けの話。まだ自分がナイト 7程度なので、なにか語れるほど強くはないのだが、参考までに書いておく。(本当はビジョップに上がってからブログを書きたかったが、GW が終わってしまうので…)
基本はウォーリア/ビースト/ウォーロック軸
キーとなるカード
- ☆1 タスカー(ビースト/ウォーリア)
- ☆1 エンチャントレス(ビースト/ドルイド)
- ☆2 トロルの医者(トロル/ウォーロック)
- ☆3 ライカン(ヒューマン/ビースト/ウォーリア)
- ☆3 ベノマンサー(ビースト/ウォーロック)
- ☆3 影のデーモン(デーモン/ウォーロック)
- ☆4 トロルの戦将(トロル/ウォーリア)
- ☆4 ローンドルイド(ビースト/ドルイド)
- ☆4 不死のネクロ(アンデット/ウォーロック)
- ☆4 ドゥームデーモン(デーモン/ウォーリア)
- ☆5 不死の悪霊使い(アンデット/ウォーロック)
序盤引きやすいウォーリア軸なので事故が少ない。仮に事故ったときもドルイドで最下位を回避しやすい。派生のバリエーションが多いので、ドローに合わせて柔軟に戦略を変更できる。タスカー・ライカン・ベノマンサー・ネクロで、ウォーリア 3 ウォーロック 3 ビースト 4 アンデット 2 みたいなルートもある。
初手は可能な限りタスカーだが、正直ウォーリアならなんでもいい。どのルートでもドゥームデーモンとトロルの戦将は強いので、優先的に集める。影のデーモンが揃いそうなときはベノマンサーやトロルの医者を集めて、早期のウォーロック 3 を意識する。
序盤中盤終盤、隙がない半面、完成時にぶっちぎりの火力を出せるというわけではないので、完成したメイジ 6 やアサシン 6 やハンター 6 には弱い。
終盤、対面のメイジ 6 が完成しそうな場合、☆5 タイドと ☆2 スラーガーで「ナーガ 2」 の魔防+35%を狙う。範囲攻撃で全員巻き込まれないように、盤面の配置を左右に分ける。これでタイドのスタンがうまく刺されば、そしてゼウスの雷がはずれれば、自分に Lv3 が多く揃っていたら、もしかしたら勝てるかも、という感じ。正直なところ、完成したメイジに対しての勝率は良くない。
おわり
GW はまだ終わってない!auto chess で効率よく溶かすぞ!
同時接続もやたら多いので、これから流行るの間違いないと思う。
amp-script の実用性について考える
AMP Conf 全体の感想は後回しにして(書かないかも)、 amp-script について
単に使ってみたい人は AMP で任意の JS を実行できる amp-script を試してみた - Qiita や https://github.com/mizchi-sandbox/amp-script-preact で
最初に
僕の amp に対するスタンスは http://ampletter.org/?lang=ja に示された懸念とだいたい同じで、基本的にAMPは邪悪なもの、現代のウェブの事情を考慮する必要悪と悪の中間ぐらいだと思っており、それと同時に極端にリソースが制約されたプログラミング環境というものが好きで、そういう点で AMP 由来の技術を追っている、という立場。
amp-script について知っていること
全然ドキュメントないので、コード読んで、書いて、触って、あと中の人達に直接聞いたりして知った知識
- 中身は worker-dom
- worker-dom は正直 alpha 品質。変なことするとすぐ落ちる
- 1 コンポーネント 150kb 制限 (gzip 前)
- 150kb は 1 コンポーネントあたりであって、複数コンポーネントのマウントは可能
- 中から
.wasm
のバイナリを呼ぶと容量制限なし- 将来的に消されないか、意図してる挙動か不明
- script を評価する前に sanitize されるのでこれまた完全に自由ではない
- fetch や indexeddb は呼べる
サイズ制限のせいで、いわゆる JS フレームワーク は preact(7kb) か lit-html(3kb) ぐらいしか選択肢にならない。もしかしたら svelte とか使えるかもしれないが…
- https://v3.svelte.technology
- https://github.com/developit/preact
- https://github.com/Polymer/lit-html
複数コンポーネントは色々できそうな気がしたが、状態を共有しようとすると indexeddb を介したポーリングになると思って実験しようとしたが、 dexie を引っ張ってきたらその時点で 150kb オーバーした。webpack の minimize を常に有効にして watch させるとCPU負荷がかなり高くファンが唸りまくって、出先でやってたらバッテリ使い果たした。
preact も動いたり動かなかったりで、この Issue を見てる限り対応しようとしてるが、待つしかなさそう https://github.com/ampproject/worker-dom/issues/319
amp-bind との比較
AMP の動的コンテンツといえば amp-bind がある。これで専用のハンドラや mustache テンプレートの展開、 amp-live-list と組み合わせた動的コンテンツと組み合わせて、それっぽいものが作れる。
https://amp.dev/documentation/components/amp-bind
個人的な意見だが、これはよくある「プログラミング抜きで〜できる!」と称して一つの DSL 体系を一式覚えさせられるやつである。個人的に全くモチベーション上がらない。基本的には amp-script で全部済ませられるはずだが、amp-login でつくったセッション情報とかを amp-script 側に引き回せるか、まだよく調べてない。できたら同等の表現力になるはずだが。
コールバックで AMP.setState({counter: 1})
みたいな JS みたいなコードを書けるように見えるが、これは正規表現で使える表現が決まっている。また 1 行あたりの発行可能な文字列制限もある。
AMP Bento
カンファレンス中で発表されたもので、まだどこにも情報が上がってないのだが、AMP CDN 下になくても amphtml project の機能を使える、というやつである。 amp 制約下で全部これから作れと言われるとウッとなるのだが、逆に普通のウェブサイトでも使うと便利なウィジェットなどが色々あるので、これは普通に歓迎したい。
AMP の方向性
元来単純なものはAMP、複雑なものはPWAという棲み分けを意図していたように思うが、今回のカンファレンスで示された方向性からは、AMPがPWAやSPAという領域もカバーしようとしている、という印象を受けた。
どうせ Google のことだし内部で明確な方向性定めず部署ごとに競い合ってる状況だと思うが、個人的には邪悪に寄りすぎない範囲でやれることが増えると、ステークホルダーを説得する方便としては便利な技術であると思うので、邪悪ではない限りで応援したい。邪悪だと思っているが。
フロントエンドの開発環境に Docker は不要(少なくともMacでは)
追記: 前提部分
開発環境を docker-compose で抽象することが最近のベストプラクティスだとされているが、フロントエンドをコンテナに突っ込むと無視できないIOボトルネックが発生する。
とくにwebpackのファイル監視からのビルドで発生する高頻度のIO処理を捌くために、フロントエンドだけはホスト環境に移したほうがいい、という主張。
これについて
自分の意見
- Web開発者の主要な開発環境である Docker for Mac は I/O がとにかく遅い (3x~5x)
- data volume の driver やら cache を工夫しても遅い
- npm install/webpack は 基本的に I/O ヘヴィー
- フロントエンドの最終成果物(.js, .css, .html)に環境依存なプログラムが含まれない(含まれてたらおかしい)
- そもそも JS という言語自体がクロスプラットフォームに配慮された言語なので、ホスト環境によるランタイム差がほぼない
ネイティブモジュール周りの既知の問題
- fsevents: webpack や chokidar などの裏側でファイルシステム監視を行うモジュール。npm の lockfile がビルドした環境次第で optional dependencies の native module をうまく依存に含めることができず npm install で再現されないことがある。ファイル変更監視が低速化するだけで動くには動く。yarn でこれが起きたことはない。
- node-sass: libsass の node バインディングだが、ややビルドが不安定。nodeのバージョン上げると大抵コケるのでキャッシュ捨てて再ビルドが必要。最近は css-in-js が流行ってるのでnode-sass見かけることが減った。
- node-gyp: node本体のビルドツール(python2)。 python3 にパスが刺さってる状態でネイティブモジュールをビルドすると失敗する。node でネイティブモジュールを使う環境は
python
が python2 を指している必要があるが、これは他のビルドツールでも何かと要求される要件ではある。
これらを知っていればそこまでクリティカルにはならない。
運用どうするか
CircleCI、デプロイ時、初期セットアップの手数を少なくするためにとりあえずNodeイメージ経由でのフロントエンドのビルドタスクは用意する。開発環境では使わない。
他のプログラミング言語の人から本体のバージョンを固定することを強く要望されることがあるが(それらの言語が不安定なことが多い)、直近の Stable 使ってる限りは Node の実行に差が出ることは稀で、フロントエンドのビルドツールツェインに関してはそこはあまり抽象してメリットがあるレイヤーではない。が、自分の詳しくない領域の安心感がほしいのはわかるので、上述のビルドタスクを提供する。
node のインストールが困難な開発メンバーがいる場合はサポートする。たぶん二手ぐらいで終わるので、docker それ自体の導入より遥かに簡単。
Windows/WSL環境 の場合
すいません自分がWindowsでフロントエンド開発したことないです。
あんまり人権がある方ではないとは聞いてる。
サーバーサイド node の場合
他のサーバーサイドと環境と違ってビルドによる環境差がそこまでないので気にしなくていいと思っているが、 node はネイティブモジュールの数次第で、 imagemagick あたりが鬼門。こいつは常に鬼門。別環境に追い出したい。
node server を運用する際はこの限りではない。
というのが自分の意見です。
Chrome 73 で Desktop PWA Support & mdbuf アップデート
Signed HTTP Exchange もですが、個人的に待望だった Desktop PWA が正式リリース。 PWAアプリをウェブアプリのように振る舞わせることができます。
例えば mdbuf を開いて、「mdbuf をインストール」を選択すると…
モーダルが出て
Win/Mac のアプリのように立ち上がります
mdbuf について
サンプルで紹介しましたが、これは僕が作ってる markdown のプレビューツール です。
amachang さんや結城浩先生へのインタビュー、その他このブログの記事、各種書籍への原稿も全部これで書いています。
mdbuf v1.0.0: 最高の Mardkown Preview を目指して - mizchi's blog
この時点からさらに自分で使い込みながら機能を足したので、Desktop PWA ついでに紹介。
アウトライン機能
ヘッダの位置にジャンプします。
prettier の整形
Cmd+S (Ctrl+S)で prettier で markdown を整形します。
バックグラウンドのコンパイル
WebWorker でコンパイルしているので、入力中のラグ(layout junk) が非常に発生しづらいです。普通に実装する markdown コンパイルはCPUを専有しがちなので、効果が大きいです。
編集中の領域に自動フォーカス
編集に対応するプレビュー側をハイライトします。
保存機能(IndexedDB)
保存します。
textarea => monaco editor => codemirror の切り替え
monaco エディタを使えば編集側でコードハイライトできます。
HTMLでコピペできそうでできない要素を作る
歌詞サイト内で湘南乃風の睡蓮花の歌詞がだんだん大きくなっていた「作詞XSSとか楽しすぎるものをみたけど…」 - Togetter
うたまっぷといえばコピペ禁止、コピペ禁止といえば最近こういう嫌がらせを考えていたので、やってみました。
↑をマウスで選択してコピペしてみてください。うまく範囲選択できないし、できたとしても無意味な文字列になります
仕組み
- テキストをランダムに並び替える
- ランダムに並び替えた文字を, 元の位置に来るように flex の order 属性を指定
フレックスアイテムの並べ替え - CSS: カスケーディングスタイルシート | MDN
コード
React でさっくり書いた
function Text() { const text = "YOU-CANNOT-COPY-THIS-TEXT"; const chars = text.split(""); const textOrders = chars.map(_ => Math.floor(Math.random() * 1000)); const textOrdersSorted = textOrders.slice().sort(); const idxMap = textOrdersSorted.map(v => { return textOrders.findIndex(n => n === v); }); const chars = idxMap.map((to, original) => { return <div style={{ order: to }}>{chars[to]}</div>; }); return ( <> <div> <div style={{ display: "flex", flexDirection: "row" }}>{chars}</div> </div> </> ); } const el = document.querySelector(".root"); ReactDOM.render(<Text />, el);
実行環境
だるくてマルチバイト対応してないので、コードポイントで分割してください。
謝罪文などでこれが来たらいい感じに読者の反感を買えると思います。 悪用禁止!!!!!!!!!!!!!!!
SPA が、ウェブ開発のベストプラクティスになる時代
最近のフロントエンドに関するお気持ち。正直まとまってはない。
最近、こんな感じのツイートや記事が増えた。
シングルページアプリケーション (以下SPA) の台頭により、私の観測範囲ではモダンな Web サイトは SPA で作られるようになった。サーバーサイドは JSON を返す API サーバーとなり、DB やバックエンドシステムのプロキシのような存在になりつつある。 私はサーバーサイドエンジニアとしてキャリアを積んできた。SPA が流行りだした頃、いずれサーバーサイドエンジニアは不要になって自分のキャリアを考え直さなくてはいけない時期がくるのではないかと戦々恐々としていた。
自分も元々、SPA を他サイトとの「差別化技術」と定義していた。ブラウザのタブページのライフサイクルにおいて、初期化プロセスを一回にまとめてシームレスな遷移を実現する技術。たとえばゲームだったり、Electron 環境でネイティブに負けないリッチな UI を提供するためのもの。
しかし、最近ではその潮目が変わってきている、と強く感じる。具体的には、SPA 技術は「すべてのウェブ開発におけるベストプラクティス」になってきたと感じる。
Node.js が Rails に「勝てなかった」理由
元々 Node.js が c10k 問題へのソリューションを謳って登場したのを覚えてる人は、どれだけいるだろうか。その時は他 WAF への Altenative であることが強く打ち出されていた。
それから数年経って、結論から言ってしまえば、Node.js は Rails に勝てなかったのではなく、勝つ必要がなくなった。Node.js は主にフロントエンドツールチェインとして発達し、マイクロサービスにおけるフロントエンド周りを担当する「補助輪」として機能すればよくて、バックエンドに興味を持たなくなった。
現代のストレージは、アプリケーションレイヤーで管理すると言うより、RDS や Aurora, Firebase や Spanner のように、フルマネージドなバックエンドで抽象されるものになった。データベースのスケーリング技術を知識として持つことは依然として重要だが、以前ほど重要ではなくなった。
現代では、並列実行を管理する主体がプログラミング言語のスケジューラから、前段のロードバランサやコンテナのスケジューラに移ってきた。Node.js の弱点はシングルスレッドのイベントループが process fork に向いておらず、シングルプロセスを酷使するや故に例外復帰が難しいことだったが、むしろ現代のマイクロサービス環境ではコンテナに割り当てられた CPU を使い切ることが重要で、例外復帰は投機的なコンテナ単位で行われるようになった。
結論から言えば、 Rails や Symfony のような一つの言語に依存するフルスタックフレームワークは今世代が終わりで、これからはPaaSやマイクロサービス環境で他と協調することが前提のものに分解されていくだろう。しかしそのための土台になると予想される k8s は、数年前のフロントエンドと同じような「難しい抽象を一番うまい抽象化したやつが勝ち」みたいなOSS乱立期で、やや手を付けづらい。
JS の進化 / 漸進的型付けの時代
JS といえば昔はphpやperlと並んで貧弱な言語の代表格だったが、近年の ES2015 以降の言語仕様の進化は目覚ましい。ランタイムにおいても V8 の JIT は異常な域で、繰り返し実行される処理に関しては、ネイティブから「多少遅い」程度のスピードが出てしまう。
また、今は動的型付に対する反動の時代で、ドキュメンテーションとしての型、ある種の Linter としての型というものが再評価されている。その点で TypeScript は漸進的型付けに必要なものを全部備えていて、現代における動的型付けと型の向き合いに関してはほぼ最強みたいなレベルに達している。
漸進的型付け言語の時代に必要なもの - mizchi's blog
というわけで言語仕様的な貧弱さの問題も解決しつつある。TypeScript の型定義も昔はないのが普通だったが、最近は大方ある、という感じになってきた。
そういえば、 python で pyre-checker や mypy を試してみたが、正直実用に程遠い完成度で、これだったらまだ TypeScript のが開発体験は良いという感想。(ただ js では numpy が現状置き換えられないので機械学習用途に使うのは難しい)
依然として後方互換のためのバッドパーツは残っているものの、ES2015 と TypeScript のプラクティスが普及することで解決される問題だと思っている。
WebAssembly は…、たぶん非常に限られた使い道になりそうな予感がしていて、GC インテグレーションの問題が解決しない限りは C++/Rust 以外でまともなサイズのwasmバイナリが生成できない。ツールチェインは Rust がよく出来るので、しばらくはピンポイントで重い処理を Rust を書く、というのがメインになりそう。
パフォーマンス問題
読み込み問題も、読み込みを lazy に分割する chunk splitting の技術や、precat や lit-html のような軽量 View ライブラリ、vue や angular の静的解析技術によるコード生成サイズの減少で、大きな問題にならなくなってきた。
- https://gist.github.com/Restuta/cda69e50a853aa64912d
- https://github.com/developit/preact
- https://github.com/Polymer/lit-html
一部のフロントエンドは、 HTTP/2 + ESModules 環境でブラウザネイティブの ESM ですべてを解決する夢を見ていたが、現状そのための仕様は頓挫し、Webpack を捨てることは、あと数年は困難になった。
Cache Digest と HTTP2 Server Push の現状 | blog.jxck.io
webpack が置き換えられることはあるかもしれないが、その目的はしばらく死にそうにない。
今後の SSR問題
SSRは高難易度の技術だったが、next.js や nuxt.js の普及、国内においては特に nuxt.js が普及したことで比較的手軽になった。自分は React 派だが、正直 next.js より nuxt のが遥かに良く出来てる。(というか next.js は過剰なミニマリズムの病気に掛かっている気がする…)
ついでにいうと、WebComponents は今の仕様のままだと依然として SSR の問題を抱えていて、shadowRoot 下に生成されるコンテンツをクローリングさせるために SSR が必要になっている。というわけで今後もSSRを避けて通ることができないと予想している。
自分が知る限り、SSR を行わないウェブサイトは、ニュースメディアのような速報性が強いサイトには依然として SSR が必要ではあるが、それ以外では意外とインデックスされるし、そこまで重要ではない。(依然として検索スコアが低いような気はしなくはないが…)
これは自分が知る限り、GoogleBOT によるウェブサイトのクローリングが行われると、JS 実行キューに入り、そこでページが構築されるとインデックスされる、という 挙動にある。JS によるページ構築は即座に行われるのではなく、数時間遅れて実行される。
今後の展開としては、BFFのレイヤーはマイクロサービスのクラスターの一部というより、 CDN Edge 上の Edge Worker に主戦場が移って、キャッシュマネジメントとSSRを同時に担うのではないか、と考えている。
Edge Worker PaaS の fly.io が面白い - mizchi's blog
本質的な作業に集中する、とはなんだろうか
主に非エンジニアのスタートアップ事業者や新規事業者にとって興味があるのは、UI と概念のモデリングとそこから生まれる体験であって、そのインフラストラクチャに対応として構成は「仕方なく」やるものなのは変わっていない。(それこそエンジニアリングといえばそうなのだが…)
なので、UI に興味が集中する。なので、競合に勝つための体験、「SPA」に興味が集中するのは、当然のような気もする。ただ、うまく使いこなせているプレーヤーは少なく、とくにパフォーマンスチューニングは属人化しているのが現状(なので自分のようなフロントエンド専門のフリーランスに需要がある)
あるジャンルが高度化しては PaaS/OSS/Container にラップされる、というのを今後も繰り返すだろうが、フロントエンドがそうならないのは、UI は人間の理不尽な要求に振り回される、という特徴にあるという気がしている。
例えばソーシャルゲームはリッチ化の過程でユーザーの期待値が膨れ上がり、開発費が高騰して参入障壁が跳ね上がっているが、似たような現象はどの分野でも起こる。UI への投資が減ることはないだろう。エンジニアとデザイナと連携する部分で AI による生産性の向上はあるかもしれない。
個人的には e2e が未発達なことに課題を感じている。
おわり。
Edge Worker PaaS の fly.io が面白い
なかなかよいおもちゃを見つけたので、紹介します。
fly.io は CDN Edge Worker で JavaScript に特化した PaaS です。既存のサービスで近いものだと CloudFlare Workers もしくは Lambda@Edge でしょうか。
アカウント登録をして、次のようなコマンドを叩くとエッジで動くアプリケーションを作成することができます。
npm install -g @fly/fly fly login # mkdir my-flyio; cd my-flyio fly new
最小コードはこんな感じ。CloudFlare Workers と同じような ServiceWorker 風と、Google Cloud Function 風の 2 つのパターンでワーカーを定義できます。
// index.js addEventListener('fetch', function (event) { event.respondWith(new Response('Redirecting', { headers: { 'Location': 'https://fly.io/docs/apps/' }, status: 302 } )) })
fly.io のここがいい
フロントエンドの最適化の行き着く先の解の一つ、それは「CDN Edge で HTML をキャッシュして返却する」というものです。そして、ある程度動的な JS をユースケースに応じて返却したい場合、 Edge で SSR を行って、一度実行した HTML はキャッシュする、という戦略が有効です。
JS の SSR は、残念ながら今後も必要な技術だと想定されています。しかし、コンテナ技術の発展で、Node の運用の敷居は前より下がりましたが、それでも Node を運用するのを躊躇するエンジニアの方も多いでしょう。
SSR や HTML Cache に対するこれらの懸念を、Edge Worker はまとめて払拭できます。
- 必然的にPaaS なのでフルマネージド
- レスポンス最適化のために Edge Cache で HTML を返せる
- SSR は複雑な処理なので、ほぼフルスペックの Node がいる必要がある
また、SSR / BFF 特有の事情として、次のような要求があります。
- HTML をキャッシュする場合、セッション情報に触れないほうが安全に SSR できる
- SSR の主な需要は大雑把なファーストビューの最適化と、 GoogleBOT 向けの情報を構築することなので、セッションに触れる必要はない
- 起動後にリバースプロキシとして動いて API オーケストレーションを行う
イニシャルビュー最適化で、すべてのリクエストに対してセッション情報付きで SSR するのを要求する人もいますが、運用事故を避けたり、キャッシュ最適化やパフォーマンスチューンまで考えると、この辺が現実的な落としどころだと思います。
つまりは BFF (Backend for Frontend) と呼ばれていた層の一部を地理的に最適化される Edge Location に持ってくることができます。
そして、キャッシュを扱う以上、それなりに KVS を扱いたいわけで、他のサービスではなく fly.io が優れてるのは、この辺のために便利なパーツが一通り揃っていることです。
@fly/cache
: リージョン単位の揮発する KVS@fly/cache/global
: 永続化されるグローバルな KVS@fly/db
: 永続化されたグローバルな簡易ストレージ(Mongo 風?)@fly/static
: 簡易アセットサーバー@fly/fetch/mount
簡易ルーター@fly/fetch/proxy
簡易リバースプロキシ- varnish surrogate key のような、タグによる Cache Invalidation
varnish surrogate key による Cache Invalidation が個人的に一番欲しかったやつで、現状他の CDN だと fastly ぐらいしかこの機能を持っていませんでした。
https://book.varnish-software.com/4.0/chapters/Cache_Invalidation.html
各種ストレージを使ってみた感じ、それぞれは本格的なものではないのですが、アプリケーションサーバーへ到達する前の エッジロケーションにこれがある、ということが大事で、とくに各種キャッシュと簡易アセットサーバー、簡易ルータがあるので、頑張れば Edge で完結するアプリケーション層として動くことすら可能です。
作ってみた
というわけで、簡単な掲示板アプリを作ってみました。各ページはその Edge ではじめてときだけ SSR され、それ以降はキャッシュされた HTML を返却します。初期化以降は CSR で動きます。
https://grave-crowd-822.edgeapp.net
ソースはここ
https://github.com/mizchi/flyio-playground/tree/master/examples/react-ssr
主に React + react-router + styled-components での SSR と、 fly/db に書き込みの内容を永続化して、 fly/cache で SSR 済み HTML をキャッシュしています。next.js などは使わず手作業で無理矢理 isomorphic にしてるので、コードの見通しは悪いです。あとでどうにかする…
作ってみた感想
- node エンジニアなら特に迷うところサッと作れる
- ローカルでほぼサーバーと同等のものが動くので開発が楽 (lambda/cloud function はここが微妙)
- GitHubにソースが公開されてるので最悪これを自分でホスティングすればいいという安心感がある
- express (node http) 互換ではなく、コールバックが
(req, res) => {}
ではなく、(req) => new Response(...)
みたいな形式 - API ドキュメントがまだまだふわっとしている
- 独自の v8 でビルドされていて、微妙に実装されてないものがある (crypto 周りで動かないモジュールがあった)
fly/db
は、本当にただのおもちゃなので、信用しないほうがいい… (query や scan 相当のものもないし、列挙も出来ない…)- 本番環境での fly/cache/global への書き込みはそれなりに遅い
複雑なストレージを持つようなものではないので、これ一つで完結する、というものではありません。
参考になるリソース
- 公式 API ドキュメント https://fly.io/docs/apps/api/index.html
- GitHub の Examples https://github.com/superfly/fly/tree/master/examples
examples 眺めながら、公式ドキュメントを読みつつ、わからなかったら GitHub で実装を読む、という感じでだいたいやりたいことをやれました。
料金
- $25 の無料枠
- 有料の場合、最低月 $10 から
超大規模想定で適当に試算してみても $100 超えるのは難しそう
で、本格的に使っていいの?
ぶっちゃけリリース直後なので、なんとも言えません。人柱募集したいところ。
とりあえずは、Edge Worker 使った際のアーキテクチャを考察するための実験場として使うのがいいんじゃないでしょうか。ユーザーが増えて、実質 SLA どのぐらいか判明したら、プロダクションに突っ込むかどうか考えれば良さそう。
cloudflare も Edge Worker というよりは Serverless として Edge Worker 市場に参入するぞ!みたいなことを言い出してるので、こっちも注視したいです。
Node.js エンジニアの活路としての Edge Side
前々から思っていたこととして、フロントエンドとサーバーサイドの間に、 エッジサイドのエンジニアという職域がうまれるんじゃないかと想像しています。先に述べたように API オーケストレーション+SSR を行う Node BFF がここに位置するのではないか、と思っています。
日本においては node.js エンジニアは(SFなどの海外と比べて)あまりサーバーサイドでシェアを取れませんでしたが、まともな ORM がない Node 一本で行くのは僕もちょっと厳しいと思っていて、Node が本当に生きるのは、ブラウザと緊密に連携する前段の、Edge Side なんじゃないかと考えています。
Edge Workers は単なるパフォーマンス要件を満たす選択だけではなく、BFF ベストプラクティスとしての活用があると思っています。SPA を何年も作ってきましたが SPA をフルに運用するには、やはりフロントエンドエンジニアが握る BFF が不可欠だという気持ちがあります。
という感じでみなさんも fly.io で遊んでみてはいかがでしょうか。
ちょっと前に Edge ヘヴィーなフロントエンドのアーキテクチャの考察をしたので、こちらもどうぞ