Next.jsのReact EssentialsのServer Componentsの説明をオレオレ翻訳しながら読む

これの話

https://nextjs.org/docs/getting-started/react-essentials#server-components

正確さではなく(それならAIでいいよね)、自分の理解に引き寄せて翻訳してみる。

Server Components

Server and Client Components があるとサーバーとクライアントの両側にまたがるアプリケーションを作れます。クライアントサイドのリッチなインタラクティビティと伝統的なサーバーレンダリングのパフォーマンスを組み合わせることができます。

Thinking in Server Components

ReactはUI設計の考え方を変えました。同じようにReact Server Componentsは、サーバーとクライアントの両方を活かしたハイブリッドアプリケーションを作るための新しい考え方です。

Reactはこれまで全てをクライアントサイドでレンダリングしていました(SPAというやつです)。しかし、Server Componentsがあると目的に応じてどこでレンダリングするかを決められます。

たとえば、アプリケーションのpageを考えます。

ページをコンポーネントに分割すると、実は大多数のコンポーネントはインタラクティブではないです。つまりサーバーサイドでServer Componentとしてレンダリングできます。そしてその中にインタラクティブなクライアントコンポーネントを点在させるのです。これはNext.jsのサーバーファーストなアプローチと相性がいいです。

Why Server Components?

Server Componentsのメリットは何?という疑問が浮かぶでしょう。

Server Componentsはサーバーのインフラを活用しやすいです。たとえば、巨大な依存パッケージをクライアントに送信する必要がありません。こうなるとReactはPHPやRoRのよう(テンプレートエンジンのように?)に扱えます。

Server Componentsは初期ページ読み込みが早いです。バンドルサイズが小さくなります。根幹部分のクライアント側ランタイムはキャッシュ可能かつサイズの予測が可能で、アプリケーションが成長しても増えません。追加されるJavaScriptは、Client Componentsが使われたときだけ増えます(この辺あんまりわかってない)。

Next.jsでrouteが読み込まれたとき、初期HTMLがサーバーでレンダリングされます。このHTMLはブラウザで段階的に成長し、クライアントがアプリケーションを引き継ぎ、インタラクティビティが付加されます。このためのランタイムの読み込みは非同期的です。

Server Componentsに楽に移行できるように、App Router内のコンポーネントは全てデフォルトでServer Componentsにします。special filesやcolocated componentsも同様です。だからあなたは何もしなくてもServer Componentsを採用して優れたパフォーマンスを得られます。ここに use client directiveを使うことでClient Componentsをオプトインできます。

Client Components

Client Componentsを使うとクライアント側でのインタラクティビティを付加できます。これはNext.jsではサーバーでのpre-renderingとクライアント側でのhydrationで実現しています。Client ComponentsはこれまでのPage Routerと同じ動きです。

The "use client" directive

use client directiveはServer / Client Componentsの境界線を宣言するものです。

'use client';

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}

"use client" はサーバーとクライアントのコードの間に配置します。ファイルの一番上、importsよりも上に書きます。"use client" が宣言されると、そのファイルがimportしている全てのモジュール(子コンポーネントなど)はクライアントバンドルの一部と認識されます。

デフォルトはServer Componentsなので、 "use client" 宣言がない限り全てはServer Component moduleに含まれます。

豆知識

  • Server Component moduleに含まれるComponentはサーバーでのみレンダリングされることが保証されます
  • Client Componentはクライアントでレンダリングされるものですが、Next.jsは事前にサーバーでレンダリングすることもあります
  • "use client" はファイルの一番上で宣言しなければなりません
  • "use client" は全てのファイルで宣言する必要はなく、Server Componentsとの境界でだけ宣言すれば十分です(そのファイルがimportしているファイルもクライアントバンドルになるので、"use client" が宣言されたファイルはentry pointとみなすことができます)

おわりに

Server Componentsが何なのか知りたくて調べていたんだけど、なんか概念的な記事しかなくてよくわからなくて、この記事もそうだった。完。でも概念はちょっとわかった。

最近考えていること@202206

読書

『ザ・ゴール』

スクラムでベロシティを安定化するにはどうしたらよいかで紹介されていたので8割方読んだ。8割方というのは、途中生産管理の話から思考法っぽい話に移ったところで興味を失って止まっているからだ。

この本では問題を抱えた工場の工場長が、学生時代の恩師(作者がモデルのようだ)から断片的なヒントを得ながら、それまでとは全く違う思想の生産管理を取り入れて成功するというストーリーが物語仕立てで描かれる(無職やめ太郎氏のようなものだ)。端的に言えば全員を休みなく働かせるのが最高効率というわけではなく、むしろボトルネックに着目しろという話だったように思う。「ように思う」というのは、教科書ではなく物語だから論理的な筋立てはあまりよくわかっていないからだ。

