明日の下書き
- 高円寺.dev #3 用の資料 https://koenji.connpass.com/event/160886/
- フロントエンド専門じゃない人向けの、フロントエンドの最先端〜やや未来の話です
- このレイヤーでは Node.js を使うべき/使うと強いという部分がありますが、他言語を否定しているわけではありません。むしろ他言語でこのアーキテクチャを模倣してほしいという話です。
- IE が死ななかったので各種ポリフィル、メタ言語からのトランスパイルが発達。しかしモダンとレガシーの乖離が深刻に。
- node と npm エコシステムの成立
- 仮想 DOM がフロントエンドライブラリの標準的な状態管理手法に
- モジュールシステム需要が ES Modules(ES2015)に結実。しかし webpack は死ねなかった。
- IE 需要+ブラウザ自身も後方互換性を維持し続けたために、先進的な技術を使う人と、素朴なサポート水準の技術を使う人のスキルセットが完全に乖離してしまった。IE を言い訳に、最新仕様を勉強しないことへのインセンティブが強く残った。
- 2010 年代前半のモバイルアプリ需要で、若者の供給が一度途絶えて、人の入れ替わりがない時期があった。最近になって一部の Web 回帰、または Firebase や ReactNative 需要で多少盛り返した。
- 作りきりの Web 制作の文脈と、アーキテクチャのある Web アプリケーションの文脈が完全に別物になってしまい、合流しなかった。
- 世界シェア 3% 国内シェア 11.7%
- Win7 の EOL (Win7 は Edge 非搭載)
- EOL の Win7 への MS Edge の配信: Chrome Based Edge が入ってるんだから IE を使えと言えるように
もはや toC では商用サポートされていないので、よほどの理由がない限り、IE を落とすことができるはず…とはいえ日本の 12%は気になるところだが…
実際には IE をサポートし続ける痛みが、現場のアーキテクチャの進化を強く阻害しているので、サポート切れを根拠になんとかして落としたい。
参考:
- Web ブラウザシェアランキング TOP10(日本国内・世界) | ソフトウェアテスト・第三者検証ならウェブレッジ
- 新 Edge ブラウザ登場に伴う IE サポート終了についてチームのコンセンサスを得るためのシンプルなテンプレ - Qiita
- Dependency Hell: Pure な ESM では、
import a from "./a.js"
と書くと、現行の仕様では、一旦サーバーからスクリプトを取得し、パースして、初めて、./a.js
の更に下の階層の依存が判明する。 - npm 時代のモジュールの依存は深い。とても深い。とてもではないが、深さ n(>5) のラウンドトリップに耐えうるものではない。元々の node.js 環境においては単にローカル FS の read でしかないので問題にならなかった。
- 依存を先に宣言しておいてストリームに投機的に次のデータを突っ込んでおく、という用途で期待されていた HTTP Server Push の仕様が死んでしまった https://blog.jxck.io/entries/2019-01-19/cache-digest-status.html
- ESM と HTTP の話とは別に、ECMA 非標準な TypeScript の人気が増しているので、結局プリプロセッサは必要なわけで、だったら結局 Webpack 通すわけでビルドの手間は一緒じゃん、といったコミュニティの温度感がある。
一応、 https://github.com/WICG/import-maps や https://blog.jxck.io/entries/2019-11-12/webbundle.html でどうにかならないか、という試行錯誤はあるが…
フロントエンドは「UX のための差別化技術」から、「アプリケーション層のベストプラクティス」に。
参考: SPA が、ウェブ開発のベストプラクティスになる時代
- next.js/nuxt.js への開発リソースの集中 (Google も支援)
- 他者に配られる静的アセットから、「アセットパイプラインと連携して、それらのリンクを効率よく配る node サーバー」に昇格
- TypeScript の漸進的な型付けで,(比較的)堅牢なアーキテクチャに
重要なのこととして、 next.js/nuxt.js 型のフロントエンドサーバーが、次世代の Rails になりつつある
- (古くは)異なる言語で同じものを作っていた二重テンプレート問題
- 初期化が重い SPA の効率的な画面遷移には、 Server Side Rendering(SSR) の他に、サーバーを経由しない Client Side Routing(CSR) が必要
- => SPA じゃないとしても、アセット再取得が最小限になる CSR は、パフォーマンス上有効なことがわかった
App Shell モデル | Web | Google Developers
next.js の実体は webpack によるチャンク生成と node.js を緊密に連携させるように設計されたフレームワーク。
マイクロサービス上の、永続層を含まない、ユーザーと通信する フロントエンドサーバー
- CDN First な設計: DC の外側にある CDN Edge とのコミュニケーション(主にインバリデーションの発行管理)という新たな領域の出現
- 永続層を含まない: Node.js は永続層周りのサポートが貧弱なので、外部に丸投げする。PaaS, DBaaS, No Code Backend
次代のスタートアップの MVP/個人 Web 制作はこうなる
- 静的アセット + PaaS の露出 (Firebase スタイル)
- ほぼ JS だけで完結
- API として露出した部分の Firebase/Serverless の持つパーミッションがセキュリティ関心の中心に
- 2つの出力モード
- 静的モード: SSR なしで完全な静的アセットとして出力。
- 動的モード: セッションの状態を含んだ First View で出力可能。
- 現代の Google Bot の挙動
- クローラーが静的コンテンツをインデックス。その後、レンダリングキューに入る。
- n 時間後、レンダリングキューの順番が来ると、 Chrome でレンダリングされてインデックスされる。
速報性が高く競合が多いニュースサイトは SSR が必須。逆に言うとそれ以外では重要度が徐々に下がりつつある。 年々この n 時間は縮小傾向。
https://developers.google.com/search/docs/guides/javascript-seo-basics?hl=ja
状態管理の目線では、出力の冪等性のためにテンプレートが同じ言語のロジックで管理される必要があり(仮想 DOM、多重テンプレート問題等の需要)、Next.js / Nuxt.js は開発言語を node.js に制限してしまう。
ブラウザとサーバーで同じロクックで動けばいい、という点では WebAssembly で仮想 DOM アルゴリズム実装込みで出力できればよい。しかし、WASM の仕様に GC が含まれないのと、出力サイズの問題で、現実的に WASM Backend として選択可能な言語は、現実的には C/C++/Rust のみ。例えば Go を WASM 出力すると、GC のために Interpreter 一式がビルドされ、Hello World 程度でも 1.4MB になってしまう。
C/C++/Rust は(好みの問題ではあると思うが)、アプリケーション層のロジックを記述する言語としてデザインされておらず、Web 開発の現場で一般的になるのは想像し辛い。
WASM の GC が標準化され、かつそれが GC 付きの言語が現実的なサイズでビルドできるような仕様であり、かつ Rust の wasm-bindgen のような優秀な DOM API ブリッジが各言語で実装されれば、 Java, C#、Ruby,Python,Swift といった言語がウェブフロントエンドの選択肢になるかもしれない。ただ、そのエコシステムが整うのが 2020 年代前半に来るとは考えづらい。
- https://github.com/rustwasm/wasm-bindgen
- https://github.com/WebAssembly/gc/blob/master/proposals/gc/Overview.md
まとめると、 WASM が来るから JS 勉強しなくていい、みたいな時代は、まだ来る気配はないです。一旦諦めてください。
すでに WASM 経由の Isomorphism の実験例がある。Blazor は WebAssembry, iOS, Android の出力を持つ、MS 製の実験的なテンプレートエンジン (埋め込める言語は C#/F#)。
コード例
<div>
<h1>@Title</h1>
@ChildContent
<button @onclick="OnYes">Yes!</button>
</div>
@code {
[Parameter]
public string Title { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
private void OnYes()
{
Console.WriteLine("Write to the console in C#! 'Yes' button was selected.");
}
}
これが実用的になれば、クラサバを C#(.NET) で完結したオールインワンの開発環境が実現されるかもしれない。
現在は Mono を使っているからサイズが大きいが、最終的な Minimal な .NET ランタイムになるから軽量(60kb)、 とのこと(本当か?)
参考: https://github.com/dotnet/blazor/wiki/FAQ
初期の Webcomponents v0/Polymer Project が目指した、宣言的な HTML だけですべてが成立する世界。JS が使えないという制約と引き換えに、Google 検索や Google CDN による各種優遇を受ける。
サーバーサイドを node.js にしない場合、むしろこっちを目指したほうが全体的なコスパは上がると思う。フロントエンドスタックを一切導入しない Rails や PHP はこちらを目指した方がいいかもしれない。
動的コンテンツを含む場合、Google CDN キャッシュ時にある種の SSR 的なテクニックは必要。 (amp-bind)
** とても政治的な要素を含む技術である点に注意。** ある種のベストプラクティスの強制であり、Google が一部の技術を優遇することの批判が絶えない。
- MFI: FMP や FCP などの各種スコアが検索スコアに関与するようになる
- フロントエンドパフォーマンスが、贅沢品から、コンテンツを見てもらうための必需品の時代に
- 5G や http/3 でまた設計が何かしら変わるかも
JS は Developper Experience の名の下に富豪的に使われすぎている。144kb以下にしろ、という主張
https://infrequently.org/2018/09/the-developer-experience-bait-and-switch/
で、よく挙げられるライブラリに以下のものがある。
- preact: 軽量 React
- lit-html
- (ライブラリとしての) AMP
よく見落とされていることだが、 AMP 制約を満たさなくても AMP をライブラリとして使うことは可能。
UI Thread から描画に関するものを排除し、ペイロードや初期化時間を効率化しよう、という戦略。IE に搭載されながらも日の目を見なかった WebWorker を使っていこうという Google Dev Rel 周りが推奨してる戦略。
- comlink: 使いづらい WebWorker をラップしてくれるフレームワーク
- comlink-loader: comlink 経由で webpack で指定した読み込み先を worker 化してくれる。便利
- worker-dom: WebWorker 上に仮想の DOM ツリーを構築して、そこに行われた変更をメインスレッドの対応する DOM に sync するライブラリ。 AMP Script の実体。
vscode がサクサク動くのも WebWorker で各種処理(コードハイライトや補完エンジン)が並列化されてるから。
キャッシュのキーに読み込んだドメインが追加されるブラウザ仕様の変更。現在、キャッシュ状態に対してサイドチャネル攻撃で検索履歴などを抜き出せたり、特定の DNS の解決速度で fingerprint に使われたりする。
例えば、 cloudflare の CDN 経由で jquery を読み込んでおけば、他のページで読み込まれてる可能性が高いから読み込みが速い、みたいな可能性がゼロになる。なんでもかんでも script タグで CDN から JS を引っ張る人に叩きつけましょう。
Double-keyed HTTP cache に関するメモ - ASnoKaze blog
ウェブ開発の歴史上、パフォーマンスやセキュリティをウリ文句にしたフレームワークが覇権をとったことはないので、結局 Firebase や AWS AppSync が問題を抱えながら普及するのだと思う。
なんらかの品質やプロダクティビティに貢献する制約を隠れ蓑に、パフォーマンスやセキュリティ意識を向上させる開発者環境に取り組んでいく必要がある。
s/ロクック/ロジック/