はじめに

 この本では2021年ぐらいに生まれたライブラリやウェブサービス、主要サービスの機能について紹介します。筆者の実務や興味の範囲でピックアップしているので、漏れはあると思いますが、ご了承ください。参考文献や最後の方には情報収集でよく使うリソースをまとめているので、興味のある方確認してみてください。

 また、内容の正確性に配慮していますが、誤りが含まれている可能性があります。もし、何かの間違いで本書の内容を何かに活用される場合は、参考文献を付けているため、必ず目を通してください。ただ、参考文献が多々説明不足なこともあるので、興味のあるトピックについては実際に試してみることもお勧めします。

本書で扱うこと

 本書では5つのカテゴリーで以下の内容について紹介します。具体的な使い方よりはこれを使うとどういう点で便利か、既存のものとどういう違いがあるのかに焦点を当てて説明します。そのため、独断と偏見で何が嬉しいのか分からないものについては簡素に説明するか全く説明しないためご了承ください。

 本書で扱う各トピックはそれぞれ独立しているため、気になるものから読んでみてください。文章量により入れ替えている部分もありますが、各カテゴリーの最初の方に出てくるものが筆者の推しです (ご参考までに)。

本書で扱わないこと

 なるべくページ数を省くため、本書ではセットアップ方法や詳細な使い方などを省略しています。実際に面白そうと思ったものについては、実際に調べて試してみてください。また以下のトピックについても本書では触れません。

対象読者と前提知識

 新しいものに出会いたい人、2021年の出来事を (適当なフィルタリング通し) 大雑把に把握したい人向けの本です。前提知識の設定が難しいですが、Webエンジニア2年目なら大体理解できるように書いてます (自分比)。難しい概念もなるべく分かりやすく書いてますが、その分厳密性がないので、明らかに間違っている場合はご指摘いただけるとありがたいです。

 あと専門書を読むときもそうだと思いますが、書かれていることが全て正しいとは限りません。疑問に思ったところや矛盾してるのでは?と感じたら、調べてください。そして余力があれば、筆者までご連絡いただけるとありがたいです。

問い合わせ先

 誤植や間違い、その他感想などはGitHubまたはTwitter, メールにてよろしくお願いします。ただし、人にメッセージを返すときはかなり慎重になるので、返事は遅めになります、ご了承ください。また、本書ではわかりやすさ優先のため、エンドポイントやリソース名をマスクせずに表示してます。それらのリソースは削除済みなので、ご連絡不要です。

GitHub: https://github.com/pilefort/tech-dojin.2021.web-change-log

メールアドレス: pilefort2020@gmail.com

Twitter: @pilefort

開発ツール編

