私の現在のスタック

AGIに仕事を奪われたい
この記事は約49分で読めます。

28,894 文字

My current stack
My channel started with the T3 stack, but since then things have changed. I wanted to go over all the stuff I'm currentl...

私のテックスタックは私にとって非常に重要なものです。長くこの界隈にいる方なら、初期のことを覚えているでしょう。このチャンネル全体はT3スタックを中心に始まりました。T3がまだ私ではなく、私のスタックだった頃のことです。Tailwindが作られる前から、私はt3.ggというドメインを持っていました。なぜならT3は私を表していて、Tの後に3文字あるからです。しかし、元のT3スタックを公開してから多くのことが変わりました。さまざまなソリューションを検討し、私のスタックの多くの部分を変更しましたが、以前に好きだったものの一部にも戻りました。
2023年初頭以来、私のスタックがどのようなものかについて適切な更新をしていません。実は去年このビデオを撮影したのですが、カレンダーの予定がどんどん後ろに押されて、今公開するには古すぎると感じるほどになってしまいました。そこで代わりに、現在使用しているものと、より重要なのは、なぜ私が使っているものの一部を、その過程で発狂したくない人には推奨しないのかについて説明します。
私のスタックは現在少し混沌としていますが、これまで以上に、優れた本番環境対応の型安全なTypeScriptアプリケーションを構築するために学べることがたくさんあると思います。しかし、これらのものを維持するためには費用を支払う必要があるので、詳細に入る前に今日のスポンサーからの短いメッセージを聞きましょう。
私のチームはこれまで以上に多くのプルリクエストを出しています。おそらくこれらの素晴らしいAIツールのおかげでしょう。ただし、それはCIの待ち時間が以前より長くなっていることも意味し、私はそれにうんざりしています。もしCIを1行のコード変更だけで2倍速くする方法があると言ったら、私は正気ではないように聞こえるでしょう。理解できますが、聞いてください。blacksmithがすごいんです。アクションランナーに1行変更するだけで、はるかに高速なビルドとはるかに優れた価格を得られます。ClerkのようなたくさんのCompanyがすでに本番ビルドにblacksmithを使用しています。彼らはビルドを非常に高速にするためにクレイジーなことをしています。
面白いハックの一つは、ゲーミングPCのようなゲーミングCPUを使用していることです。単一スレッドのパフォーマンスが大幅に向上するため、多くの単一スレッド作業を含む大規模なビルドを行う際に非常に便利です。また、キャッシュをCI Boxの直接隣に配置するため、キャッシングも大幅に高速化しています。GitHubがこれを行わないのは不思議ですが、彼らにとって大いに役立っています。また、GitHubから通常得られる10ギガバイトのキャッシュではなく、25ギガバイトのキャッシュを提供していることも助けになっています。
その速度向上がどれほどのものか気になる場合、100Mbpsから400Mbps以上になります。既にほぼすべての言語用のランナーを構築しています。Go、Rails、Rust、Python、JavaScriptなど、ほぼ確実にカバーされています。そして、月に3,000分の無料利用があり、クレジットカードの追加も必要ありません。サインアップして試すのが非常に簡単です。本日のビデオのスポンサーであるblacksmithに感謝します。ink.blacksmithでチェックしてください。
ここに最近最も決断を下した2つのアプリケーションがあります。2つの間には多くの重複がありますが、多くの違いもあります。古い方のアプリのスタックの方が私は満足していますが、もう一方のスタックが解決する特定の問題もあります。これらはpick thingとT3 chatです。
これを従来の方法で分析すると、ほとんどの人が気にするカテゴリーがいくつかあります。フロントエンドフレームワーク、スタイルシステム、ステート管理、APIシステムライブラリ、バックエンドフレームワーク、バックエンド言語、データベース、方言と呼ぶもの、データベースプロバイダー、ホスティングプロバイダーなどです。これらのカテゴリーはたくさんあり、十分長く業界にいれば、ほとんどの場合で私が何をしているか推測できるでしょう。
React、Tailwind、shadcn。ステート管理はより複雑なものです。APIシステムライブラリもより複雑です。バックエンドフレームワークは通常Next、バックエンド言語はTypeScript、データベース方言は後で触れます。データベースプロバイダーについても詳しく説明します。ホスティングプロバイダーはVercel、Cloudflare、NFIなどです。
これが簡単な要約ですが、詳細はこれからもっとカオスになります。ルーターなど、ここに含まれていない部分もあります。他にも見つかるかもしれません。認証(Auth)も重要なものです。ありがとう、チャット。パッケージマネージャーも。現代のフロントエンドスタックには多くの部分があり、私が使っているものをコピーペーストしても正しいソリューションにはなりません。
認証プロバイダーが必要ないものを構築しているかもしれませんし、データベースが単に認証プロバイダーであるものを構築しているかもしれません。ステート管理が必要ない、バニラReactやサーバーコンポーネントで十分なものを構築しているかもしれません。必要な場合も、そうでない場合もある多くの異なる要素があります。
そのため、私のコミュニティは元々create T3 appを構築しました。人々が私の使っているものすべてのテンプレートとその使い方を公開してほしいと望んでいたからです。しかし、そうすると必要のないものやツールをインストールすることになります。そこで、もし時間があれば、私が推奨する方法でNext.jsアプリをスキャフォールディングするCLIを構築することを提案しました。しかし私はそれをしませんでした。その代わり、コミュニティのNexelが、CJとJuliusの助けを借りて構築しました。私はこのプロジェクトにコードを全く寄稿していませんが、素晴らしいものです。そして今でも、Nextの機能の簡単なデモをする場合以外は、ほとんどのNext.jsアプリケーションをこの方法で始めています。
create T3 appでは、セットアップ時に各部分を選択できます。新しいプロジェクトを作成すると、pnpm create T3 app@latestとし、名前を付け、TypeScriptかJavaScriptかを選びます(実際に有効な答えは一つだけです)。Tailwindを使うかどうか、trpcを使うかどうか(これは非常に重要な部分で後で触れます)、Next Authを使うかどうかを選択します。データベースORMについては、なし、Prisma、またはDrizzleから選べます。App Routerを使うこともできます(現在は強く推奨します)。そして、どのSQLダイアレクトを使いたいかを選びます。
このようにすべてを設定してくれますが、モジュール式の部分です。すべてを強制するのではなく、オプションを提供し、必要に応じて一つのオプションを別のものに交換できます。それがスタックの要点だと思います。だからこそ私はそれを構築しました。シンプルさ、モジュール性、フルスタックの型安全性。
テンプレートは私が作ったものではありませんが、スタックは私が考案し、この業界が既にこの方向に進み始めていた時点でこのモジュール性を本当に推進しました。しかし当時のマインドシェアはまだレールズの方法、つまりすべてがフレームワークの一部として提供される一つのソリューションに傾いていました。私は異なる問題に対する最良のソリューションと、不要な部分を捨てる能力を持ちたかったのです。このスタックは、当時は可能だと気づかなかった方法でそれを実現する助けになりました。
驚くべきことに、このスタックは現在私が使用しているスタックと非常に似ています。各部分を見ていきましょう。pick thingから始めます。少なくともコアアプリ部分は、おそらく人々が使うべきものと比較的似ています。全体的にこのスタックに非常に満足しています。BenDavis(私のチャンネルマネージャーで、Svelte好きの仲間YouTuber)もこのコードベースの手伝いをしましたが、このプロジェクトのセットアップ方法が非常に良かったため、Svelteエコシステムに部分的にコピーしようとしていますが、大変な思いをしています。
ここの依存関係を見るだけで、何をしているかについての多くの情報を得ることができます。おそらくほとんどの必要な情報はそこから得られますが、これらの使い方は十分に興味深いので、すべてを詳しく見ていきましょう。
おそらく最も良い出発点はフロントエンドフレームワークです。現在では、Reactを使用していないものを構築することはめったにありません。とは言え、これまでで最大のnon-Reactプロジェクトの一つを出荷したばかりです。unduckというプロジェクトは非常にミニマルであることを意図しています。package.jsonを見ると、依存関係がたくさん入っています。Vite plugin pwaがあります(実際にはこれはdevDependencyに移動する必要があります、怠け者なので)。
コードを見ると、さらに複雑に見えるかもしれませんが、基本的にはバニラTypeScriptで、HTMLはこのインライン関数によって書かれています。検索パラメータを渡さない場合、このプロジェクトにはフロントエンドライブラリはありません。これは非常に迅速に投げ込まれたHTMLスニペットです。
プロジェクトが複雑なUIや、これらのクールなツールとソリューションを必要としない場合、私はそれらをすべて捨てることを喜んでします。私がReactを選ぶのは、すべてがReactであるべきだと思っているからでも、自分のUIを構築するのが面倒だからでもありません。複雑なUIは複雑なUIを構築するためのライブラリから恩恵を受けるからです。そして良かれ悪かれ、現在構築されているUIのほとんどはある程度複雑です。unduckのような非常に単純なものにはライブラリは必要ありませんが、pick thingのように本質的にはるかに複雑なものはライブラリから大いに恩恵を受けます。
それでは、これらの動的な動作とそのためのすべての層を実際にどのように構築するかについて話しましょう。ルートレイアウトから始めると、認証を持つ私のアプリのほとんどで最初に見えるのはclerkです。Next.jsアプリケーションに認証を追加する最も簡単な方法だと思います。サインインのための小さなボタン、ユーザーデータを保存する実際の場所、データベース全体を占有しない、処理して維持する必要のないもの、追加したいさまざまな認証プロバイダーですべてをセットアップする必要がないなど、すべての良い点があります。始めるのがはるかに簡単で、アプリが一般公開するのに十分な段階に達した場合、そのハードルを超えるのも比較的簡単です。
しかし、clerkが意味をなさない場合もあります。後で触れますが、一部のプロジェクトではclerkを使用していません。一方では非常に良かったですが、他方では非常に苦痛でした。大部分においてClerkは本当に素晴らしく、それがない場合は本当に恋しく思います。
分析については、このプロジェクトで何を使用したか覚えていません…あ、これはversel analyticsコンポーネントです。これがどうやってそこに入ったか覚えていません…「for now from me 6 months ago」とあります。それで入ったんですね。またgitプラグインに所有されています。通常はアンインストールしていて、おそらくこの後にそうするでしょう。
私が実際に気にしている分析はpost hogです。一般的に言って、私が構築したプロジェクトをどれだけ気にしているかを知りたければ、post hogをセットアップしているかどうかをチェックしてください。post hogをセットアップしている場合、おそらくそのプロジェクトを気にしています。post hogをセットアップしていない場合、おそらく気にしていません。
post hogは、私が仕事をするのが大好きな素晴らしい分析プロバイダーです。他の分析プロバイダーについて話したくないので、彼らを初めてのスポンサーにするよう強引に説得しました。他の分析プロバイダーはあまり好きではなく、post hogが本当に好きなので、すべてに使用しています。これは広告ではありません、彼らはこれに対して支払っていません。このビデオの広告になるよう頼まれるかもしれませんが、これは単に私の実際の考えなので断るでしょう。彼らが私をスポンサーする何年も前からpost hogを使用していましたし、これからも使い続けるでしょう。製品の分析をするには本当に良い方法です。
私が気にするものはすべてpost hogを使用しています。基本的な数字だけが欲しくて全く気にしないものはplausibleを使うかもしれませんが、最近はplausibleからpost hogへとますます移行しています。なぜなら、ユーザー固有のデータが必要だからです。plausibleは非常に匿名の一般的なウェブトラッキング分析ですが、プロダクト分析はありません。これは別のものです。
将来的にこれについて全体のビデオを作るべきかもしれませんが、ウェブページビュー分析とプロダクト分析は非常に異なります。どのページに人々が行くかを知るのは良いことですが、特定のユーザーが何回画像をアップロードしたかを知る方がはるかに良いことです。それは完全に異なる製品です。最初はGoogle Analyticsのようなもの、つまりGoogleの一般的な分析製品です。post hogは、ユーザーが実際に行っていることに対する深い製品分析ができるMix PanelやAmplitudeのようなものにより近いです。
50枚以上の画像をアップロードしたユーザーが何人いるかを知りたい場合、Google AnalyticsやPlausibleからは決して得られません。私のアプリケーションはますますユーザー固有になっているので、そのためにより多くのものが必要です。
また、QuickPicのようなものもあります。これは画像を素早くフォーマットするための私のサービスです。QuickPicにはPlausibleを設定したと思います。これはブラウザ内アプリで、ローンチ以来ほとんど維持していないものですが、当時私を悩ませていた画像管理の問題をいくつか解決するための素早い方法です。QuickPicは本当のサービスではなく、特定の問題を解決するために構築した簡単な画像管理ツールです。一方、pick thingは、コンテンツクリエイターとしてあなたの資産を管理するための実際の本番サービスです。
QuickPicは多くのことに使っていますが、pick thingは私のビジネスを運営する上で非常に重要です。私の中に私が登場するすべてのサムネイルは、quickpiからの資産の一つを使用しています。
ここから、元々持っていなかったが後で追加して生活が大幅に良くなったものが見えます。trpcです。私は同じ間違いを繰り返し、動的なアプリケーションがサーバーコンポーネントでやっていけると自分自身を騙していますが、できません。いつもtrpcが必要ないことを願っています。構築しているアプリが十分にシンプルでtrpcが必要なければいいのですが、時にはそうではありません。
例えばmarker thingを見てみましょう。これは私がよく使うプロジェクトの一つです。marker thingは、私のストリームのすべてのマーカーを管理する方法です。8時間のストリームを個々のトピックに分割して、チームが全体をダウンロードして自分でカットする必要なく編集を始められるようにします。
marker thingの面白いところは、データベースがなく、実際のデータアクセス層が少し滑稽なほど単純なことです。コードを見てみると、チャンネルページがあります。当時重要だったので、エッジで実行しています。これはかなり古いコードです。ページが毎回動的であることを確認するために、Dynamicを強制しています。
面白いのは、このasyncコンポーネントをマウントして、認証情報を取得し、その認証情報を使用してTwitchの資格情報を取得し、TwitchユーザーIDを取得して、APIコールを実行してすべての正しいフォッズを持つそのページを生成できることです。非常にクールで、これにはデータベースが全く必要ありません。marker thingという製品全体にはデータベースがありません。clerkから取得した資格情報を使用してTwitchからデータを取得しているだけです。素晴らしく、このコードベースをはるかに単純にしました。
面白いことに、このプロジェクトを以前に2回構築していて、他の人と共有することに自信のあるものを作りたかったので、Markと一緒に座って素早く再構築しました。1日半ほどかかりましたが、はるかに保守しやすく、はるかに苦痛の少ないものを構築しました。必要のないすべての部分を捨てることでそれを実現しました。
毎日使用するサービスで、比較的データ重視のこのサービスにデータベースがないことは本当にクレイジーです。このツールで構築したものと、Reactパターンがうまく機能していることが大好きです。
ここでコードの古さもわかります。これは2年前のコードベースです。神よ、それは痛いです。私は急速に年をとっています。サーバーコンポーネントが最初に登場したとき、JSXは非同期関数呼び出しをサポートしていなかったため、非同期コンポーネントを呼び出す前にTS expect errorを付ける必要がありました。このコードベースがどれだけ古いかがわかります。愛らしいですが痛いです。
このプロジェクトはサーバーコンポーネント全開でした。多くの利点がありました。ここでの動作は動的ではありません。ストリームが終わればそれでおしまいで、コンテンツはその時点で静的です。そのため、クライアントとサーバー間の往復がたくさん必要なく、サーバーに戻る良い方法がなくても実際には何も失いませんでした。
これは実際に私が持っている最もシンプルなコードベースの一つです。信じられないなら、オープンソースなので見ることができます。このプロジェクトが大好きで、可能な限りシンプルに保つことと、clerkのようなサービスを活用して多くの作業を避けることの良い例だと思います。
以前の試みでは、自分でTwitchの認証を行い、すべてのものをデータベースに適切に保存し、それをすべて管理していました。新しいバージョンは滑稽なほど単純です。全体で1,200行のコードで、そのほとんどはTwitch APIからのデータを再フォーマットし、そのデータのための型の巨大な山です。それが大好きです。
可能な限りシンプルに保ちましょう。複雑さによって私のスタックを図式化すると、最もシンプルなのはunduckです。unduckには依存関係がなく、できる限りシンプルです。次にmarker thingで、はるかに複雑ですが、実際には複雑ではありません。unduckよりは複雑で、認証などを処理する必要がありますが、レイヤーをトリミングして、はるかに保守しやすいものを作ることができました。
その後はpick thingです。面白いことに、これも同じプロセスを経ました。おそらく4回書き直しました。構築し、使用し、問題があり、コードベースを見て「これには触れたくない」と思い、書き直すというプロセスを数回繰り返しました。出荷したバージョンが本番バージョンであり、滑稽なほど良いものです。
その理由についてはあまり詳しく共有しませんが、それは十分に価値のある情報だからです。それはニッチで価値があるので、無料で提供しません。次にT3 chatがあり、はるかに複雑です。marker thingとunduckの間に大きな複雑さのギャップがあります。marker thingはインタラクティブではなく、unduckにはサーバーがまったくありません。
そして、pick thingはもう一段階複雑になります。これは実際のユーザー情報とデータを持つインタラクティブなサービスで、適切に管理する必要があります。権限、支払いシステムなど、他にも多くのことがあります。T3 chatはさらに大きなギャップがあります。異なるAPIとサービス間でデータを非常にパフォーマンス良く移動させ、クライアント上ですべてを処理する必要があるからです。
そしてupload thingの前にはもう一つのギャップがあります。upload thingはJuliusとMarkが完全に引き継いだため、現時点では自信を持って共有できるコードベースではありません。より複雑である必要があり、この時点でupload thingがどのように機能しているかを完全に理解していれば、私は仕事が良くないでしょう。
unduckとmarker thingのシンプルさについてはかなり十分に説明しました。pick thingに戻りましょう。学ぶべき興味深いことがたくさんあると思います。ダッシュボードのアプリページに行くと、sl.appに行った場合に表示されるページが見えます。sl.appページはpick thingであなたの情報、アップロードしたものが表示されるページです。
サインインしていない場合は/loginにリダイレクトされます。データベースからサブスクリプションを取得し、サブスクライブしていない場合はチェックアウトコンポーネントを返します。サインインしていてサブスクライブしている場合は、画像ページに直接移動します。
ここで元々はサーバーコンポーネントを使用していましたが、考え方を変えました。今はクライアントコンポーネントです。react queryからデータを取得します。実際にはtrpcをreact queryで使用しています。T3 chatのコードベースでこれがどのように機能するかについては大きな変化が見られるでしょう。
この呼び出しは奇妙に見えるかもしれません。useQueryを呼び出していますが、反対側に何も置いていません。これはプリフェッチしているので、後でこれらのものをフェッチして再表示する必要がありません。これをここで行うことで、複数のステップをスキップし、単一のバッチで多くのデータフェッチングを実行できます。とても素晴らしいです。
画像がない場合は、「ページに画像をドラッグ&ドロップして始める」という小さな情報を表示します。そうでなければ実際のコンテンツが表示されます。grouped image gridに移動し、画像を取得し、タグのパラメータを取得し、画像グループをレンダリングします。ここでの複雑なものはあまりありません。
この時点でこのコードベースで最も複雑に近いものは、おそらくデータベースとStripeインテグレーションです。このコードベースに戻って、より保守しやすくするためにまず最初にすることは、Stripe実装とサブスクリプションを削除することでしょう。そのデータを適切にモデル化することが正しいことだと確信していましたが、その後、その考え方の誤りを学びました。
そのプロジェクトは、Stripeをより良く扱う方法が欲しいと気付いた時でした。T3 chatは、最終的に怒りを爆発させて実現しました。アプリに支払いを追加する場合は、これを読んでください。Stripeで非常に多くの苦労を経験し、自分のStripeソリューションがうまく機能していると考えている人の多くに、これを強制的に読ませると、「ああ、多くのことを見逃していた」という結論に達しました。
この時点でも、代替品よりStripeを推奨しています。それらは十分に進化していないので、自信がありません。しかし、Stripeを正しく行うのは簡単ではありません。推奨する核心は、Stripeのデータをなんらかの形のKVに同期することです。リレーショナルデータベースには同期しないでください。メインDBにそのレベルの複雑さを追加するのではなく、単純なキーバリューストアに入れ、ユーザーのステータスをチェックするものとして使用してください。それにより生活がはるかに楽になります。複雑な支払いシステムを維持するには、これをコピーすることをお勧めします。このコードベースでそうすればよかったと思います。
しかし、残りは比較的シンプルです。ここで興味深いことに気づくかもしれません。SQLite。このプロジェクトは元々Planet Scaleの無料枠でした。十分長くいる方なら、昔Planet Scaleが非常に寛大な無料枠を提供していたことを覚えているかもしれません。1つのデータベースに対して$30/月のプランを無料で提供していました。しかし、無料枠は彼らに多くの費用がかかり、それを使用していた人々は単なるサポートの問題であり、実際には彼らに意味のある利益をもたらさなかったため、彼らはそれを変更しました。彼らは$20/月のデータベースではなく、$6,000/月のデータベースに焦点を当てたかったのです。
IntercomやSquare(Cash App用)、申し訳ありません、Block(Cash App用)、そしてT3 chatのような本当に大規模なものに使われるようになりました。これらについては後で詳しく説明します。しかし、私はPlanet Scaleを使用していた小さなサービスをいくつか持っていました。それらはあまり収益を上げていなかったため、コストを正当化することができませんでした。好奇心と他のものを試す意欲から、このプロジェクトにTursoを試してみました。
最初はかなり感心しましたが、その後Tursoのカオスが徐々に展開するのを見ました。Tursoについてあまり話さず、頻繁に推奨しない理由があります。成功してほしいと願っていた製品の一つですが、毎日自信を失っています。彼らは奇妙なグループです。チャットでも既に人々がそれについて言及しているのが見えます。「私のデータが削除された」。Tursoから私の経歴の中で最も恥ずかしい停止のいくつかを見てきました。
Tursoは、あなたが構築したいものための分散SQLiteデータベースという主なコンセプトを持っていました。彼らは何度も道に迷い、エッジに過度に焦点を当て、そこから離れました。彼らが本当にクールにやっていることは価格設定です。始めるのが非常に安く、使い続けるのも比較的安いです。データベースに月5ドルは本当にクールです。問題は、データベースが明日も存在するかどうか、または正しいデータベースが戻ってくるかどうかさえわからないことです。
以前、ある人がTursoデータベースからデータをクエリしようとしたとき、何も戻ってこなかったという事件がありました。混乱していたので、インスペクタを開いてみると、クレジットカード番号を含む他の人のデータベースにアクセスできていました。当時のTursoの仕組みは、無料枠ではコンピュートが残っておらず、代わりにデータベースをS3に保存し、リクエストがあったときに引き戻すというものでした。彼らのコードにはエラーがあり、時々あなたのS3バックアップではなく、他の人のS3バックアップを引き出すことがありました。これはデータベースについて聞いた中で最も恐ろしいことの一つです。
最近、彼らはAWSに移行し始めました。彼らは当時fly.ioにいたと思いますが、AWSに移行し始め、最近偶然にすべてのAWSユーザーのデータベースを消去してしまいました。データベースが実際にデータを保持することを望む場合は、注意してください。このようなことについて話すのは嫌いですし、Tursoの人たちをけなすのも嫌いですが、彼らとの交流は奇妙すぎるため、この製品への私の信頼はかなり低いです。
チャットからの素晴らしい引用は「Tursoはデータベースに賭けるべきではない別の例ですか?」です。私はそれに賭けましたが、他の人が経験している大きな問題をまだ持っていないことは幸運です。キーワードは「まだ」です。しかし、もうリスクを冒す気はありません。チャンスを取るつもりはありません。
T3 chatを最初に始めたとき、私は非常に異なる道を行きました。T3 chatは最初完全にRedisで始まりました。T3 chatの唯一のデータベースはしばらくの間Redisでした。実際には非常に良かったのですが、人々がクレイジーなスレッドのために数百メガバイトのデータを保存し始めるまでは。その後、pick thingとT3 chatの間に存在するダイバージェンスが生まれました。T3 chatはKVから始まり、具体的にはUpstashのRedisを使用していました。これは実際に素晴らしかったです。Upstashは非常に使いやすく、非常に安く、素晴らしくスケールしました。
ユーザーあたりのストレージ量は手に負えないポイントに達していたので、Planet Scaleに移行し、それ以来非常にスムーズに進んでいます。サービスがPlanet Scaleが提供するスケールと機能の利点が必要なポイントに達したとき、移行します。Planet Scaleで実行している、クレイジーなスループットを持つすべての本番サービスに非常に満足しています。upload thingのようなもの、そしてより重要なのは現在T3 chatのようなものは、Planet Scaleのクレイジーなパフォーマンス特性とスケーラビリティから大いに恩恵を受けています。非常に信頼性が高く、非常に良く、非常に満足しています。
他のソリューションを言いたくはありませんが、ほとんどすべてを試しましたが、ほとんど満足していません。現在私のビデオを提供している2つは実際により良いオプションの中にあります。Prisma Postgresの製品は、現在Postgresを行う方法として推奨するものでしょう。まだデプロイしていませんが、デモで見たすべてのことは本当に良いです。Prismaはデータベースについて知っているので、もし本当にPostgresが欲しい場合、おそらくそちらの方向に行くでしょう。しかし個人的には、最近ほとんどPostgresを使用していません。
もう一つのオプションであるスポンサーは、正直なところ、Convexをもっと使っていなかったことを後悔しています。彼らは素晴らしいです。Convexの代わりにT3 chatの一部をデモで作成しました。Convexの大きな特徴は、彼らがあなたのコンピュートを実行し、あなたのAPIはあなたのインフラではなく彼らのインフラで実行されることです。しかし、それを所有することで、クエリと変異に本当にクールな特性を可能にします。データベースを更新する可能性のあるものはすべて彼らのレイヤーに存在するため、誰かが他の人がクエリしたものに何かを変更すると、それをライブ更新できます。これは非常にクールです。
Convexに感銘を受けており、彼らがローカル同期とキャッシングのストーリーをもう少し解決できれば、T3 chatをConvexに移行する未来が見えるでしょう。そのカオスなローカルレイヤーには十分な部分が欠けているため、自分で構築した同期レイヤーを扱っていますが、Convexは私が最も憧れているものです。
そして、チャットから出てきた多くのものを推奨していないことを再度強調したいと思います。他のソリューションをけなすのに多くの時間を費やしたくありませんが、このビデオを見ているなら、「Xについてはどうですか?」と考えているかもしれません。Xについて考えました。おそらくXで何かを出荷もしました。そして気に入りませんでした。参考にしてください。間違っている可能性はありますが、ほぼすべての他のデータベースの恐ろしいスケーリング特性、奇妙なパフォーマンス特性、そして全体的に信頼性のない経験を見てきて非常に悲しいです。私がスポンサーしてもらったものを含みます。
テーマが形成され始めていることに気づいたかもしれません。これがスタックについての考え方の核心を強調するのに役立つことを願っています。ステップ1: 最も単純で合理的なもので始める。ステップ2: 必要に応じて複雑さを追加する。ステップ3: 定期的にその複雑さが実際に必要かどうかを反省する。可能であれば複雑さを削除して回避することに非常に前向きであること。
marker thingの例に戻ると、そのプロダクトが動作するためには多くのデータをデータベースに保存する必要があると確信していました。しかし、それについてますます考え、エッジケースに対処し続けるうちに、「ああ、基本的には既にTwitch APIに存在するデータの形を変換しているだけだ。それを使えるか?」と気づきました。答えはイエスで、それによって物事がはるかに単純になりました。
それが私がすべてのことでやっていることです。一般的に言って、複雑さは成功とスケールの敵です。実際にスケールするのはシンプルさだけです。だから私はいつもそれを目指し、私のものを見ると、シンプルさを可能な限り維持するためにときどきクレイジーなハックを見つけることがあります。
また、これを指摘せずにはいられません。データベースとしてのGoogleスプレッドシートをシンプルさを保つ方法として言及しているのを見ました。そうではありません。信じてください、私はGoogleスプレッドシートをデータベースとして使いたいと本当に思っています。本当に切実に欲しいです。でも、そのAPIを介して接続するのは運が良ければです。GoogleスプレッドシートのAPIはひどいゴミです。90年代に書かれたように感じます。誰がシートAPIを使って何かをしているのか理解できません。
最初にGoogleスプレッドシートにアクセスするためのユーザー認証を行うか、あなた側でセットアップした1つのシートをハードコードするために、Googleのクラウドスタッフを通じて承認を得るだけでも、実際にはGoogleスプレッドシートをデータベースとして使いたいと思っていますが、事実上不可能です。
面白いことに、最近Will Osmanと一緒にプロジェクトに取り組んでいました。彼は採用ボードを構築したいと考えており、私はUIスタッフをすべて構築せずに彼が編集できる単純なデータベースが欲しかったので、Googleスプレッドシートから始めました。それを認証しようとして2時間後、私のルームメイトでCTOのMarkが来て笑い、「警告したよ、Theo。これをやるな」と言いました。そこで私は降参し、Notionに移行しました。それは実際に本当に素晴らしかったです。NotionのAPIは完全に問題ありません。
つまり、Googleスプレッドシートはシンプルなオプションではありません。それはGoogleスプレッドシートがシンプルではないからではなく、それを使って何かをするためのAPIレイヤーが、少なくとも過去5年間で私が通り抜けようとした中で最も不必要に複雑な山の一つだからです。Googleスプレッドシートをデータベースとして使わないでください。スプレッドシート製品をデータベースとして使うことが恐ろしいからではなく、それにアクセスするためのAPIが特にゴミだからです。シンプルなソリューションではありません。そうであれば良かったのですが、実行可能ではありません。
とにかく、シンプルなことから始め、必要に応じて複雑さを追加し、その複雑さが最初に必要だったかどうかを定期的に反省してください。常に問題について考え直す機会を持ち、特定のものにたくさんのバグを見つけた場合、その解決策を完全に回避する方が良いのか、パッチを当てる方が良いのかの直感を構築することは、何年もかけて磨く必要のあるスキルです。
試すときに両方を試して、時間の経過とともに変更する以外にアドバイスはありません。しかし、パッチと置き換えの間のギャップは、正しいバランスを取るのが本当に難しいことです。AIの時代では、置き換えがこれまで以上に簡単になり、修正よりも置き換えに走りすぎることを恐れています。しかし現在は、根本的に壊れているものをパッチするのに喜んでおり、意味があるときに置き換えることをあまり喜んでいません。だから、この修正は問題ありません。働かないものを削除することにもっと前向きになるのは、業界では良い変化です。
T3 chatについてのビデオでは、データベースでの狂ったような旅について見たかもしれません。私は出荷したよりも多くのコードを削除しました。T3 chatのために構築した3つの完全な同期とデータレイヤーを削除しました。なぜなら、最初から考え直す方が、修正するよりも簡単だったからです。少なくとも、修正しなければならない回数を考えると。
「もし物事を追加していないなら、十分に削除していない」というフレーミングが大好きです。素晴らしいです。
これは混沌とした旅でした。もっと価値を引き出せるか見てみましょう。ステートマネージャーについて話しましょう。スタイルシステムはTailwindとshadcnです。モダンなスタイルソリューションについての私のビデオを見てください。もっと深いトピックです。
ステート管理は複雑なものです。いくつかのものをリストアップし、それらについてあまり話す必要がないことを願っています。役立つものとして、React Query、サーバーコンポーネント、Jotai、Zustand、Legend State、Dexieがあります。これらは私が試してみることを推奨する順序かもしれませんし、そうでないかもしれません。使用しているソリューションがあなたのニーズを満たさなくなったら、1層下に移動します。
私は常にReact Queryを使うべきだと主張しているわけではありませんが、ある意味ではそう言っています。少なくとも、React Queryを含めなかった時はいつも、ある時点で後悔したということです。
チャットからの良い提案がありました。「最初にサーバーコンポーネントから始め、次にReact Query」という順序です。私も通常同じことをしますが、ほとんど毎回React Queryがより良く解決する問題に遭遇します。サーバーコンポーネントとRSCの動作が最小限のケースでは本当に好きです。アプリケーションのコアにサーバーコンポーネントを使用できるなら、あまり怖いことをせずに、ほぼ間違いなくそうすべきです。
私がpagerアプリを構築したとき(T3 chatに新しいモデルがどのように即座に追加されるか不思議に思ったことがありますか?それは私がページングするアプリを構築したからです)、このページングアプリでは、カスタムパスワードと認証で承認された人が「新しいモデルが登場した」と私に伝えることができ、それによって電話がかかってきて警告します。
ページTheoアプリは元々サーバーコンポーネントですべてを行い、実際に非常に素晴らしかったです。KVを持っていますが、それは人々が提出したすべてのモデルを保存するためです。同じものに対して5人が私にページングしないようにするための小さなセクションがあります。しかし、これはすべてサーバーコンポーネントであり、このプロジェクトにはクライアントコードがほとんどありません。これは非常に素晴らしいです。
このアプリは複雑なクライアント側の動作が必要ないからです。基本的なフォームと基本的な送信動作と認証チェック、そして人々が提出したものをリストする方法が必要です。サーバーコンポーネントをシンプルな方法で使用すると、信じられないほどシンプルです。問題は、複雑なことにサーバーコンポーネントを使用すると、すぐにいくつかの狂ったような問題に遭遇する可能性があることです。
私は依然としてサーバーコンポーネントが大好きで、使えない場所ではサーバーコンポーネントが恋しいです。T3 chatでは大いに恋しく思っています。まったく使っていません。
もし使えない場合、React Queryは非同期の処理にとても良い方法です。Reactは非同期処理が苦手ですが、React Queryはそれを改善します。Jotaiは主に「この局所ストレージの値を5箇所で必要としている」場合に使用します。Zustandは「これら5つのものが互いに関連していて、それらをすべて一箇所にまとめたい」場合に使用します。
Zustandは主にPingのようなもの、つまりユーザーデバイスの状態管理など、本当に複雑な相互作用があるものに使用します。ライブビデオコールのためのその使用例はZustandが最適です。
Legend Stateは、主にReact Nativeの世界から生まれた素晴らしく興味深いプロジェクトで、非常に細かく最適化された状態ソリューションであり、優れた同期プリミティブが組み込まれています。まだ非常に初期段階ですが、ますます使用しており、近い将来いくつかのものをそれに移行することを検討しています。
そしてDexie。DexieはInternet Explorer 7がIndexDBのようなものを実際に使用できるようにするために構築されました。IndexDBはひどいAPIで、使用するのが本当に難しいです。Dexieは現在T3 chatのほとんどの基盤となっています。素晴らしいです。彼らのクラウド製品は私を怖がらせ、私たちが持つ問題を実際に解決しませんが、コアDexieライブラリはおそらくIndexDBとデータを保存するためのブラウザ標準のすべてのカオスに対処する最良の方法です。T3 chatに使用しています。必要でない限り推奨しませんが、必要な場合は非常に簡単に推奨できます。クライアント上に10メガバイト以上のデータを保存している場合、おそらくDexieが必要です。
これがステートマネージャーでの立場です。シンプルに始め、必要に応じて複雑さを追加し、常にトリミングしてください。さもなければゆっくりと狂っていくでしょう。
APIシステムとライブラリについて。これまで話したプロジェクトのほとんど、主なものはpick thingとT3 chatですが、最初は両方ともtrpcなしで始まり、結局私がやらかしてtrpcを追加することになりました。それがなかったことを深く後悔しました。trpcは依然として複雑なバックエンド・フロントエンドの関係を扱う唯一の正気な方法であり、結果は信じられないほどです。一緒に作業するのがとても良いです。
これはチャット履歴をデータベースで更新するかどうかを管理するスイッチです。チャット履歴を同期したいかどうかです。use-sync-enabledフックに行くと、興味深いことがわかります。useQuery trpc…待って、trpcのuseQueryを呼び出すのではないですか?何が起こっているのでしょうか?
ここで起こっていることは、trpcでreact queryを呼び出す新しい方法があります。trpcがreact queryをラップする代わりに、react queryが期待するもの、キー、オプション、その他すべての部分を取得し、それを生成してreact queryに渡します。そのため、アプリのすべての部分に同じreact queryインスタンスを使用でき、非常に素晴らしいです。この新しい方法を使った経験に非常に満足しています。今はreact queryとtrpcの間をより頻繁に行き来していますが、それからも多くのクールな利点を得ています。非常に素晴らしいです。
trpcの魔法は、一度セットアップされた後の型安全性とシンプルさですが、この型安全性がどれほど深く統合されているかが魔法です。このコンポーネントはクライアントコンポーネントです。上にuse clientを付けていないかもしれませんが、T3 chatのすべてのコンポーネントは、アーキテクチャの方法によりクライアントコンポーネントです。その点については後で触れます。
getPreferencesをコマンドクリックすると何が起こるか見てください。今、バックエンドtrpcフォルダの、クライアント上で呼び出している正確な関数にいます。それはどれほどクールですか?タイプスクリプトを使ってバックエンドとフロントエンドの間を行き来することは非常に素晴らしいです。2つの間のバインディングで、グラフスキーマの補間も、誰も生成を覚えていない狂ったようなオープンAPIスペックもなく、どこから来ているのか理解できないようなものもなく、変更することを恐れています。バックエンドに行って変更を加えるだけで、フロントエンドがその変更を見ることができます。非常に素晴らしく、やらないたびに後悔することになります。
T3 chatの最初のバージョンではサーバーアクションをかなり使いましたが、それらをすべて削除しました。おそらく最初からtrpcで始めるべきでしたが、いつものように「これは十分にシンプルだからtrpcは必要ない」と自分を説得し、十分にシンプルでなくなった途端、Juliusにコードベースに飛び込んでセットアップしてもらうよう必死に求めることになります。
trpcは依然として複雑なアプリケーションには必須のように感じられます。バックエンドとフロントエンドを同じプロジェクトに保つことができれば、trpcはあなたの生活をはるかに楽にし、そのモノレポ・モノリシックなソリューションにしばらく留まることができるようになります。本当に素晴らしいです。本当に満足しています。サーバーアクションとは異なり、比較的安定しており、意味をなさない奇妙なエッジケースもたくさんありません。地獄を経験しました。いつか多くの話をする予定です。
ルーティングをどのようにアーキテクチャしているか話しましょう。いくつかのステップをスキップしますが、設定したルーティングは魅力的です。Next.jsコードベースであるにもかかわらず、react routerがあることに気付くでしょう。サーバー側でのルーティングをしたくありませんでした。T3 chatを使用する際に、ネットワーク接続がある場所から別の場所に移動するのをブロックしてほしくありませんでした。
では、Next.jsでreact routerをどのように使ったのでしょうか?ハックの山です。必ずしも推奨しません。このプロジェクトのために「nexit」と呼んでいるものから抜け出す過程を探索していますが、その度に、あまりにも多くの書き直しが必要になり、保守性が低く、より複雑になるようなことが起こり、ため息をついてNextに固執しています。このハックがどれほどうまくスケールしているかには驚きました。しかし、お勧めはしません。
ただし、こちらには「なぜこのルートは静的なのか」というものがあります。next/dynamicをインポートしています。このコンポーネントをSSRすると、すべてが壊れるからです。Dynamicは静的用です。このルートを静的にしたいからです。そしてapp関数をエクスポートしています。appはより伝統的なreact routerのクライアント側アプリケーションです。
なぜこれが静的なアプリシェルにあるのか、なぜ単なるキャッチオールルートではないのか?なぜなら、Next.jsではキャッチオールルートは常に動的だからです。URLを知る必要があるため、T3 chatを開くたびに最初のページに移動するたびにサーバーコードを実行していました。それは悪く、愚かでした。
すべてを静的にし、静的なルートにすることでこれを修正しました。キャッチオールルートにした場合、静的ではなくなり、エラーが発生するでしょう。しかし、どのようにしてすべてのページを処理するのでしょうか?もっとハックです。app-shell-rewriteがあります。ソースが/pathであれば、つまり何でもあれば、static-app-shellにリダイレクトします。
しかし、ここに呼び出しを追加する必要がありました。なぜなら、trpcエンドポイントもキャッチオールルートを使用しているからです。Nextの動作方法の面白いところは、configでリライトを行うと、実際のNextルーターのリライトとキャッチオールルートよりも優先されることです。このルーターのルートは、私のconfigによって横取りされていました。trpcを呼び出そうとすると、その静的なHTMLページが返されていました。すべてのtrpcコールにカスタムヘッダーを追加し、そのヘッダーを持つものをnext configでフィルタリングして、このキャッチオールルートによって横取りされないようにする必要がありました。
これをすべてうまく動作させるのにかかった時間を共有することには興味がありません。私と同じ悪い決断をしている人が時間を節約できることを願っています。TanStack Routerを使えばいいのか、Remixを使えばいいのか、他のすべてのものを使えばいいのか?
何か面白いものを見せます。このPRに注目してください。誰がこのPRを作ったのか見てください。これが先月行われたことに注意してください。そしてまだマージされていません。私よりも賢い多くの人々から、この移行は完全に可能で簡単だと約束されてきましたが、これらの人々は現在、これが実際にある程度可能になるようにライブラリに変更を加えています。この時点では、RemixチームとTanStack Teamのどちらが最初に不足している部分を追加できるかのレースです。
Remixとreact routerがクッキーを処理する方法は、まるで90年代に戻ったかのように感じます。一方、TanStackはそれらのことではるかに進んでいますが、私たちのユースケースにうまく適合しない部分が十分あるため、Tannerはシングルページアプリケーションの動作に一生懸命取り組んでいます。また、彼らは長い間基盤としてきたVineを削除するプロセスにあり、コアを取り除こうとしているフレームワークを採用したくはありません。
これらのいずれかが将来的に有力な選択肢になるかもしれませんが、私が次のように言うのはクレイジーに聞こえるかもしれませんが、Nextは他のオプションよりも現時点では安定しています。私の奇妙な改造された使い方でさえも。
だから、他のフレームワークについて尋ねるのをやめてください。あなたよりも深く考えたことがあり、あなたよりも賢い人々によって、そして私よりも賢い人々によって、そして最終的にはそうするでしょう。しかし今のところ、これは本当にうまく機能しています。しかし、このビデオの要点は、あなたが私の正確なスタックをコピーすべきだということではありません。それは、これのようなものを構築しようとする過程であなたを呼び寄せるサイレンへの警告のセットです。
それがルーティングの状況であり、これらすべてを実行可能にするために対処してきた楽しい回避策です。スタックの中で他に価値のあるものはありますか?
ステート管理、APIなどは扱いました。バックエンドフレームワークはまだNextです。無期限にそこにいるでしょう。もっとElixirを使いたいですが、TypeScriptが多くの異なることに便利すぎます。データベース方言とプロバイダーについては説明しました。そこでのホットテイクは、合理的な限りKVを使うことです。
どのデータベースもKVに変換できますが、すべてのKVがDBに変換できるわけではありません。キーバリューストアから始めて、キーバリューストアからSQLに移行するのはそれほど難しくなく、ほぼどの時点でもそれを行うことができ、問題ありません。それを2回やりましたが、始めてからずっと持続可能でした。Upstashの経験も本当に良かったです。彼らは素晴らしく、スケールで本当に速く応答する必要のあるデータを扱うのに非常に簡単な方法です。非常に満足しています。強くお勧めします。可能な場合は使用し、不可能な場合は移行し、シンプルに保ってください。
ルーターについては説明しました。サーバーにはNext、クライアントにはreact router。以前はwowterの大ファンでした。これはreact routerの最小限の代替でした。react routerは現在かなり良い状態にあります。tanStackルーターは素晴らしい状態にあります。もっと使う必要があります。ただ、複雑な検索パラメーターがなく、tanStackのサーバー側部分がない限り、データ読み込みパターンが欲しくありませんでした。
私にとってtanStackルーターは、tanStackの部分が完全に結合されるのを待っているだけで、おそらくそれに全面的に乗る予定です。しかし今のところ、これらはコードを安定させるために使用しているものです。
react routerの使い方で最も面白い部分は、これが新しいreact router構文ではないことです。V4からのreact router構文を使用しています。彼らはV7です。これは2018年にTwitchで使用したのと同じルーター構文です。新しいものは本当にクールに見えます。ファイルベースのルーティングなどは本当に素晴らしそうです。そこに行くときに行きます。今は私の問題ではありません。ルートがURLを持つコンポーネントであり、レンダリングするものであることは非常にシンプルで満足しています。これで満足しています。
最新のものを常に採用していると言う人たちは、私のコードを全く読んでいません。そうではありません。認証セクションの前にこれを言う前に、私が最もよく使用する2つの認証プロバイダーはclerkとopenauth.devです。異なる認証オプションとそれらをいつどのように推奨するかについての長いビデオがあります。
また、エンタープライズ側の利点を見るにつれて、WorkOSにますます傾いています。企業チームがあなたのクレイジーな認証スタッフを自社のITチームを通じてセットアップできるようにしたい場合、管理パネルは私が人生で決してやりたくないことの一つです。別の会社がT3 chatを購入し、OktaやSAMLをセットアップする必要がある場合、それをする必要なく、その時が来たらWorkOSに移行するでしょう。
可能な限りclerkを使用してください。特定のニーズがある場合は、個人的にopenauth.devに満足しています。openauth.devはSSTeaのDaxとクルーによって構築されました。非常にハンズオンで、基本的なことを行い、すべてをまとめる方法を大まかに示します。認証を独自のサービスに分離でき、二度とデータベースに認証を入れたくはありません。データベースは私のデータ用であり、認証用ではありません。認証を外に出しておくことで、生活が大幅に改善されました。
openauth.devを使うと、T3 chatの認証レイヤーは、Cloudflareのワーカー上で実行される20行のコードで、KVデータをCloudflareのワーカーKVに直接書き込んでいます。触れることも、インターフェースも何もしません。openauth.devクライアントを使って呼び出すだけです。本当に素晴らしいです。セットアップに永遠にかかり、例が欠けていたため、後で検証したり、他のランダムなものを修正したりする必要がありましたが、自分で認証を構築することの代償です。それは満足しています。問題ありません。
すべてのリクエスト間で実行されることを期待する認証ソリューションは望んでいませんでした。ローカルファーストのものをブロックしない認証ソリューションが欲しかったのです。T3 chatでは、ユーザーと彼らがしようとしていることの間に存在するものを最小限にしたかったのです。clerkはNext.jsのミドルウェアにあり、すべてのリクエスト間で実行されることで生活をはるかに簡単にします。
リクエスト間で実行される認証レイヤーに全く興味がありませんでした。必要なときに呼び出せる認証レイヤーが欲しかったのです。最もシンプルな認証レイヤーが欲しかったのであり、それが十分柔軟で使用できれば満足でした。全体的に満足しています。
clerkを使用できる場合、おそらくそれを使用することをお勧めします。しかし、特定のニーズ、パフォーマンス特性、願望、その他のカオスがある場合、openauth.devを使うと、私が本当に好む分離を維持できます。全体的にかなり満足しています。
他の認証ライブラリについての意見が欲しい場合、私が現在のすべての認証ソリューションとそれに対する感想を分析したビデオがあれば便利ですね。
パッケージマネージャーについて、最後に簡単なものです。私はpnpmを使用しています。bunはいつか到達するでしょう。ただ、一つのことだけをするソリューションが欲しいのです。pnpmは生活をはるかに良くしてくれました。すべてをローカルにキャッシュし、基本的に適切に動作します。モノレポに関しては、bunはランタイムであり、パッケージマネージャーでもありますが、彼らの焦点は他の多くのことにあります。バンドル、ランタイム、その他多くのものです。
モノレポ管理には多くのものが欠けており、モノレポで使用しようとするたびに地獄に陥り、pnpmに戻っています。将来的にbunをもっと使い始める可能性はありますが、現在のところpnpmは生活をはるかに簡単にしてくれました。
ランタイムを真剣に尋ねるなら、私のランタイムはNode.jsです。私のランタイムはNode.jsのままで、長い間Node.jsでした。これからも長い間そうなるでしょう。Cloudflareはいくつかの非常に特定のことに使用します。例えば、KVの上にある認証ラッパーなどです。あるいはpick thingについては、画像の最適化はすべて異なるサービスを呼び出しています。例えば、この画像の背景を削除したバージョンを生成する場合、背景を削除し、新しいアセットを生成するためにいくつかの異なるAI企業や提供者、APIを使用しています。
それをすべてCloudflareを通じて行っています。なぜなら、これを何度も再構築する中で、状態管理と何が背景を削除したかなどを追跡する問題に対する本当に賢いソリューションを見つけたからです。URLを見てください、少し意味不明です。エディタを開きます。bg.image.engineeringとは?ああ、特に見るものはないようです。気にしないでください。image.engineeringはいつか完成させます。
このプロジェクトは実際には、Cloudflareの上に構築したCDNと画像最適化レイヤーです。そのランタイムの特性は、存在しないイメージをユーザーが要求し、そのものが存在するまでリクエストを人質に取るというスケールと奇妙な待機動作のタイプに非常に便利でした。それはすべての状態を削除する非常に素晴らしい方法でした。
これは私の構築方法のテーマの一つでしょう。状態を削除する方法を見つけたり、データが2つの場所に存在する「分裂脳」を削除したりする方法を見つけるたびに、それを実現するために地の果てまで行きます。データが1つの場所ではなく2つの場所に存在するようにするために、本当に愚かなことをします。データを異なる場所でミラーリングし、変更し、修正し、導出する必要が少ないほど、私は幸せです。
データが2つの場所にあるたびに、少なくとも4つの問題があります。データが存在する追加の場所ごとに、潜在的な問題の表面積が指数関数的に増加します。単一の真実を持つことができればできるほど、生活は良くなりました。私だけがこれを言っているわけではなく、これを実感している唯一の業界でもありません。
面白いことに、昨晩LTのLukeと一緒に過ごしましたが、彼は物事の単一の真実を持つように社内で考え直していることについて話し続けていました。複数の人がいて、異なるプログラムの異なるToDoリスト、異なるカレンダーなどを持つことは会社を燃やしています。単一の真実はあなたの生活をより良くし、どの画像が背景を削除されたかなどを管理するためのカオスは、私が狂いそうになるほどでした。
現在のimage.engineeringの仕組み、より重要なのはpick thingの仕組みは、画像をアップロードすると、結果をレンダリングするまで背景の削除は始まりません。画像をアップロードして、すぐにタブを閉じると、背景は決して削除されません。背景は、このタグがページにマウントされたときに削除され、そのタグがページにマウントされると、画像がCloudflareから取得されます。それが存在する場合はストレージから取り出され、提供されます。存在しない場合は生成され、提供されるとともにストレージに書き込まれます。
これにより、複雑さを大幅に削減でき、このプロジェクトは恥ずかしいものから本当に誇りに思うものになりました。それはすべてCloudflareによるものですが、それはpick thingのコードベースの一部ではなく、別の画像サービスです。
シンプルで状態を持たないものを保つために、ますますマイクロサービスを作っています。openauth.devは基本的に認証レイヤーのための非常にシンプルなマイクロサービスを作る方法であり、image.engineeringで説明したのは、画像が持つ可能性のある異なる状態を管理する複雑さをすべて取り除くためのシンプルなマイクロサービスでした。これらの結果に非常に満足しています。
しかし、マイクロサービスから始め、これらの孤立したものから始めると、間違ったものを選ぶでしょう。モノリスから始め、できるだけシンプルにし、2回目か3回目の構築で「これらのものは独自のサービスになる可能性があった」と気づき、その時点でより簡単なものを作ることができるでしょう。
他に何かありますか?package.jsonで本当に良いものは?ああ、upload thing。私のサービスのほとんどはupload thingを使用しています。ほぼすべてのサービスにはユーザーがものをアップロードできるユースケースがあり、upload thingをセットアップするのは本当に面倒です。このサービスとその現状に満足していますが、同時に、アップロード問題を解決するマイクロサービスを構築できて嬉しいです。存在する必要のないランダムなS3がたくさんあるプロジェクトがありました。
このコードベースのupload thingコードは、その中で最もシンプルなものの一つであり、それらのことについて心配する必要がないのは本当に素晴らしいです。それに比べて、Stripeでは独自の内部マイクロサービスを構築して、誰がサブスクライブしているかなどを管理する必要がありました。
SQLが必要な場合、私のORM選択はdrizzleです。Prismaは急速に追いついており、将来的にはもっと使用することを検討していますが、drizzleは本当に良いです。
もう一つ重要なもの、私のすべてのプロジェクトにあるもの:T3 ENV。これはJuliusが以前に作成したパッケージで、プロジェクト間を行き来したり、他の人と共有したりするときに環境変数を管理することが大変だったからです。何かをデプロイし、環境変数を忘れると、サービスを使用している会社にとっての責任と問題になります。
create T3 appのサポートチケットの半分以上は、デプロイ時に環境変数を忘れた人々でした。t3-envを使うと、プロジェクトで使用するすべての環境変数をスキャフォールディングし、ビルド時にZod検証を与えることができます。これで、プロジェクトをビルドするときに環境変数が不足していると、ビルドに合格せず、特定の不足している変数でエラーになります。クライアントとサーバーを分割することもでき、非常に素晴らしいです。
プロジェクトを異なる開発者や人々の間で渡すときに、生活をはるかに簡単にしてくれます。だからこそ、TannerのようなLが私のコードベースを取得してローカルで実行できたのです。必要な環境変数を簡単に把握できるからです。t3-envに非常に満足しています。これもまた、含めないと後で後悔することになるライブラリの一つです。お勧めします。検討すべきです。
面白いことに、t3-envはcreate T3 appよりも人気があります。なぜなら、他の多くのスタックや場所でも使われているからです。多くの人々がこれを構築してくれてありがとうと言ってくれますが、私はt3-envには何も関与していないので面白いです。Juliusがある日作って、T3のために使ってもいいかと尋ねただけです。環境変数を処理する最良の方法の一つとして強くお勧めします。env.t3.ggで詳細を確認できます。複数の人があなたのプロジェクトで作業している場合は、ぜひ試してください。そうでなければ、少なくともprocess.envを手動で検証していることを確認してください。そうしないと地獄に陥るでしょう。
ほとんどすべてを説明したと思います。私のスタックは少しカオスで、そうでないふりはしません。また、私のスタックはこれまで以上にプロジェクト間で非常に異なります。ほとんど常にTypeScriptを使用し、通常はReactを使用し、できればtrpcを使用し、しばしばRSCを使用しています。Reactを使用している場合はReact Queryも使用しています。
これを描く理由は、構築しているものの必要性や抱えている問題が痛いほど大きくなるにつれて、円が拡大するような感じだからです。しかし、私は常に最もシンプルなことから始めようとします。ほとんどの場合、それはTypeScriptになります。
私のアプリがより複雑になるにつれて、あるパーツを別のものに交換するのではなく、パーツを追加し、シンプルなものやカスタムものを減らして、より正しいソリューションを使うようになります。問題がより痛いほどです。
KVからSQLへの移行は、プロジェクト内のすべてのKV呼び出しを削除することではありませんでした。T3 chatでは依然としてKVを多用しています。レート制限機能がUpstashを通じてRedisから離れる未来は見えませんし、Stripeサブスクリプション管理がUpstashを通じてRedisから離れる未来も見えません。しかし、実際のものの設定やカオスなメッセージ履歴など、実際のデータ管理には、SQLデータベースを持つことが理にかなっています。
一般的に言って、問題を解決する最もシンプルなことから始める限り、より複雑なものに移行するのはそれほど悪くありません。しかし、複雑なものからシンプルなものに移行するのは、もはや移行ではなく、書き直しです。KVを使うべきときにSQLから始めた場合、書き直しです。KVから始めてSQLに移行する場合、良い手にあります。Material UIから始めてTailwindに移行する場合、書き直しです。Tailwindから始めてshadcnに移行する場合、新しいコンポーネントを追加するだけです。
これらのシンプルな部分から始め、それらがあなたが解こうとしているパズルを解決しない場合は、実際に解決する可能性のあるものを追加します。
ここで話したいことはすべて説明したと思います。質問に答えて、見逃したものがあるかを確認しました。ほとんどの質問は他のビデオで詳しく説明したことについてなので、それほど多くはありません。
最後の質問はサーバーについてです。サーバーをどこに置くか?Vercelはサーバーレスには良いですが、サーバーについてはどうですか?私は長い間サーバーの必要性を避けることに信じられないほど成功してきました。そして、もし実際にサーバーが必要になった場合、それは従来のサーバーを持つことから大きな利益を得る珍しいケースの一つです。
すでに作業をJuliusとMarkに委託しており、彼らはAWSでホスティングしています。そのような厳しいサーバー負荷は、おそらくそこに属しています。しかし、実際のサーバーを立ち上げる頃には、これらの特注のソリューションから離れ、状態を管理し、異なるもの間で同期し、それに伴うすべてのエッジケースを持つカオスな世界に戻ります。
upload thingで過去1年間に経験したほぼすべての障害はサーバーが原因でした。そういうものです。できるだけ良くするために一生懸命取り組んでいますが、サーバーは常に多少面倒です。
他の質問について話すほど気にしていません。これで私の考え方と構築するものについての技術的決断の仕方について良い洞察を得られたと思います。
できるだけ長くシンプルに保ち、必要な場合にのみ複雑さを追加してください。可能な限りものを削除するために遠回りし、削除しすぎて物事を戻す必要がある場合でも、それは問題ありません。
ここで言いたいことはすべて言いました。皆さんの考えを聞かせてください。私のスタックをコピーしますか、それともここからの教訓を受け取り、Laravelに戻って幸せでいますか?教えてください。次回まで、平和を、ナード達。

コメント

タイトルとURLをコピーしました