Upgrade to Pro — share decks privately, control downloads, hide ads and more …

「書いたJavaScriptがそのままブラウザで動く未来へ」スピーカーノート

sosukesuzuki
November 19, 2023
11k

 「書いたJavaScriptがそのままブラウザで動く未来へ」スピーカーノート

2023年11月19日開催された JSConf JP 2023 で発表した「書いたJavaScriptがそのままブラウザで動く未来へ」のスピーカーノートです(スライドに対した情報がないので、スピーカーノートをそのまま公開します)。

sosukesuzuki

November 19, 2023
Tweet

Transcript

  1. 1. こんにちは、今日は「書いたJavaScriptがそのままブラウザで動く未来へ」というタイ トルで発表をします。「いやいや、JavaScriptはブラウザで普通に動くだろう」と思わ れる方もいらっしゃるかもしれませんが、話を聞いてもらえれば何を言っているのか わかると思います。 2. JSConf JPで登壇させていただくのは今回で3度目なのですが、オフラインのカン ファレンスで話すのは今回がはじめてなので少々緊張しています。 3.

    最初に軽く自己紹介をします。鈴木 颯介と言います。大体のところで Sosuke Suzuki という名前とこのアイコンでやっています。ユビー株式会社でプロダクト開発 エンジニアをやりながら、筑波大学でパソコンのお勉強をしています。あと、Prettier というコードフォーマッタのメンテナーとかBabelというJavaScriptのトランスコンパイ ラのコミッタなどをやっています。 4. また、私の所属しているユビーは今回JSConf JPのプレミアムスポンサーをやらせて もらっています。ブースもありますので興味のある方はぜひお立ち寄りください。 5. ユビーとはあんまり関係ないですが、Babel のステッカーも配布しているのでそちら もよろしければ取っていってください。 6. さて、ここからトークに入っていきます。 1. 突然ですが、みなさんは仕事でどんなフロントエンド技術を使っていますか? 2. 現在のフロントエンド開発には、数多くの選択肢があります。 3. たとえばReact、Vue、Svelte。そしてそれらのメタフレームワークであるNext、Nuxt 、Sveltekit。実際にはもっとたくさんの選択肢があります。Angular、preact、qwick、 nueなどもあります。もっと昔のもので言えばBackbornやRiotなどもあります。数え たらキリがないでしょう。 4. ちなみに、私の所属しているユビーのtoCアプリケーションではNext.jsを使っていま す。 5. もちろん、こういったフレームワークを使わずにJavaScriptをそのまま書いたり jQueryを使っている人もいると思いますし、Ruby on Railsなどのサーバーサイド主 体のフレームワークに搭載されているフロントエンドのための機構を使っている人も いると思います。Closure LibraryとかClosure CompilerやClosure Templateなん かを使っている人もいるかもしれませんね。 6. ここでは、私が今名前を挙げた中でも、いわゆる「モダン」なものに注目してみます。
  2. 7. 「モダン」というと主観的すぎてイメージがしにくいかもしれないので、なんとなく私が 今想像しているものの名前を挙げておきます。Next.jsやNuxt.js、Sveltekit、Astro、 Remixあたりでしょうか。 8. もしかしたらここで異議がある方もいるかもしれませんが、この分類を厳密に行うこと は今日の発表にとっては本質的ではありませんので、話を続けますね。今は「そうい うフレームワーク」について話してるんだと理解してください。 9. これらのフレームワークには共通する特徴があります。それは「JavaScriptを直接書

    かないこと」です。 10. Next.jsをお使いのみなさん、あなた方のほとんどはTypeScriptとJSXを使ってい ると思います。 11. もしまだピュアなJavaScriptとhyperscriptを使ってReactコンポーネントを書いて いるという人がいたら、そのこだわりについてぜひ聞きたいです。 12. Next.jsのプロジェクトを立ち上げて、普通に設定をしていったらTypeScriptとJSX を使うことになると思います。我々普通のプログラマーは、その詳細を把握している 必要はありません。便利な世の中になりました。 13. こういったフレームワークが普及する前は、webpackやBabelの設定を一から書 いていました。実は私はそれらの設定が人よりちょっとだけ得意でしたが、もうそのと きには戻りたくありません。 14. 整理すると、現代を生きる我々の多くは「ブラウザでは実行できない何かしらの言 語を使ってソフトウェアを記述し、それをなんらかのツールを使ってブラウザが直接 実行できるHTMLやJavaScriptなどの言語に変換している」と言えそうです。 15. なぜそんなことをしているのでしょうか。普段はあまり考えないかもしれませんが、 もしもそれらがなくなったときのことを考えれば、理由は明らかだと思います。 16. TypeScriptなしで、JSXなしでReactアプリケーションを書くことを考えてください。 これを考えると、TypeScriptの型によって安全なプログラミングが、JSXによって直感 的な宣言的UIの記述が可能になっている、ということを思い出せるでしょう。 17. これは逆に考えると、そのままのJavaScriptだけではそれを実現できないから、 何かしらの変換を行っていると言えますね。 18. でも待ってください。JavaScriptは高級言語です。それもかなり高級です。私はコ ンパイラについてそこまで詳しくありませんが、マシンからしたらそれなりに厄介そう ですよね。 19. 私は、そんなJavaScriptをコンパイルターゲットとして使っている現状に違和感を 感じています。
  3. 20. その現状について「悪い」と言うつもりはありません。私は仕事でも趣味でも Next.jsを使っています。でもちょっとだけ違和感があります。 21. 同じような気持ちになったことがある人もいるのではないでしょうか。 22. ブラウザがECMAScript Modulesを実行できるようになってからもwebpackを使 い続けて「アレ、おれたちなんでこんなことしてるんだっけ」と思った人はいません か?私はそのように思いました。

    23. そこで、どうしたらJavaScriptをそのままフロントエンド開発に使えるようになるの かを考えてみたいと思います。 24. ここからは、我々がJavaScriptをコンパイルターゲットとして扱っている理由を更 に深ぼって、JavaScriptやWebにどのような機能があれば、そのままフロントエンド 開発に使えるようになるかを考えます。 25. つまり、ここからが本題です。 ここまでで8分 1. ビルドステップを詳細化することで、我々がJavaScriptをコンパイルターゲットのよう に扱っている理由を明確にしていきましょう。 2. 最初に注意しておきたいのですが、今から説明する各ビルドステップについて、ここ では便宜上分けて説明しますが、すべての実装においてパスが別れているというこ とではありません。 3. まず最初は、TypeScriptからJavaScriptへの変換です。TypeScriptやMetaのFlow などの、JavaScriptの構文を拡張する形で型アノテーションを記述する言語を使って いる場合、それをそのままJavaScriptエンジンで実行することはできませんので、型 アノテーションの部分を除去する必要があります。 4. スライドをご覧ください。このような、ある関数についてその引数が string 型で返り値 が void 型であるという注釈を除去します。 5. このステップを行う具体的なソフトウェアは、TypeScriptコンパイラ、Flowコンパイラ、 Babel、SWC、esbuildなどです。 6. 次に、JSXからJavaScriptへの変換です。JSXはECMAScriptに含まれている構文 ではありません。ECMAScriptの立場から見ると、エコシステムによっていわば勝手 に拡張されているということになります。 7. JSXの構文もTypeScriptなどと同じようにJavaScriptエンジンで直接実行できるわけ ではありませんから、実行できる形に変換する必要があります。
  4. 8. JSXの最も一般的な用途は、Reactコンポーネントを記述することだと思います。で すが実際のところJSXをどのようにJavaScriptに変換するかは自由に設定できま す。実際にVueなどのReact以外のライブラリでも使うことができます。あまり見かけ ないですが、ExpressなどのAPIをマッピングすることでサーバーを書くこともできま す。 9. つまりこのステップの役割は、事前に決められた設定にしたがって JSX の構文を

    JavaScriptの関数呼び出しへと変換することなのです。 10. このステップを行う具体的なソフトウェアは、さきほどと同じで、TypeScriptコンパ イラやFlowコンパイラ、Babel、SWC、esbuildなどです。 11. 次のステップは、いわゆるダウンレベルコンパイルです。 12. Ecma International のTC39やJavaScriptエンジン開発者、コミュニティの尽力に よって、JavaScriptは毎年大きく進化し、プログラマにとってより便利なものへと成長 しています。 13. まだ記憶に新しい便利な機能としては、ES2020 の Optional Chaining や ES2022 の Array.prototype.at などがあるでしょうか。GitHub の tc39 オーガナイ ゼーションの proposals リポジトリの finished proposals の一覧を見ると JavaScript が年々便利になっていっていることがわかると思います。 14. 我々プログラマーは生産的な仕事をするためにこのような便利な機能をできるだ け早く使いたいわけですが、フロントエンド開発の性質上、それが難しいことがありま す。 15. サーバーサイドの開発では自分たちの書いたコードを実行するランタイムを、基本 的には自分たちで決めることができます。しかしフロントエンドではランタイムはユー ザーが持っているウェブブラウザです。したがって、新しい言語機能をすぐに使えな いケースがよくあります。 16. そういった場合には、新しいJavaScriptのコードを古いバージョンのJavaScriptで も動くように変換する必要があります。これがダウンレベルコンパイルです。 17. スライドをご覧ください。これは Optional Chaining と Array.prototype.at をそれ ぞれ ES2015 でも動くように変換する例です。 18. このステップによって我々JavaScriptを書くプログラマは、自分が使うJavaScript のバージョンを決定する自由を手に入れているわけです。 19. このステップを行う具体的なソフトウェアは、さきほどと同じで、TypeScriptコンパ イラやFlowコンパイラ、Babel、SWC、esbuildなどです。 20. 次のステップは、モジュールのバンドルです。
  5. 21. 以前のECMAScriptにはモジュールの機能がなく、ウェブブラウザ上の JavaScriptでモジュールを使った開発をするのは不可能でした。想像してもらえれば わかると思いますが、モジュールなしで大規模なソフトウェアを開発するのは中々に つらい仕事です。 22. そこで、モジュールバンドラーというソフトウェアが登場しました。プログラマはモ ジュールで分割されたコードを書き、モジュールバンドラーを使ってそれをあらかじめ ブラウザが実行できる形式にバンドルします。 23.

    実際のユーザーのブラウザでは、そのバンドルされたコードが実行されるというわ けです。 24. つまり、ダウンレベルコンパイルと同じような考え方とも言えます。 25. スライドをご覧ください。これは簡単なモジュールのバンドルの例です。 26. このステップを行う具体的なソフトウェアは、browserify、webpack、parcel、 Rollup、Vite、esbuild などがあります。 27. 最後のステップはミニファイです。 28. ユーザー体験を最大化するためには、配布されるJavaScriptのサイズは小さい 方が良いです。当然ですが大きなサイズのファイルをダウンロードするのには時間 がかかります。 29. スライドをご覧ください。これは簡単なミニファイの例です。 30. ミニファイには色々な手法があります。空白やコメントの除去、変数名の短縮、よ り短い等価なコードへの変換、デッドコードの除去などです。 31. このミニファイのステップは十分に普及していますが、性質上必須というわけでは ありません。そのままでもJavaScriptのサイズが十分に小さい場合や、難読化の必 要がない場合には不要です。 32. このステップを行う具体的なソフトウェアは、terser、UglifyJS、SWC、esbuild、 Closure Compiler などがあります。 33. さて、ここまででJavaScriptのビルドステップについて説明しました。昔からなじみ のあるwebpackとBabelの組み合わせも、最近のNext.jsも、大まかにはこのような ステップを経て、JavaScriptをブラウザで動く形にまで変換しています。 34. ここからは、どのような機能がJavaScriptやWebに備わっていれば、このようなビ ルドステップから解放されることができるのか、そしてそれは現実的であるのかにつ いて考えていきましょう。 ここまでで15分くらい
  6. 1. 今説明したすべてのビルドステップを取り除くことができれば、私たちはJavaScriptを 直接記述できるようになるということです。 2. では、それぞれのステップについて、どのようにすれば取り除けるか検討していきま しょう。 3. 最初は、TypeScriptの型を除去するステップを取り除く方法について考えましょう。 4. つまり、型アノテーションが書かれたコードをそのままブラウザで動かす方法、という

    ことです。 5. 実は、TC39にはこのための Type Annotations という提案がすでに存在していま す。この Type Annotations は JavaScript のコードの中にTypeScriptやFlowのよう な型アノテーションを書けるようにする提案です。 6. この提案で追加される型アノテーションはJavaScriptエンジンにとってはコメントのよ うなもので、ランタイムによる型チェックが行われるわけではありません。型チェック は今と同じようにTypeScriptコンパイラなどの別のソフトウェアが担うことになりま す。このような特徴もあって、この提案は以前は Types as Comments と呼ばれて いました。 7. この提案があれば、TypeScriptのような構文でプログラムを書くことができ、型アノ テーションを除去するためのビルドステップは必要なくなります。 8. その型チェックは別のツールで行う必要がありますが。 9. しかし、この提案は影響範囲や議論する観点が多すぎて、中々進捗していません。 MicrosoftのTC39メンバーによってこの提案が発表されたのは2022年3月のことで すが、今現在でもまだTC39プロセス上でStage 1のままです。 10. さて、次はJSXをJavaScriptの関数呼び出しへと変換するステップを取り除く方法 について考えます。 11. これも、考え方としては Type Annotations と同じです。JSXをJavaScriptの関数 呼び出しとして解釈できる機能を、JavaScript自体に実装するしかありません。 12. 今のところ、TC39プロセス上にJSXを追加するという提案は正式には存在してい ません。しかし TC39のフォーラム( https://es.discourse.group/) や Matrix Room では議論が続いています。特に今月のTC39ミーティングのアジェンダではJSXにつ いて議論するためのMatrix Roomが紹介されるそうなので、議論を続けていく気が ある人はいるようです。 13. しかしながら、議論を追いかけると、シンタックス・セマンティクスの両面で懐疑的 な姿勢を取っている人もおり、良く進捗しているとは言い難い状況かと思います。
  7. 14. 次に、ダウンレベルコンパイルのステップをどのように取り除けるかを考えます。 15. Intenet Explorer がその役目を終えてMicrosoftによるサポートもなくなった現在 では、以前と比べて多くのユーザーがいわゆるエバーグリーンブラウザを使うように なっています。 16. Google

    Chrome や Microsoft Edge では、基本的に放っておけばバージョンが 勝手に上がっていきます。Apple Safari はそこまでではないですが、MacOS の バージョンを上げれば Safari のバージョンも勝手に上がるようになっています。 17. それに伴ってダウンレベルコンパイルの必要性はそもそも下がってきているので はないかと考えています。提供するサービスのユーザー層によっては、すでにダウン レベルコンパイルなしでも十分に便利なJavaScriptを書けるのではないでしょうか。 18. 現実的には、新しすぎるJavaScriptの機能を使うとユーザーの環境では動作しな い可能性が高いので、ESLintなどの静的解析で、それらの機能を使えないように制 限する必要があると思います。eslint-plugin-es-x などを使えば、特定のバージョン のJavaScriptの機能を使えないように制限をかけることができます。 19. さて、次はモジュールのバンドルのステップを取り除く方法について考えましょう。 20. さきほどはモジュールのバンドルというステップの必要性について、ダウンレベル コンパイルと同じような側面からのみ説明しました。 21. その観点で言えば、やはりダウンレベルコンパイルと同じように、すでにモジュー ルのバンドルは必ずしも必要とは言えなくなってきています。 22. なぜなら、多くのウェブブラウザはECMAScript Modulesを直接実行できるように なっているからです。モジュールを使ってコードを書いて、それをそのまま配布できる はずです。 23. 多くのフレームワークが今でもモジュールのバンドルをし続けているのはおそらく 別の理由で、それはパフォーマンスの改善です。 24. ECMAScript Modulesを使ってコードを書いた場合、基本的にはimportのたびに fetchが発生することになります。もしもファーストビューのために数百からなるモ ジュールを読み込む必要があったら、結果としてユーザー体験を大きく損なうことに なるでしょう。 25. そのため、事前にモジュールを適切な大きさに区切ってバンドルしてから配布して いるというわけです。この観点では、ブラウザがECMAScript Modulesをサポートす るようになった後でも、モジュールのバンドルというステップは依然として必要です。
  8. 26. この import による fetch のたびに発生するオーバーヘッドという問題を解消する ために、Subresource loading with Web

    Bundles や Bundle Preloading といった 技術が提案されていました。 27. これらの技術は、複数のJavaScriptなどのファイルのHTTPレスポンスを、Web Packaging の技術を使って一つのファイルとして返し、ブラウザはそれを個別の HTTPレスポンスとして解釈できるようにするものです。 28. この技術があれば、意味論としてはそのままで、多くのモジュールから構成された JavaScriptファイル群を、実体としては一回のHTTPリクエストで取得できるようにな るというわけです。 29. しかし Web Packaging 関連の技術はこれ以上進むことはないらしく、したがって これらの技術が実用されることはないでしょう。 30. 最後に、ミニファイのステップをどのようにして取り除けるかを考えてみましょう。 31. これは本当に難しい問題です。ミニファイのステップでは、JavaScriptのコードを 解析した上で等価かつ小さいものに変換します。これを汎用的な圧縮技術で実現す るのはおそらく困難でしょう。 32. しかし実は、このような問題を解決するための Binary AST という提案が TC39 に存在しています。Binary AST では、名前のとおり JavaScript の AST を表現でき るバイナリ形式を新しく作成して、通信経路には JavaScript のテキストファイルでは なくそのバイナリデータが流れるようにします。 33. これによって、クライアントがダウンロードするデータのサイズを減らすことがで き、パースの時間も削減することができます。 34. しかしこの提案もほとんど動いていないようです。おそらく、各エンジンでの実装や 標準化が難しかったのだと思います。 35. 以上で、JavaScriptの各ビルドステップをなくすための様々な手法を考えました。 もちろん、この発表を聞いてくれている人の中には、今話した話題について私よりも もっと多くのことを知っている人がいると思います。ぜひ、懇親会などで話しかけてく ださい! ここまでで20分くらい 1. ここまで話して、一つわかったことがありますね。 2. 少なくとも現段階ではほとんどのビルドステップを取り除くことはできないし、少なくと も短期的な未来にはそこまで希望はない、ということです。残念です。
  9. 3. ではここからは、「そもそもJavaScriptをそのままブラウザで動かす必要はあるのか」 について考えていきましょう。 4. 私の考えでは、今のところその必要はないのではないかと考えています。 5. 以前までは、それとは全く逆の考え方をしていました。 6. なぜなら、ビルドステップを構成するソフトウェアの開発は難しく、その開発がサステ ナブルなものではなかったからです。

    7. 以前までは、webpackとBabelやTerserが最も使われているツールだったと思いま す。これらはOpenCollectiveなどでお金が支払われているとは言え、コミュニティの ボランティアによって開発されていました。 8. しかしここ数年間で、ビルドステップを構成するソフトウェアの開発を取り巻く環境が 大きく変わりました。 9. 今ではVercelやByteDanceなどの会社がJavaScriptのビルドステップを構成する ツールに大きく関わっています。 10. もちろん、これらの会社の存続や、開発に対する姿勢を完全に信頼できるわけで はありませんが、以前よりはサステナブルなものになっているのではないでしょうか。 11. 5年後10年後にどういう状況になっているのか非常に楽しみでもあります。 12. 今説明したように、JavaScriptがブラウザでそのまま書けるようになる必要は、少 なくとも今のところ、実用性の観点ではなさそうだとは思っているのですが、私個人と しては「そうなってほしいなあ」とは思っています。 13. というのも、どうしてももったいないと感じてしまうのです。 14. たとえば、ブラウザでのECMAScript Modulesの振る舞いはECMAScriptと HTMLですでに標準化され、多くのブラウザでちゃんと動きます。 15. そのような状況であるにもかかわらず、それらの機能をプロダクションで利用でき ていないのは、HTMLとJavaScriptのポテンシャルを活かしきれていないように思え て、どうにももったいないと感じてしまうのです。 1. ここまで話を聞いてくれてありがとうございます。 2. 最後にまとめです。 3. 最近流行っているフレームワークでは、プログラマがJavaScriptを直接書かないもの が多いです。 4. その裏側には、いくつかのビルドステップがあります。 5. JavaScriptやWebにいくつかの新しい機能が備わっていれば、それらのビルドス テップを取り除くことができそうです。
  10. 6. しかし、実際にはそれらの技術の多くはまだ実用的とは言えず、短期的には中々厳 しそうです。 7. ここ数年の間で、VercelやByteDanceなどの会社の動きによってビルドステップを構 成するためのソフトウェアの開発を取り巻く環境が変わってきています。 8. したがって、ビルドステップを構成するソフトウェアの開発負荷という観点では、 JavaScriptをブラウザで直接書けるようにする必要はなくなってきていると私は考え ています。

    9. しかし、私としてはもったいないと感じる部分もあります。HTMLやJavaScriptのポテ ンシャルを活かすことができていないと感じるからです。 10. 私の発表はこれで以上です。人によって色々な感じ方がある内容だったと思いま す。もっと議論したい人は懇親会でぜひ話しかけてください!また、ユビーのブース にもおりますので、声をかけてください!