port7777

 port7777は必要なときに必要な時間だけ踏み台サーバを起動し、AWSのプライベートなRDSへアクセスするためのプロキシツールです (https://port7777.com)。

 通常、RDSにアクセスするときは踏み台サーバー (Jump Server) を作成し、踏み台サーバー経由でアクセスします。EC2で構築し、SSHキーを利用者のローカルに落として使う方法はよく知られていると思います (https://aws.amazon.com/jp/premiumsupport/knowledge-center/rds-connect-ec2-bastion-host/)。

 port7777を使う場合は踏み台サーバーをECS上のFargateで起動し、7777ポートを使いローカルからFargateへ、そしてFargateからRDSへSSH接続できるようになります。ちなみに、特定のIPアドレスかつ認証されたユーザー以外はローカルからFargateへアクセスできないようになっています。また、Fargate上で作成されたSSHキーもport7777を停止したときに破棄されます。

 port7777でRDSに接続している間はこのようになります。7777コマンドで、所属するAWSで稼働中のRDSを認識し自動接続します。ローカルの7777ポートにTablePlusなどのDB管理ツールを繋げることで、GUIで操作できます。

connect-db
port7777を利用して、TablePlusとRDSを繋ぐ

 具体的なセットアップや必要なAWSの権限などはGitHubのサポートリポジトリ (https://github.com/whilenull/7777-support) に詳細があるので権限を絞って利用できます。

GitHub Dev (VSCode Web) と GitHub Codespaces

 GitHub Dev (VSCode Web) はブラウザ上でVSCodeを起動するためのものです (https://code.visualstudio.com/docs/editor/vscode-web)。iPadなどのタブレット上からでも利用でき、https://vscode.dev/ にアクセスするか、GitHub上で「.」を押すことで利用できます。エディタの状態を解除するためのショートカットは存在しませんが、メニュータブ (≡) のGo To Repositoryをクリックして新しくリポジトリを開き直すことはできます。ショートカット一覧はこちら (https://code.visualstudio.com/shortcuts/keyboard-shortcuts-macos.pdf) です。

vscode-webgithub-dev
VSCode WebGitHub dev

 このツールを利用するメリットはライブラリの中身を見るときにコードジャンプがやりやすいところと、コミットなどもできるので、簡単な修正がやりやすいところだと感じています。他にもWeb対応しているVSCodeの拡張機能も利用できるため、例えば Visual Studio Live Share (https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare) を使って簡単に共同編集したりもできます。

 ターミナルの機能などもWeb上で利用したい場合はGitHub Codespaces (https://github.com/features/codespaces) を利用する必要があります。現状だと、GitHub TeamかGitHub Enterprise Cloudでないと利用できませんが、これを使うことで、Web上で開発やビルドをしたり、VSCodeのほとんどの拡張機能が利用できます (https://code.visualstudio.com/docs/remote/codespaces)。

類似サービス・ツール - Stackblitz

 このようなWeb上でコードを触れるようなサービスは他にも種類があります。1つはStackblitzのWeb Containerです。Web ContainerはStackblitzの造語で以下の機能 (https://github.com/stackblitz/webcontainer-core#key-webcontainer-components) を備えているものです。つまり、ブラウザのセキュリティサンドボックス (ブラウザからOSへのアクセスを制限した環境) で動作する開発環境のことを指しているようです (明確な定義がないので間違っている可能性があります)。

 ブラウザのセキュリティサンドボックスで動作させるため、リモートコンテナを利用するGitHub Codespacesよりも速く動作し、ブラウザ外からのアクセスもできないため、よりセキュアな環境を提供できるようです。こちらで実験できるので、興味のある方は試してみてください (https://stackblitz.com/ , 一部のテンプレートはターミナルが使えないみたいなので注意してください)。ちなみに現在パートナーとの統合を検討しているようで、今勢いのあるVercelやNetlifyと連携できると熱いと感じてます。

stackblitz-editor
Stackblitzの画面

類似サービス - github1s, JetBrains Fleet, Coder

 GitHub devが公開される前に出ていたサービスとしてgithub1sがあります。こちらは「github.com」の部分を「github1s.com」に書き換えることでリポジトリをVSCodeで表示できるサービスです (https://github.com/conwnet/github1s)。remote-containersというVSCodeのプラグインとGitpodsを使ってホストすることでリモート開発環境が作れるみたいです。詳しくはREADMEに記載されています。

github1s
github1sの画面

 JetBrainsの方もJetBrains Fleetというエディタでリモート開発ができる機能を開発中です (https://www.jetbrains.com/fleet/)。Waiting Listには追加してるのですが、まだ招待メールが届いてないので、詳細不明です。その他にもCoderというサービス (https://coder.com/) も出てきており、今後もリモート開発環境を支援するサービスやツールが増えてきそうな気配を感じます。

サービス編

PlanetScale

 PlanetScaleはMySQL 8.0を利用できるサーバレスデータベースサービスです (https://planetscale.com/)。YouTubeのデータベース基盤として使われているVitess (https://github.com/vitessio/vitess) を使用しており、ノンブロッキングスキーマ変更が可能です。つまり、データベースのブロックやテーブルのロックが発生せずにスキーマ変更ができます (https://docs.planetscale.com/concepts/planetscale-workflow#non-blocking-schema-changes)。その他にもブランチ機能があり、本番のデータベースをコピーして実験したり、開発と本番でDBを分けることもできます。また、コネクションプールも組み込まれており、DBの接続制限なども意識しなくて良くなってます。リリースされて間もないサービスですが、日本リージョンも用意されてます。

branch
PlanetScaleでのBranches画面

 クエリの実行やスキーマの確認も簡単にできます。ちなみに、本番環境に指定したブランチはコンソールアクセスがデフォルトで不可になります。

consoleschema
クエリ実行スキーマの確認

 PlanetScaleが提供するCLIもあり、こちらを利用することでローカルでのDB操作もできるようになります (TablePlusなどのDBツールとの連携も可能です)。Rails (https://docs.planetscale.com/tutorials/connect-rails-app) や Prisma (https://docs.planetscale.com/tutorials/prisma-data-platform-integration) と連携するチュートリアルも用意されています。ちなみに、prisma側でもPlanetScale連携をサポートする予定みたいです (https://github.com/prisma/prisma/issues/7292)。

cliconnect-db
pscaleが実行できるコマンドTablePlusとの接続

Render

 Renderは2021年の初め頃にリリースされたWebアプリを簡単にデプロイするためのサービスです (https://render.com/)。似たようなサービスとしてHerokuやRailwayなどがありますが、こちらはDockerfileを認識して環境を作成してくれます。ちなみに、HerokuでDockerfileを認識させるにはheroku.ymlの修正が必要です (https://devcenter.heroku.com/articles/build-docker-images-heroku-yml) がRenderはデプロイ時の設定でDockerfileを選択できます。

 Webアプリだけでなく、静的サイトやcron job, DBなども作成できます。DBについてはPostgreSQLだけでなく、MongoDBやMySQLもRenderが用意しているリポジトリ (https://github.com/render-examples/mysql) を使って作成できます。その他にもRedisやSidekiqなどもRenderのリポジトリにDockerfileや設定ファイルのサンプルがあり利用できます。

create-select
Renderでホストできるもの

 アプリを作成すると、以下のようなダッシュボードが表示されます。一部有料機能もありますが、アプリのデプロイ状況の確認、環境変数の設定、PRごとにURL生成、DockerfileのCMDの上書きなどは無料でできます (Shellの利用は有料枠です)。

render-dashboard
Renderのダッシュボード

 PRごとのURL生成では、以下のようにコミットを追加するたびにRenderのURLが発行され、変更を確認できる機能です。バックエンド側でこれができるのは面白い点だと思います。Herokuにも似たような機能 (https://devcenter.heroku.com/articles/github-integration-review-apps) が追加されましたが、Renderではワンクリックで有効にできます。

 東京リージョンはまだありませんが、ロードマップ (https://feedback.render.com/) を見る限り対応中のようです。他にも今後追加される機能などもロードマップで確認できます。

preview
PRごとのURL生成

類似サービス - Railway

 2020年の12月ぐらいにRailwayというサービスも出てきました (https://railway.app/changelog/2021-12-31)。こちらはHerokuと同じBuildpack (https://devcenter.heroku.com/ja/articles/buildpacks) を使ってゼロコンフィグでアプリの動作環境を構築してくれます。ただし、Dockerfileがある場合はそちらを優先してビルドしてくれます。

 こちらのサービスはプラグインとして、MySQLやPostgreSQL, Redis, MongoDBを後から追加することができます。Renderでは別々のダッシュボードで管理しますが、Railwayでは1つのダッシュボードでアプリとDBを管理できます。ちなみに、ダッシュボードはデフォルトでダークモードで変更できません。

plugindashboard
plugin追加の選択肢Railwayのアプリのダッシュボード

 RailwayもコミットごとにPRを作成できます。また、サーバーサイドはRailwayを使いつつ、フロントはVercelを使うというやり方もできるようです。サンプルアプリも豊富にあります (https://github.com/railwayapp/starters/tree/master/examples)。

generate-urlvercel-connect
コミットごとのURL生成Vercel連携

ライブラリ編

Partytown

 Partytownはリソースを大量消費するスクリプトをWeb Worker (Service Workerなど) に移すことでメインスレッドのブロッキングを防ぐ遅延ロードライブラリです (https://github.com/BuilderIO/partytown)。

 Partytownは以下の目標を掲げています (https://github.com/BuilderIO/partytown/wiki#goals)。つまり、サードパーティーライブラリを従来通りのやり方で使ったり管理しつつ、Web Workerに安全に移行できるものを目指してるようです (解釈違いがあったらすみません)。

 Next.jsで利用する場合は次のようになります。<Partytown />を読み込んだ後に、Web Workerに移行したいライブラリのtypeをtext/partytownと指定して使います (https://github.com/BuilderIO/partytown/wiki/Getting-Started#React)。数ヶ月前に試しましたが、今も同じように書いて動くのか不明なので、試す場合はGetting Startedとissueをよく確認して使ってください。まだPartytownはバージョン0.xの実験段階のライブラリです。

SWR 1.0

 SWRはNext.jsで有名なVercelが提供しているReact Hooksライブラリで、fetchやaxios, graphql-requestなどのデータを返す非同期関数と併用し、フロントで取得したデータを再利用可能な形にできるものです (https://swr.vercel.app/ja)。

 SWRはstale-while-revalidateの頭文字を取って名付けられており、キャッシュからデータを返し (stale)、次にフェッチリクエストを送り (revalidate)、最後に最新のデータを取ってくるというのを基本戦略としています。そのため、キャッシュの扱いやリクエストの実行タイミングに関してよく考えられています。

 SWRは以下のような形式で扱うことができます。まずfetcherとして、SWRと併用したいデータフェッチライブラリの設定をします。次にuseSWRを使って、レスポンス先とfetcherを指定し、その返り値としてdataとerrorを取るようにして使います。リクエストが返るまでの間はdataとerrorはundefinedになり、値が返るとdataに、エラーが返されるとerrorに値が入ります。

 SWRでは以下のようなコンポーネントを作っておくと、他の場所でもリクエスト結果を使い回すことができます。複数のコンポーネントで使うと、使いまわした回数だけリクエストが実行されそうですが、SWRではキャッシュを使い、リクエストを1度だけしか実行しないようです (フェッチリクエストの動きを把握してないため、少し濁して説明してます)。また、デフォルトで「ページにフォーカスが当たる」「タブを切り替える」「ネットワークがオフラインからオンラインに回復する」ときにデータの再検証をしてくれるそうです (https://swr.vercel.app/ja/docs/revalidation)。

 ちなみにデータを再検証するタイミングも制御でき、定期的に実行したい場合はrefreshInterval, ウィンドウが非表示のときにポーリングしたいならrefreshWhenHidden, ネットがオフラインのときにポーリングしたいならrefreshWhenOfflineなどのオプションを付けて制御できるそうです (https://swr.vercel.app/ja/docs/revalidation#%E5%AE%9A%E6%9C%9F%E7%9A%84%E3%81%AA%E5%86%8D%E6%A4%9C%E8%A8%BC)。

 また、useSWRImmutableを使うことで、1度しかリクエスト結果を検証しないように使うこともできます (https://swr.vercel.app/ja/docs/revalidation#%E8%87%AA%E5%8B%95%E5%86%8D%E6%A4%9C%E8%A8%BC%E3%81%AE%E7%84%A1%E5%8A%B9%E5%8C%96)。

 レスポンスでエラーが返ってきたときのデータの再取得方法も指定でき、再試行しないステータスや試行回数、試行間隔なども指定できます (https://swr.vercel.app/ja/docs/error-handling)。

フレームワーク編

Remix

 RemixはCDNのEdge部分でSSRできるReactの新しいフレームワークです (https://remix.run/)。Remixでは以下4つの理念からなる特徴を持っています (https://remix.run/docs/en/v1/pages/philosophy)。

  1. ソースコードとコンテンツ/データの分離を含む、クライアント - サーバーモデルを採用
  2. ブラウザやHTTP, HTMLなどのWebの基盤を活用する
  3. JavaScriptでブラウザの動作をエミュレートし、ユーザー体験を向上させる
  4. 基盤となるテクノロジーを過度に抽象化しない

 まず1つ目ですが、Remixではクライアント-サーバーモデルを採用しているため、クライアント側で完結するSSGをサポートせず、Edge領域でのSSRを活用します。このことにより、動的コンテンツを提供するアプリでも静的サイト並みの速度を提供できるそうです (https://remix.run/docs/en/v1/guides/performance)。

 またRemixではネットワーク送信量を減らす機能が豊富にあります。これはサーバー側は高速化できるが、ユーザーのネットワークは改善しようがないことを認識しているためです。例えば、GitHubのGist APIを単純に使う場合は以下のようになりますが、このように書く場合は不要な情報も含まれるため、送信されるデータ量は多くなります (https://remix.run/docs/en/v1/pages/philosophy#serverclient-model)。

 対してRemixを使う場合はユーザーにデータを送信する前に、loader関数でデータをフィルタリングできるため、以下のように書くことができます。このようにフィルタリングすることで送信するデータ量を少なくできます。

 2つ目として、RemixではWebの標準的な機能を活用するために、独自のリクエスト/レスポンス APIなどを作らず、Fetch APIを活用します。例えば、Fetch APIのHeadersインターフェース (https://developer.mozilla.org/en-US/docs/Web/API/Headers) を使うと、HTTPリクエストやレスポンスヘッダーに応じた処理ができますが、RemixでもloaderHeaders関数として利用できます。また、このようなHTTPヘッダーを各ルート (異なるパス) ごとに作成できるのもRemixの特徴です (https://remix.run/docs/en/v1/api/conventions#headers)。

 ヘッダーだけでなく、metaタグもパスごとに設定できます (https://remix.run/docs/en/v1/api/conventions#meta)。

 3つ目はRemixではユーザー体験を向上させるために、ページ遷移時はレイアウトの変更部分のみデータ取得するように動きます。これはNested Routingという機能が関わってきます。言葉や図で説明するのが難しいので、こちらをみてください (https://remix.run/#:~:text=a%20cheat%20code%3A-,Nested%20Routes.,-%E2%86%91%E2%86%91%E2%86%93%E2%86%93%E2%86%90%E2%86%92%E2%86%90%E2%86%92BA)。頑張って文で説明すると、/invoices/12から/invoices/12/editにページ遷移する場合を考えます。(Suspenseを使う場合は少し変わりますが) Next.jsの場合は遷移先のページで必要なJavaScriptやCSSを取得してからページが変わります。しかし、Remixでは変更先で必要な部分のみ取得して更新し、共通部分はそのまま維持され再描画しません。また、必要な部分のみを取得して更新できる特性から、そのページで必要なコンポーネントを並行してダウンロードできます。ここら辺の技術的な話は理解も説明も難しいため、気になる方はまだ未整理のドキュメント (https://remix.run/docs/en/v1/guides/routing) や他の文献を探してみてください。Remixのこの機能はreact-routerのv6で追加された機能と同じなので、こちらのリポジトリも参考になるかもしれません (https://github.com/remix-run/react-router)。

 4つ目にRemixのAPIは基本的なHTTPやブラウザ, JavaScriptの機能をラップしてますが、過度に抽象化しないように気をつけて作られているようです。(具体的な例をもって説明はできませんが) 汎用性のある技術を学べる点もRemixの良い点だと感じます。

 Remixは他にも以下のような面白い特徴を持っています。

 Next.jsだとページが存在しないときに、ステータスコード 404で404ページを返すにはひと手間必要です (https://github.com/vercel/next.js/issues/4452)。しかし、Remixを使う場合は何も設定しなくても、ページが存在しないときは404のステータスコードと一緒に404ページを返してくれます。

 Nuxt3ではビルド時にデプロイ先を決めたりできますが、Remixではアプリ作成時にデプロイ先を選びます。候補としてはfly.ioやAWS Lambda, Cloudflare Workersなどがあります (https://remix.run/docs/en/v1/guides/deployment)。アプリを作り始めたらすぐにデプロイできるようにこのようにしているらしいです。

 VercelにもChecksというサービスを統合できるようになりましたが、RemixにもMetronomeというWeb Vitalsやアクセス数、発生したエラーの詳細を確認できるサービスがあります (https://metronome.sh/)。Rollbarなどをフロントに入れなくても、エラーの詳細が確認できるなら、ありがたいですが、まだ試してないので、詳細は分かりません。

 Remixにはいくつかサンプルアプリ (https://github.com/remix-run/remix/tree/main/examples) もあるので、興味のある方はぜひ試してみてください。

その他

Pulumi

 Pulumiはインフラ構成をGoやTypeScriptを使って記述できるツールです (https://www.pulumi.com/)。いわゆるIaCで、TerraformやCloudFormationなどと同じものですが、CloudFormationと異なりAWS以外のクラウドサービスでも利用できます。また、Terraformと異なり、独自の言語を使わず、TypeScriptなどで書くことができます。

 例えば、以下のように書くと、src配下のindex.htmlをS3にデプロイして公開できます。

 デプロイ時はこのような画面になります。また、Terraformと同じように、デプロイごとに状態ファイルを作成するため、差分を確認することができます。

pulumi-uploadpulumi-diff
pulumiでデプロイしたときの様子pulumiでの再デプロイ時の様子 (差分が表示される)

 Pulumi自体は前からあるのですが、2021年ではNative Providerという機能が追加されました (https://www.pulumi.com/blog/pulumiup-native-providers/)。これはGCP, Azure, AWSなどで新しいサービスや機能が追加されたときに、その日のうちにPulumiでも利用できるという機能です。すぐ使いたい機能がリリースされたけど、CloudFormationなどが対応してないから手作業でやらないといけない... ということがなくなるリリースで、非常に価値ある機能だと感じています。ちなみに、AWSのNative Provider対応はAWS Cloud Control APIを利用しているようです (https://aws.amazon.com/jp/blogs/aws/announcing-aws-cloud-control-api/)。

Chrome Extension Manifest V3

 2021年にはChrome Extension Manifest V3が正式リリースされました (https://developer.chrome.com/blog/new-in-chrome-88/#mv3)。Manifest V3ではV2の機能を制限することで、セキュリティ的な安全性の向上を図っています。2023年6月にはManifest V2で作られたものは動かなくなるため、それまでに拡張機能の書き換えが必要です (https://developer.chrome.com/docs/extensions/mv3/mv2-sunset/)。Manifest V2とV3の主な違いは以下の点にあります (https://developer.chrome.com/docs/extensions/mv3/intro/mv3-migration/#feature-summary)。 

 大きな変化はサービスワーカーの利用です。DOMへのアクセスが不可になるだけでなく、localStorageへのアクセスもできなくなります。DOMへのアクセスはcontent_script経由で、localStorageは使えないのでStorage APIを使うことで対応できます。

 また、windowオブジェクトへのアクセスもできないため、chrome.windows.create APIでChrome拡張からウィンドウを作ることはできますが、setSelfAsOpenerが指定できなくなってます。つまり、Chrome拡張が開いたウィンドウを閉じるときに、postMessageとchrome.windows.remove APIを併用して書く必要があり、従来と比べてコードが書きづらくなってます。