興味深い読み物ではあったが、単純にソフトウェアエンジニアリングに応用できるかは疑問だ。ソフトウェアエンジニアリングには固定化した生産ラインはないし、在庫コストもないからだ。しかしフロー効率とリソース効率とか、従属事象・統計的変動の概念はなんとなく掴めたので、もうちょっとかっちりした制約理論の教科書を読んでみたいと思った。

『プロを目指す人のためのTypeScript入門』

言わずと知れた有名人uhyo氏の著作。3割くらい読んだ。

僕は既にプロなので9割くらいはもう知ってる知識だ。しかし端々に挟まれる詳細な仕様の知識とか歴史的経緯、さらにuhyo氏の思想などが勉強になる。知っていると思い込んでいるものをもう一度学び直すという意味で価値のある読書だなと思う。思うのだが、やっぱり大体は知ってる話なので退屈になってしまってなかなか読み進められない。

『HTML解体新書』

仕様が広大ゆえに使いこなすのは難しいHTMLの本。全然読めてない。

『データ構造とアルゴリズム(五十嵐健夫)』

連結リストやスタック、木、ハッシュなどから始まり、ソートやグラフや文字列検索なども扱うらしい。これも3割くらい。

C++で実装しながら読み進めている。2-3木は辛かった。コアになるアルゴリズムはシンプルなのだが場合分けがドエラい数になる。平均計算量に関してはある程度計算で求める必要があるが、理解できないほどではなかった(自分で発想しろと言われても無理だが…)。

労働

あまり多くは語れないが、ここ半年くらいはずっと悩んでいる。4年目にもなるとこれまで通りの仕事をしていても学びがなくなってくる。だから更にスコープを広げて何かチャレンジしたいなと思っているけど、なかなかうまくできない。仕事に学びを求めるのが間違いなのかもしれない。

だからまあ、最近本をたくさん買ってみたり個人開発頑張ってみたりというのは、何か突破口が見つからないかなあということですね。

個人開発

最近はもっぱら https://anime.chao.tokyo の開発を進めている。Animetickからしょぼいカレンダー(手入力のアニメ放送予定API)への依存を切って、大量視聴を管理するための可視化などを足してみたいなという狙い。

使用技術はRemix+PrismaでEC2に雑に(DBもEC2で動いてるw)立てている。バックエンドの処理をパイプラインに見立ててfp-tsで書いているのが自分的こだわり。

飽きたら次にやってみたいのはweb componentsとかかなあ。Reactを捨てて生のHTMLと最低限のJSで何ができるのかというところを勉強してみたい。あるいはなんかOSSとかも。GoやRustも触っておきたい。学ぶべきことはいくらでもある。その気になればTypeScript一本でなんでも書けてしまうので、意図的にコンフォートゾーンの外に出るようにはしたい。

料理

以前から美味しいものを食べるなら外食で、自炊は楽で身体に悪くないものというポリシーでやっている。最近は以下のセットで固まっている。

  • ご飯
  • 味噌汁
  • 自作サラダチキン
  • ブロッコリーの惣菜(冷凍食品)
  • スーパーで買ってきたサラダ(ごぼう・コールスロー・切り干し大根のローテーション)
  • 納豆
  • ヨーグルト

サラダチキンを切らしたときは適当に惣菜買ってきたり。ここから50年くらいずっと同じものを食べ続ける可能性すらあるので、自炊は変に偏らないようには気をつけたい(何食っても塩分過多で怒るのであすけんは嫌いです)。

健康

3月末に右足首を捻挫して結構長く歩行で痛んだり疲れやすかったりした。ようやく治りつつある。

アニメ視聴

まあ、そこそこ見てます。

Dota2

ちょっとやる気なくなってます。4月頃は調子よくて3880まで上がったけどしばらくやらなくなって今3430。

自分の持ちキャラのメタ変動の話をすると、Dazzleの7.31の変化が気に入らない。タイミングの概念を捨てて単にCD上がるたびにスキル撃つのを推奨するようなメカニクスになっていて、こんなの人間がプレイする必要ないじゃんと思ってしまう。

ということでプロの間で大流行していたPugnaばかり使っていた。癖はあるもののスキルセットが強力。サポートでも積極的にタワーを折れる1番、SavingにもDisableにもなる2番、設置するだけで大きなダメージを叩き出せるNether Ward、そしてダメージにも大回復にもなるUlt。Shardは弱いと思うけど…(相手にPLかNagaがいたら買うかも)。

