bun入門 Next.js Learnと一緒に

Next v14 と一緒に新しいチュートリアルが出たみたいなのでやってみる
ついでに気になってたBunも使って一緒にやってみる

Bun は、Node.js のより高速で、より効率的で、より現代的な代替品として設計されています。
BunはNodeの代替らしい
Bun は単なるランタイムではありません。長期的な目標は、パッケージ マネージャー、トランスパイラー、バンドラー、スクリプト ランナー、テスト ランナーなどを含む、JavaScript/TypeScript を使用してアプリを構築するための統合されたインフラストラクチャ ツールキットになることです。
npm, yarn, pnpmと同列のパッケージマネージャーだと思ってたけどそれ以上のいろんなものを包括したやつになるらしい
とりあえずはパッケージマネージャーとして使ってみる

インストールコマンド
bun create next-app nextjs-dashboard --example "https://github.com/vercel/next-learn/tree/main/dashboard/starter-example"

第2章
序盤はcssの話で特に目新しい情報はなかったのでスキップ

第3章
next/font
累積レイアウトシフトGoogle がウェブサイトのパフォーマンスとユーザー エクスペリエンスを評価するために使用する指標です。フォントの場合、ブラウザが最初にフォールバック フォントまたはシステム フォントでテキストをレンダリングし、読み込まれた後にカスタム フォントに置き換えるときに、レイアウトのシフトが発生します。この入れ替えにより、テキストのサイズ、間隔、レイアウトが変更され、周囲の要素が移動する可能性があります。
next/image
imgタグをそのまま使うと↓を手動で行わないといけない
画像がさまざまな画面サイズで応答することを確認します。
さまざまなデバイスの画像サイズを指定します。
画像の読み込み時にレイアウトがずれるのを防ぎます。
ユーザーのビューポートの外にある画像を遅延読み込みします。
next/imageのImage使うと勝手にやってくれる
画像読み込み時に自動的にレイアウトがずれるのを防ぎます。
小さなビューポートを備えたデバイスに大きな画像が送信されるのを避けるために、画像のサイズを変更します。
デフォルトで画像を遅延読み込みします (画像はビューポートに入るときに読み込まれます)。
WebPなどの最新の形式で画像を提供する とAVIFブラウザがサポートしている場合。

第4章
page.tsはルートのUIを含むReactコンポーネントをエクスポートする特別なNext.jsファイル。
/app/page.tsx
は/
のルートに関連づけられる
/app/login/page.tsx
は/login
のルートに関連づけられる
ネストしたルーティングもできる
/app/dashboard/customers/page.tsx
→ /dashboard/customers
/app/dashboard/invoices/page.tsx
→ /dashboard/invoices
/app/layout.tsx
→ 全てのページで共有されるルートレイアウト <html>タグを<body>タグを持つ
/app/dashboard/layout.tsx
→ ダッシュボードページ固有のものになる
1つ上の階層にlayout.tsxがない場合、その下の階層のpageはルートレイアウトを継承しないっぽい
/app/dashboard/layout.tsx
→ 作らない
/app/dashboard/customers/layout.tsx
→ 作る
↓
/dashboard/customers
のルートでは/app/layout.tsx
のレイアウトが継承されない

第5章
ナビゲーションの最適化にはLinkを使う
aタグと使い方は同じ
aタグのままだとページ間の移動でページ全体が更新される
next/linkを使うと部分的に更新されるようになる
自動コード分割とプリフェッチ
クライアント側のナビゲーションに加えて、Next.js はアプリケーションをルート セグメントごとに自動的にコード分割します。従来のSPAとは異なります、ブラウザーは初期ロード時にすべてのアプリケーション コードをロードします。
コードをルートごとに分割すると、ページが分離されます。特定のページでエラーが発生しても、アプリケーションの残りの部分は引き続き動作します。
pageを分けているとそれぞれが別のコードとして生成されるから挙動を切り分けることができる
さらに、本番中はいつでも、<Link>コンポーネントがブラウザのビューポートに表示されると、Next.js がリンクされたルートのコードをバックグラウンドで自動的にプリフェッチします。ユーザーがリンクをクリックするまでに、宛先ページのコードはバックグラウンドですでに読み込まれており、ページの遷移はほぼ瞬時に行われます。
これ凄すぎ
cacheとかもあるのでドキュメント読む

第6章
Vercel Postgres
Vercel DashboardのStorageからPostgresを選択して、CreateNameとRegionを決めてたら作られる
Quickstartの.env.localを選択してコピペ
@vercel/postgresというVercel Postgres SDKが公開されているのでそれを使うらしい

scripts/seed.js
をnodeで実行するとデータベースに初期データが入る
せっかくなのでbun コマンドで実行するようにしてみる
bunは自動的に.envを読み込むので、-r dotenv/config
は不要
package.jsonのseedにbun run ./
を入れてみる
実行してみるとエラーが発生
error: Cannot find module "/Users/ntogawa/private/nextjs-dashboard/node_modules/bcrypt/lib/binding/napi-v3/bcrypt_lib.node" from "/Users/ntogawa/private/nextjs-dashboard/node_modules/bcrypt/bcrypt.js"
error: script "seed" exited with code 1 (SIGHUP)
Issueを発見、bcryptを手動でコンパイルしないといけないみたい、、、
npm rebuild bcrypt
を実行すると解決した、が、bunでrebuild相当のものが見つからなかったので、一旦npmで諦め

改めてbun run seed
を実行してみたが、途中で止まってしまった
bun run ./scripts/seed.js
Created "users" table
error: script "seed" exited with code 11 (SIGSEGV)
./scripts/seed.js
のbcrypt.hash(user.password, 10);
の処理で落ちてるっぽい

詳しいことはわからなかったが、上記のようにbcryptとBunは相性が悪いみたい、、、
でもBunはpasswordハッシュを内包したAPIがあったので、そっちを使うように書き換えたとこと無事に動いた
- const hashedPassword = await bcrypt.hash(user.password, 10);
+ const hashedPassword = await Bun.password.hash(user.password, {
algorithm: "bcrypt",
cost: 10,
});

第7章 データの取得