Next.jsのチュートリアルをやってみる
長年Angularをやってきた。
しかし気づけば世は大Next.js時代。一度はNext.jsに触れておいたほうがいいのではないかと思い、重い腰を上げてチャレンジしてみることとする。
AngularでもSSRはやったことがないので、そのあたりの概念にも追いついていきたい
Next.jsには公式チュートリアルがある。
By the end of the course, you'll have the essential skills needed to start building full-stack Next.js applications.
コースを終えた時には、フルスタックなNext.jsアプリケーションを作り始めるために必要なスキルを身につけることができます。
とのこと。
なお、自分のような「そもそもReactもあんまわかってないです」のような人のためにNext.jsはReactの解説も公開しているので、そっちを先に読んでみることにする。
(Next.jsのチュートリアルと違って、こっちは手を動かすパートはなさそう?)
Reactとは何か?
React is a JavaScript library for building interactive user interfaces.
Reactはインタラクティブなユーザーインターフェースを構築するライブラリである。
Reactはライブラリであり、どのようにして使うかはそれぞれの開発者に放任している。
そのため、ゼロから始めるには努力が必要となり、Next.jsを含むサードパーティツールのエコシステムが成長した。
Next.jsとは何か?
Next.js is a React framework that gives you building blocks to create web applications.
Next.jsはwebアプリケーションの構成要素を提供するReactのフレームワークである.
Reactで構築したユーザーインターフェースをもとに、Next.jsは必要なツール・設定・アプリケーションに必要なものを提供する。
「Reactはフレームワークではなくライブラリ」とはよく言われるが、こういう違いがあるんですよ~ってことですね
HTML→DOM→UIの流れについて
JavaScriptでDOMを操作できます
JavaScriptでDOMを更新するには命令型プログラミングが必要で、面倒ですよね?
そこでReact!Reactは宣言型プログラミングでUIを構築するので楽なんです!
JSXを使うので、Babelコンパイルが必要になります
Reactを使うことでコードを削減できて、宣言的なプログラミングができます
ReactにはComponents、Props、Stateという3つの中心となるコンセプトがある。
ConponentはUIを構成する要素。自己完結しており再利用可能なので保守がしやすい。
PropsはPropertiesの略で、Componentに外から渡す情報。引数。
StateはUIの中で変化する情報。通常はユーザーのアクションによって変化する。
useState()
はStateそのものの変数とStateを更新する関数を返す。
前者でStateを参照しながら、後者でStateを更新する。
Reactのまとめと、Next.jsの概要
前のチャプターまでに作ったReact製のコードをNext.js化する
サーバー側で動くComponentと、クライアント側で動くComponent
Reactについてはサラッと流し気味で
これだけ気軽にSSRできるのはやっぱNext.jsの強みだなと思いますね(Angularも最近追いつきつつあるけど)
ということでNext.js本体のチュートリアルをスタート
はじめに
サンプルコードがダウンロードされるので読む
package.jsonのdependenciesにtailwind, TypeScript, zodがあり、いかにも現代~って感じ
フォルダ構成は初めて見てもまあ分かりやすい印象
Angularのhtmlファイルとjsファイルを分ける書き方に慣れてるせいだと思うが、jsの中にhtmlがあって、さらにそのhtmlの中にjsが書かれてたりする多重入れ子構造?が少し気持ち悪い…
書かれてる内容はまあだいたい分かるかな
手順通りにdevサーバーを起動してアクセスすると、cssが適用されてないページが表示される
こういう失敗例を先に提示しておくパターンたまにあるけど、一瞬びっくりしたあとちょっとイラッとしません?初学者に「問題発生→解決」の手順を学ばせるため?
Chapter 2 CSS Styling
CSSスタイリング
Next.jsで使用するcssまわりの知識を叩き込まれる
clsxはAngularでいうngClassか
最後にはscssやcss in jsの話も
未経験の人とかだとここ結構しんどそうだな…
Chapter 3 Optimizing Fonts and Images
フォントと画像の最適化
「序盤は見た目を整えることで初学者にもわかりやすい成功体験を与えていくぜ」という意図をひしひしと感じる
フォントの変更って(特に日本語フォントだと)フォントファイルの重さのせいでなかなかやりづらいのだけど、SSRだから最適化して配信しますよって話なのだろうか
クライアントで再レンダリングするようなコンテンツの場合どうなるんだろ
画像最適化!AngularでいうNgOptimizedImage
だ
NgOptimizedImage
は出てきた頃に記事書いてみたんですけど、今調べてみたら更に便利になっててびっくりした
Chapter 4 Creating Layouts and Pages
レイアウトとページを作る
フォルダ構成がそのままrouteになるのか
Angularと比べるとページ作るのは圧倒的に楽だけど、細かい設定とかどうなんだろ
layout.tsxでパスの階層ごとにヘッダーとかサイドバーとか切り替えられるの便利だなーこういう仕組みAngularにもあったっけ?と思ったら普通にあったわ
全然知らなかったので力技でヘッダー入れ替えたりしてたな…
Chapter 5 Navigating Between Pages
ページ間の移動
<Link href="{foo}">
、Angularでいう<a [routerLink]="foo">
か
コードの事前プリフェッチはすごいが、うっすらとプリフェッチにいいイメージがないので怖いかも
Chapter 6 Setting Up Your Database
データベースのセットアップ
ついにDBまわりの回が来た
Angularでバックエンド側を触ったことはないので、さすがに気になる
GitHubにpushして、VercelとGitHubを連携して、ボタンぽちーでデプロイ完了。便利~
しかもpushするたびに自動デプロイされるし、ステージング環境向けのフィーチャーフラグとかコメント機能とかあるし、アクセシビリティやレイアウトシフトのチェックもされる。
とんでもなく便利ですわね……
Postgres生やすところ、チュートリアルと実際のUIが違う気がする
secretsをローカルにコピペして、ローカルで指定のURLにアクセスするとスクリプトが走って、クラウド上のDBにデータが書き込まれる。
「クラウド上でデータ書き込むんじゃなくて、ローカルからクラウドに書き込むんだ」の驚きと、
「指定のURLにアクセスするとスクリプトが走ってDBに書き込む」がいにしえの開発を思い出して懐かしさを感じる。
フロントエンドとバックエンドが明確に分かれる前のデータ投入ってわりとそんな感じじゃなかった?
Chapter 7 Fetching Data
データの取得
フロントエンド系フレームワークのチュートリアルで「SQLを使います」って言われる日が来ると思ってなかった
というかNext.jsはフロントエンドではないんだろうな…
app/lib/data.ts
のレイヤーが現実的にはTypeORMとかPrismaとかになるのだろうか
そこまでできてしまうのなら、ちょっとDBとつなぎたいだけのバックエンドってもう要らない時代なんですか……?
軽めの業務システムだったらこれだけで作れますよね……???
静的レンダリングと動的レンダリング
ここはほとんど座学の時間
DBアクセスが重くてページの初期表示まで待つの、いにしえのwebアプリケーションっぽくて懐かしいよ
Chapter 9 Streaming
ストリーミング
いにしえの我々がページの部分的更新をAjaxでどうにか表現してたやつが簡単にできるってこと???
ファイル1個置くだけでローディング表示がされた…
これでFCPめっちゃ早くなるのUX的にかなり良いな
Route Groupsの概念ちょいむずいかも
ディレクトリ名に()
をつけると~ってのはもうちょっと実践しないとしっくりこなさそう
スケルトン、それ自体を作るのは多少面倒だと思うけどそれにしても効果ありそうでいいな
Move data fetches down to the components that need it
データの取得を必要なコンポーネントに移す
これはドメイン分割とかテーブル構成ちゃんとしたうえでページ構造を把握してないと怖いな
同じテーブルにアクセスしまくって重くなるとかDBへのアクセス回数を跳ねさせてしまうとかしそう
Chapter 10 Partial Prerendering
部分プリレンダリング
これはchapter9でやったコンポーネント単位での「Streaming」とは別物なのか?
開発環境でも本番環境でも動きの違いがわからん…
Streamingの場合はページ全体が動的レンダリングになる。つまりLoading...
とか各Skeltonとかの静的にHTMLを出力しておける部分も動的になってしまうが、
Partial Prerenderingの場合はそのへんは静的レンダリングのままSuspence
した部分だけ動的レンダリングになるってことか
Chapter 11 Adding Search and Pagination
検索とページネーションを追加する
このチャプターなっがいな
onChange={(e)=>{...}}
イベントの書き方がAngularと違うので違和感がある
(change)="foo($event)"
に慣れすぎちまったよ
debounceするのにサードパーティのライブラリを追加する必要があるのはReactの最小限さを感じる
オールインワンを称するAngularだと自前(ではないけど)のライブラリが最初から入ってるので
Adding pagination
の章、コードハイライトの位置がズレてない?
ここなんかも16行目がハイライトされてるのが正しい気がする
1つのページ内でSuspense
されてuse client
で動くComponentと、Suspense
されずにuse client
で動くComponentとの差がわからなくなってきた
両方ともクライアント側でレンダリングされるわけだから、Suspense
の利点としてはSkeletonを表示できること?
→ユーザーがイベント発火させたいComponentはuse client
が要るのか
だからPagination
はuse client
が必要なのね
Chapter 12 Mutating Data
データの変更
このチャプターもなっっっっがいな
心が折れそうになってきた
React Server Actions
ってなんだ…?今までやってきたのもサーバー側の処理してたのでは…?と思ったが、
多分ユーザー側のアクションをサーバー側で処理することをこう呼ぶのかな
すぐ下のサンプルで<form>
のsubmitを上書きするような処理してるし
っていうかこれがあればPOSTとかのエンドポイント作る必要がないってことですか???
バリデーションのところでZodが出てきた
ほんとに現代の開発環境まとめセットだなぁ
Chapter 13 Handling Errors
エラー処理
説明見た感じだと例外は正しくcatchしてないといい感じのエラー表示ができないのか?と思ったが、別にそうでもなさそう???
try-catchの外でthrow new Error()
してもerror.tsxは表示されるっぽいな
Chapter 14 Improving Accessibility
アクセシビリティを向上する
$ pnpm lint
コマンドを打ったら説明と違う流れになったし、lintからもすごい怒られた
linter側がなんか変わったっぽいな?(関連PRも出てた)
コマンド打ってからの流れ
> next lint
./app/dashboard/(overview)/page.tsx
2:10 Error: 'Card' is defined but never used. @typescript-eslint/no-unused-vars
6:10 Error: 'fetchCardData' is defined but never used. @typescript-eslint/no-unused-vars
./app/lib/actions.ts
35:12 Error: 'error' is defined but never used. @typescript-eslint/no-unused-vars
60:12 Error: 'error' is defined but never used. @typescript-eslint/no-unused-vars
73:12 Error: 'error' is defined but never used. @typescript-eslint/no-unused-vars
./app/ui/customers/table.tsx
5:3 Error: 'CustomersTableType' is defined but never used. @typescript-eslint/no-unused-vars
./app/ui/dashboard/revenue-chart.tsx
4:10 Error: 'Revenue' is defined but never used. @typescript-eslint/no-unused-vars
./app/ui/login-form.tsx
5:3 Error: 'ExclamationCircleIcon' is defined but never used. @typescript-eslint/no-unused-vars
ついに正解例がない練習問題が出てきた
ここはまぁスルーさせていただきまして…
lintのエラーが出てるせいでVercel上のデプロイもコケた
不要な変数を消して回りました
Chapter 15 Adding Authentication
認証を追加する
ログインページが404になる…なんでぇ…?と思ったら/app/dashboard
の下に/login
ディレクトリ作ってた
凡ミスです
パスワードのハッシュ化アルゴリズムがbcryptだ
md5じゃないにしても、妙に古めじゃない?このチュートリアルのノリならargon2とか来そうなのに
細かいファイルがいっぱい生えたのと、そもそもログインまわりって小難しくなりがちなのとで、
どこがどう動いてるのかわからないままコピペしてる感じがある
Chapter 16 Adding Metadata
メタデータを追加する
SSRはSEOに強いって売りがあるのだし、SEO向けなメタデータの具体例があればよかったなぁとは思う
途中で紹介されてるImageResponseすごいな
動的なogp画像を楽に作れるって話ですよね?
Chapter 17 Next Steps
次のステップ
最終チャプター。
Next.jsを使ったアプリケーションのサンプルが5つも紹介されてるのいいな
webアプリだけじゃなくて、ブログとか画像ギャラリーとかの静的サイトがあるのはNext.jsの使われ方的にも参考になりそう
以上!Next.jsのチュートリアル終わり!
気が向いたらさらなる深堀りですね
Next.jsとVercelの便利さがよくわかった。
1つのフレームワークでフロントエンドとバックエンドができて、
さらにホスティングやDBが一瞬で準備できるのは強い…
そりゃちょっとしたサイトやアプリケーションくらいならNext.js&Vercelでやるってなるわ
いまNext.jsに対抗できるwebフレームワークってなにがあるんだろう
最近だとRemixとかHonoをよく聞くけど、ここまで発展しきってるイメージはない
vercel対抗はCloudflareとかFirebaseかsupabaseとかあるとは思うんだけど