ただPugnaも7.31dでかなりお仕置きを受けてしまったのでやめる。またDazzleに戻ることも検討しているが、単に数字上のbuffがあったというだけでメカニクスは改善していないので悩ましい。あるいはEnchantressもいいかもしれない。これもプロで猛威を奮っていたので7.31cでEnchantにレベルキャップがついてしまったが(なかったほうがおかしいだろ!)、それでもタンクやラットができるサポートというのは貴重だ。

Stunがないサポートは嫌がられるのでHoodwinkを使っていた時期もあったが肌に合わず全然勝てなかったのでやめてしまった。

2/18~2/24 在宅勤務/過剰な健康への不安

在宅勤務

すでに発表されている通り弊社は在宅勤務期間中だ。僕はソフトウェアエンジニアの一般社員なので仕事に占めるコミュニケーションの割合が低く、在宅勤務でもそこまで不便を感じていない。エンジニア職以外の事情はよくわからないし、エンジニアでもリーダー級以上になるとミーティングが多くあるのでなかなか大変なところがあるのではと思う。

あえて不便なところを挙げると、オフィスが使えない分自宅の環境に左右されるところか。自宅のPCデスクはかなりリソースを投じて強化してきたので問題ないどころか会社以上に快適。だがネット回線は時間帯によって不安定でイライラする。自宅の周りに飲食店がないので食事に変化がなくなるし(自炊のレパートリーが少ない)、運動不足にもなる。通勤が不要なぶん1日あたり80分くらい時間が浮いてるので、その時間を使って散歩でもすればいいのか。でも花粉のシーズンだからなあ。

過剰な健康への不安

先週の虫歯の処置以降、なんでもない歯の感覚がどれも虫歯の兆候なのではと思えてしまって不安だ。歯医者では処置した歯以外は問題ないと言われているが、それもあまり信用できない気分。一般論として医者は信用すべきなんだが。

もともと僕は健康を損ないたくない、特に永続的にダメージが残るような病気にはなりたくないという心配が強すぎる。年齢的に考えればこれから健康は失っていく一方だというのに、バカバカしい。

ちゃおネイキッドプロジェクトの進展

自動デプロイ

Spotify機能のためにredisを立ててdocker-composeで連携するようにした。これに伴いデプロイの手順が変わったので.drone.ymlを調整した。docker runに複雑なオプションを載せまくるよりもdocker-compose.ymlに書いてしまう方が楽だし1コンテナでもdocker-composeを使うべきなのかもしれない。

CSSレイアウトのお勉強

Spotifyで聴いている曲を表示できるようになったので、画像・タイトル・アーティストをいい感じにレイアウトしたくてCSSのお勉強をした。MDNのドキュメントが大変参考になった。というかCSS系の情報はググってもノイズが多すぎる。

勉強のためにstyled-componentsでCSSをTSの中で記述してみた。ファイルの中身がカオスになる感覚は否めないが、コンポーネントとスタイルの結びつきが強くなるのは使いどころによっては便利なのだろう。特にwebpackを弄らずとも導入できるのはよい。

bundleサイズ削減

bundle analyzerで見てみるとmomentのタイムゾーンとかlocaleのファイルがすごい容量食っててビビったのでググって削減した。効果が数字で見えるのは楽しいのだが、webpack.config.jsがどんどん複雑になっていくのはつらい。

今後の野望

  • 監視・ロギングの強化
  • 様々な自動投稿機能がついたTwitterタイムラインのようなサービスにしていきたい

ESLint入れた

12/18(水)

TypeScript+ReactのプロジェクトにESLintとprettierを入れた。ESLintのプラグインを上手く組み合わせていくテクニックが難しかった。

結論はこんな感じ。

.eslintrc.json

{
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "project": "tsconfig.json",
    "sourceType": "module"
  },
  "extends": [
    "plugin:@typescript-eslint/recommended",
    "plugin:prettier/recommended",
    "plugin:react/recommended"
  ]
}

yarn lint で能動的にlintを実行できるようにしつつ、lint-stagedとhuskyでcommit時にも仕込んだ。

給料が出ますよ/localStorageは文字列限定/右に偏っている

明日が初任給だ。まだ年金も健康保険料も住民税も引かれないので額が大きい。考えたら憂鬱になってきた。とは言っても既に健康保険の恩恵はたっぷり受けている。給料を増やすためにスキルアップするか、資本家になるか、革命を起こすか、どれがいいか考えている。

今日もTodoアプリの作業を進めた。customsをlocalStorageに保存しようと思ったのだが、配列を保存しても勝手に文字列に変換されてしまっていた。文字列しか保存できないらしい。Store.jsというライブラリを使う手を教えてもらったが、ごく単純な文字列の配列を保存したいだけだったので配列を.join(',')して保存し、読み出すときに.split(',')している。

