どうもおはようございます、zenncastパーソナリティのマイクです。
2026年3月4日、水曜日の朝7時を回りました。みなさんいかがお過ごしでしょうか。
このzenncastでは、エンジニア向けナレッジ共有サービス「Zenn」で、いま話題になっているトレンド記事をピックアップしてご紹介していきます。
今日はお便りはお休みなので、そのぶんガッツリ記事を追いかけていきましょう。
さて、本日ご紹介する記事は全部で5本です。フロントエンドの宣言的UIから、GitHub Actionsセキュリティ、モノレポのビルド最適化、Macの開発環境構築、そしてNode.jsのDIパターンまで、技術寄りなところを幅広く押さえていきます。
まず1本目。タイトルは「Async React時代の宣言的UI: デバウンスの例」。
Reactの世界でよく言われる「宣言的UI」、言葉としては聞くけど、じゃあ具体的に何が宣言的で、どこからどこまでを指してるの?ってモヤっとしていた人にはかなり刺さる内容です。
記事では、重いリストフィルタ処理を例にとって、「本当にやりたいこと」はあくまで「入力に応じた一覧表示」なのに、従来のデバウンス実装だと、タイマーの開始やクリア、どのタイミングで反映するかといった命令的なロジックをガリガリ書いてしまう、これが宣言的UIの思想から外れがちだよね、という話をしています。
そこでAsync Reactの`useDeferredValue`が登場します。入力値と画面に表示している値の“一致”をあえて崩して、「入力は優先してスムーズに、それ以外の重い処理は後からでいいよ」という“ポリシー”だけを宣言する。あとはReact側が優先度制御や処理の中断をうまくやってくれる。つまり「やりたいこと」を宣言するだけで、パフォーマンス最適化という雑務をフレームワークに丸投げできる、というわけですね。
とはいえ、コンポーネントの切り方やチャンクの分け方など、人間がまだ頑張らないといけない部分も残っていて、「Reactはまだ宣言的UIの理想形に到達しているわけじゃないよ」と、ちゃんと批判的な視点も添えられています。Reactを評価するときは、見た目のJSXだけじゃなくて、「ステート管理や非同期制御まで含めた宣言的UI」という広い文脈で考えよう、というのがこの記事のメッセージです。
React触ってる方はもちろん、「宣言的って何?」を自分の言葉で説明できるようになりたい人にもおすすめの記事でした。
。。.。。.。。.。.
続いて2本目。タイトルは「PRを送るだけでリポジトリを『乗っ取れる』?GitHub Actionsの危ない書き方を実際に検証してみた」。
これは2026年2月に実際に起きた、AIエージェント「hackerbot-claw」によるGitHub Actions悪用キャンペーンを題材に、どんなワークフロー設定が危ないのかを、かなりリアルに検証している記事です。
ポイントになっているのが3つあって、1つ目が、`run`の中で`${{ }}`をそのまま展開してしまう書き方。PRタイトルとかブランチ名に悪意のある文字列を仕込まれると、そのままコマンドインジェクションになってしまうケースですね。
2つ目が`pull_request_target`イベント。これを雑に使うと、攻撃者のPRのコードを、Secrets付き・書き込み権限付きのコンテキストで実行しちゃうことがある。「テスト回すだけだから大丈夫でしょ」と思っていると、そのテストスクリプトの中に仕込まれていてやられます。
3つ目は、AIレビュー用のワークフロー。プロンプトインジェクションでAIに悪さをさせるパターンですね。AIに`git push`させられたら洒落にならないので、実行ユーザーの権限設計が超重要だよ、という話が出てきます。
記事は「こう書くとダメ」というアンチパターンだけじゃなく、「こう直すと良い」というところまでちゃんと押さえていて、`run:`の中ではコンテキストを直接埋め込まず、一回環境変数に落としてからクォートして使う、とか、`pull_request_target`ではPR由来コードは基本実行しない、とか、実務ですぐに取り入れられる指針がまとまっています。
「うちは大手じゃないから狙われないでしょ」と思ってるリポジトリほど狙われやすい、という示唆もあって、`.github/workflows`フォルダを一度もちゃんとレビューしたことがないチームには必読レベルの記事です。
。。.。。.。。.。.
3本目は、フロントエンド基盤寄りのお話。タイトルは「大規模モノレポでVite 8(Rolldown)移行に挑戦中!」。
ナレッジワークさんの巨大モノレポ、25個のnpmパッケージと、11個のNext.jsアプリを抱えた構成で、Vite 7からVite 8 beta、つまりRolldownベースの新世代ビルドに移行していく奮闘記です。
Vite 8では、いままでRollupやesbuildに分散してた内部ツール群が、RolldownとOxcにだいぶ統一されていく流れなんですが、記事のプロジェクト構成だと、すべての`src`配下をエントリポイントに扱う作りになっていて、そのまま移行するとRolldownの自動コード分割が暴れちゃうんですね。distの中身がルートホイストだらけになって、しかもそのあとwebpackで再バンドルする二段構成なので、せっかくの自動分割があまりおいしくないどころか、構造を余計ややこしくしてしまう。
そこで出てくるのが`preserveModules`と`preserveModulesRoot: 'src'`。これを使って、ソースのディレクトリ構造をできるだけ保ったまま出力しつつ、globで全ファイルをinputに指定する、という作戦に切り替えています。これでファイル数が無駄に増えたり、空ファイルが量産されたりする問題が解消できて、Next.js側のバンドルサイズも約5%削減できたそうです。
一方で、開発者が一番体感したい「ビルド待ち時間」は、型定義生成プラグイン(`vite:dts`)がボトルネックになっていて、あまり変わらなかったというオチも正直に書かれてます。CPU時間としては13%くらい良くなっているので、将来的に型定義周りを改善できれば、もっと効いてくるかもしれませんね。
ヘルパー関数を共有しやすくなったり、import/exportの可読性が上がったりと、地味に効くメリットも語られていて、「Vite 8いきなり本番導入どうしよう…」と悩んでいるモノレポ勢には、実測値とともにかなり参考になる事例になっています。
。。.。。.。。.。.
4本目はちょっと雰囲気が変わって、開発環境お引越し系の記事。タイトルは「初めてのMac環境構築。モダンな次世代ツール群でターミナルを染め上げた話」。
壊れてしまったWindowsマシンから、M4 MacBook Airに移行した筆者が、「せっかくだから今っぽいツールだけで環境を組み直してみた」という実録です。
WindowsからMacに来ると、まず最初にぶつかるのがキーボードとウィンドウ操作。CtrlとCommandの違いとか、Windowsのスナップみたいなレイアウトが標準ではできないとか、あの辺でストレスたまるんですよね。そこをRectangleとRaycastで補完して、キーボード主体の操作性を確保しています。
ターミナル周りはかなりモダン寄りで、ターミナルエミュレータにGhostty、シェルはfishにStarshipを組み合わせて、さらにZellijでペイン管理。Rust製の`eza`、`bat`、`zoxide`、`bottom`あたりで、昔ながらのlsやcatを一気に置き換えていきます。
エディタはZedをメインに据えつつ、ターミナルの中ではLazyVimを動かして、テーマも透過させて統一感を出すというこだわりぶり。
バージョン管理ツールはmiseに集約して、Dockerの代わりには軽量なOrbStackを採用。ブラウザはArc、メモはObsidianと、GUIアプリも今っぽいラインナップで固めています。
最終的に、設定はdotfilesとGNU Stow、それからBrewfileで一元管理して、マシンを変えてもコマンド一発で同じ環境を再現できるようにしているのが秀逸でした。
記事の最後には、Windowsから来た人向けに「このショートカットはMacだとこれ」という対応表もあって、今年からMacに乗り換えたばかりのエンジニアにはかなりありがたい内容になっています。
。。.。。.。。.。.
そして5本目。タイトルは「Contextを引数でバケツリレーするのはもう辞めよう」。
Node.jsやTypeScriptで開発していると、リクエストIDとかDB接続、ロガー、ユーザー情報みたいな「どこからでも欲しい共通情報」を、関数の引数で回し続けてしまう「バケツリレー問題」、心当たりある人多いと思います。
この記事では、その問題を解決するために、Node.jsのAsyncLocalStorageをラップしたDIライブラリ、`@praha/diva`を紹介しています。
`createContext`という関数でコンテキストを定義すると、ResolverとProviderが生成されて、以降は関数の引数にいちいち渡さなくても、必要な場所から直接その依存関係にアクセスできるようになる、という仕組みです。
面白いのが、スコープの概念が2種類用意されているところで、キャッシュされるものと、呼ぶたびに新しく生成されるTransientなものを使い分けられる。さらにコンテキストをネストしたり、`withContexts`で複数コンテキストをまとめて扱ったり、`mockContext`でテスト用のモックに差し替えたりと、実務で欲しくなる機能がコンパクトにまとまっています。
内部実装も軽く触れられていて、AsyncLocalStorageを拡張したStackStorageでネストされたスコープを扱ったり、Disposableパターンで値のライフサイクルを安全に管理したりと、仕組みを理解したい人にも読めるようになっています。
InversifyJSのようなフル機能のDIコンテナよりも、「必要なところだけサッと使える、型安全で軽量な選択肢」として設計されているので、「バケツリレーつらいけど、でっかいDIフレームワークを入れるのもなぁ」というチームには、ちょうど良いバランスのソリューションになっていそうです。
。。.。。.。.
というわけで、きょうのzenncastでは、
Async React時代の宣言的UIの考え方、
GitHub Actionsの危ない書き方とその対策、
大規模モノレポでのVite 8(Rolldown)移行の現場レポート、
次世代ツールで固めたMac開発環境構築、
そしてAsyncLocalStorageベースのDIでバケツリレーをやめよう、
この5本を駆け足でご紹介しました。
気になった記事があれば、ぜひショーノートから元の記事もチェックしてみてください。ここでは触れきれなかったコード例や細かい設定の話もたくさん載っています。
番組の感想や、「こんなテーマを取り上げてほしい」といったリクエストも、お便りフォームからいつでもお待ちしています。みなさんのフィードバックが、このzenncastをより面白くしてくれます。
それでは、きょうも良い一日をお過ごしください。
お相手はマイクでした。また次回のzenncastでお会いしましょう。