Reactはパフォーマンスのためにリストアイテムにユニークなkeyをつけるよう推奨している。困ったのでmapするときのindexをそのままkeyに放り込んだが、それでよかったのだろうか。

抜歯の跡がまだ気になって右でばかり噛んでいる。明日の午前中に歯医者に行って経過を診てもらう予定だ。食事を気にする必要はないと言われたら体に悪いラーメンでも食べに行きたい。左で噛めるようになったら次は右を抜かなきゃいけないわけだが。

ReactでTodoアプリ/枠を超える笑い/日記が長い

ReactでTodoアプリ

しばらくReactのドキュメントを読んでいたのでそろそろ実践しようと思いTodoアプリを作り始めた。帰宅してから何をするかを整理し、実行できたかをチェックできるものにしたい。Custom欄を設け、毎日やりそうなことはCustom欄からAddAllで一括登録できるようにした。Customの内容は今はハードコーディングしているがCookieから読めるようにしたい。

環境構築にcreate-react-appを使った。デフォルトでeslintが入っていてミスや無作法を懇切丁寧に指摘してくれるし、LiveServerを起動しなくても保存するだけで変更が反映される。これがモダンな開発かと感動した。

読むのと作るのでは当然違うのでよくつまづくが、それが勉強というものだ。楽しい。

枠を超える笑い

お気に入りのユーチューバーでありお笑い芸人でもあるガーリィレコードチャンネルの新作動画が面白い。リアルイベントの映像化だ。

デブ3人が面白いことをするのをガリが撮影するというのがガーリィレコードチャンネルのお決まりの流れであり、この動画は隙間を走り抜けるデブ3人をガリが判別するという遊びだ。

詳しくは自分で見てほしいが、走り抜ける3人を頑張って見て当てる(当てられないように速く走る)というルール通りに遊んでいたのは序盤だけで、中盤以降は予想もつかないルール破りがテンポよく飛び出す。そのたびに大声で笑ってしまった(感情がある)。あらかじめ枠を設定しておいて、それを飛び越えると笑いが生じるのだろう。

日記が長い

最近は妙に読者を意識して長いブログを書いてしまっている。時間がかかってしんどい。

第2の料理/ReactのsetStateがワカラナイ

※この記事は『Asahi 極上<キレ味>』を飲んで書かれた。

↑キレ味ってなんだ…?

昨日なんとなく焼きそばに飽きたので今日は鮭の炊き込みご飯を作った。これも僕のレパートリーの1つだが、ご飯を炊くのは時間がかかるので敬遠していた。

作り方はかんたんで、ご飯を炊くときに醤油・鮭・えのき・鮭を一緒に入れるだけだ。こだわるなら昆布も。炊き上がるころには部屋が醤油のいい香りに包まれている。

今日もReactのドキュメントを読んでいた。だいたい理解しながら読み進んでいるが、やはりReactがパフォーマンスを出すために中でゴニョゴニョやっていることを理解するのが難しい。たとえばここ。再描画の回数を減らすためにsetStateは即時に実行されないことがあるという。しかし例示されているコードでどのような不具合が起きる可能性があるのか、failの一言だけではよくわからない。

Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.

For example, this code may fail to update the counter:

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});

これの解決策としてsetStateに関数を渡すことで確実にsetStateが行われるタイミングでのpropsの値を取得する方法が紹介されているが、これによって何を解決しているのだろうか。

だいたい家にいた/ナウいReact

※この記事は『Asahi 極上<キレ味>』を飲んで書かれた。

強い意思があったわけではないが、今日は夕方に買い物に行った以外は家にいた。

以前からやりたいと思っていた‎@kfurumiyaさんの『正真正銘のReactだけの不純物なしでReact入門』をやった。「不純物なし」というのは意外と厄介で、複雑な状態管理はReduxでやるのが普通なのに対して、このチュートリアルではReactの新しい機能であるHooksを使っている。

Reactは形作りが面倒だが、そこに当てはめていくことで巨大なアプリでも比較的小さい負担で作れるというのがこれまでの認識だった。しかしReactの真価である差分検知システムを効率的に動かすためには無駄な再描画をさせないための工夫が必要らしい。慣れればこれも流れ作業のように書けるのかもしれないが、現時点では難しそうだ。

チュートリアルに沿ってひとりツイッターを作ったあと、本家に近づけるために

  • 空白の投稿はできない
  • 投稿したら入力欄が空白になる
  • 削除できる

の3つの機能を追加してみた。見た感じでは正しく動いている。今後はnodeでなんかいい感じにコンパイルする、テストを書く、Ajax通信するなどをやってみたい。