uhyo/blog

書評『TypeScriptとReact/Next.jsでつくる 実践Webアプリケーション開発』

2022年8月11日 公開

皆さんこんにちは。今回は、2022年7月25発売の『TypeScriptとReact/Next.jsでつくる 実践Webアプリケーション開発』を読み終わったので、書評という形で感想と紹介を述べたいと思います。筆者はもともと技術書を読まず「ネットでいいやん」派だったのですが、このたびTypeScript入門書を出版したこともあり、それを過去の話として葬り去るべく技術書を読んでいくことにしました。せっかくなので、読んだ技術書の感想等を紹介します。

おことわり: この記事では、「筆者」とはこの書評を書いた人を指し、『TypeScriptとReact/Next.jsでつくる 実践Webアプリケーション開発』を書いた人たちのことは「著者ら」と呼びます。また、この記事の内容はすべて筆者の個人的な見解であり、本の内容や本を読んで得られる知識について何らかの保証をするものではありません。

筆者について

筆者はフロントエンドエンジニアで、TypeScriptとReactを専門としています。今回の本はTypeScript, React, Next.jsというスタックで、ちょうど筆者の専門領域を扱うものとなっています。そのため、筆者がこの本から新しい知識を得ようというよりは、人に紹介するときにどうかという観点から読みました。

総評

残念ながら、この本を書いたのはフロントエンドの専門家ではないと判断せざるを得ません。そのため、記述の一字一句、サンプルコードの一行一行を全部身の糧にするというような読み方はおすすめしません。TypeScript, React, Next.jsというスタックの大ざっぱな概観を素早く掴むために読むのがよいでしょう。

内容からは、著者らはどちらかというとサーバーサイド寄りのフルスタックエンジニアという印象を受けます。記述のクオリティが高いところと低いところに差があり、Reactそのものに関してやフロントエンドのビルドの仕組みなどについては間違いが散見されます。また、マークアップやコンポーネント設計についても、良いアプリケーションを作るために必要なメッセージがあまり読み取れません。一方で、CSR, SSR, SSG, ISRの使い分けなどのトピックやNext.jsのアーキテクチャ図などは比較的しっかりしているように見え、サーバーサイドも絡んだこのような領域が得意なのだと思われます。

本の内容としては、タイトルにあるようにTypeScript, React, Next.jsというトピックについて学習し、本の後半(6章)では実際にNext.jsを使ってアプリケーションを作ってみるという構成になっています。後半の内容は、実務の現場でも使われているさまざまなライブラリを取り入れて使用する実践的なものとなっています。

どのような人におすすめ?

TypeScriptの説明が一定の知識を前提としており「超速習TypeScript」の様相となっているので、プログラミング未経験の方が読むのは難しいでしょう。サーバーサイドなど、他の分野でプログラミングの経験がある人がフロントエンドにコンバートする(あるいはフロントエンドもやる)場合に適しています。TypeScriptやReactの機能の説明においては、基礎的な部分はともかく、実務でReactのコードをいじるのに必要な知識は一通り揃うようになっています。

そのため、御託はいいからとにかく早くフロントエンドの現場に入れるようにしてくれ! という人が読むのがよいと思います。間違いがあるとは言いましたが、1メンバーとしてプロジェクトに参画するなら触らない部分に関するものが多いので、そこまで問題にはならないかもしれません。

この本について注意すべきこと

この本を読むととりあえずReactのコードをいじれるようになると思われますが、基礎的な部分やコンポーネント設計の何たるかなどはあまり取り扱われていません。また、サンプルコードの質も低いところがあります。そのため、基礎からじっくり身に付けたいという人には向かないと思われます。本書で到達できるのは「とりあえず動く」というレベルであり、それを超えるような高いクオリティ(設計のよさ・Reactらしさ等)を出せるようにするためにはさらなる研鑽や別の本が必要です。

とくに、基礎的部分の取り扱いが薄いことから、この本だけ読んでフロントエンドをリードしたり、他のメンバーに教えたりする立場になるのは難しいでしょう。この本を取っ掛かりにしてさらに勉強するか、あるいはメンバーとして入り、他のより詳しい人から教えてもらいながら成長して一人前になるというのが堅実なプランです。

各章について

各章の概要、感想、良い点・悪い点を紹介します。

1章 Next.jsとTypeScriptによるモダン開発

Next.jsやTypeScriptを用いるモダンなフロントエンド開発の概要を知るとともに、そこに至るまでの歴史(JavaScriptの開発、Google Map、SPAという概念の普及、単方向データフローの普及など)を概観する内容です。歴史の説明は要点を踏まえてまとまっており参考になります。

また、Next.jsの機能に絡めてSSRやSSGの紹介やその必要性に関する説明もあります。

一方で、筆者がここで気になったのは、ReactとNext.jsの機能境界に誤解があることです。この本ではSSRは(Reactではなく)Next.jsの機能としていますが(p2, p20など)、実際にはSSR用の関数はReact本体が持っているものであり、Next.jsはそれをラップしているという関係にあります。

これは一見すると些細な間違いに見えますが、著者らの理解度を推し量る上で重要です。というのも、この本ではReact 18が取り扱われていますが1、React 18の新機能の一つとしてStreaming SSRがあることから、Reactの情報をちゃんと追っていればSSRがReactの機能であることは必然的に理解していたはずです。

他にも、webpackの機能として「利用している依存モジュールのバージョン管理」(p18)が紹介されている点など不正確な記述があります。

説明を簡単にするために簡略化した可能性もありますが、このような基本的な部分を雑に済ませるのは筆者としては感心しません。すべてを事細かに説明せよとは言いませんが、何も書かないか、明示的にぼかすのがよいと思います。わざわざ間違いを書いてしまうのは本の信頼性を下げるし、間違いがあると本を読んだ人が活躍できる幅を狭めるからです。このような間違いを鵜呑みにしてしまった人が他の人を教育する立場になると、不幸なことになります。

2章 TypeScriptの基礎

章名が示す通り、この章はTypeScriptがどのような言語か、そしてTypeScriptの基本的な使い方を説明する章です。総評にも書いた通りTypeScriptの言語機能の説明はかなり簡潔です。配列の説明は0.5ページで、オブジェクトは1ページ、async/awaitも0.5ページといった具合です。型アサーション(as)の説明も序盤にありますが、危険な機能である(ランタイムエラーを引き起こす可能性がある)と一言添えられているのが好印象です。

また、2.4「実際の開発で重要な型」として、ジェネリクスなどと並んでユニオン型・インターセクション型・リテラル型、そしてnever型まで紹介されているのも良いですね。特にユニオン型は使わないとTypeScriptの力を20%くらいしか発揮できませんから、しっかり紹介されているのは実践的でとてもよいです。

以上のことから、この章を読んでTypeScriptを身につけろというよりは、読者が自分でTypeScriptを調べるにあたって引っかかりそうなところや、必要そうな知識を事前にインプットしておくための章という意味あいが強いと推察されます。そうして見てみると、トピックの選定は結構筋がよいと感じられます。

ただ、それだけで読者に理解させるためではないとはいっても、基礎的な原理を踏まえずざっくりとした説明になっているところがあるのがやや残念です。例えば、インターセクション型については積集合であるという説明(p56)とオブジェクト型をマージするという説明(p57)が同居しており、両者がどう関係あるのかについては説明されていません。この説明をするためには構造的部分型について理解してもらう必要がありますが、その説明は省かれています。リテラル型についても「|でデータを区切るリテラル型」(p57)とされており、(本の内容を見るに著者らは正しく理解していると思われますが)ユニオン型と混ざった雑な説明になってしまっています。

他に突っ込みどころがあるとすれば、2.5.1ではoptional chaining (?.) の説明がされていますが、以降のサンプルコードでf && f() というパターン(fがあるときのみ関数を呼び出す)が多用されているところです。おそらく、著者らはoptional chainingの機能のうちfoo?.barは知っていてもf?.()は知らなかったのではないでしょうか。

この章では他にもTypeScriptの設定(tsconfig.json)やPrettier, ESLintのセットアップの説明もあります。ここの設定でstrictNullChecksだけtrueにしてstrictをfalseにしているのは勘弁してくれと思いましたが、のちのち第5章でもう一度環境を作るときはstrictをtrueにしていたので大丈夫です。

3章 React/Next.jsの基礎

TypeScriptの導入が終わったので次はReactとNext.jsです。この章ではReactの基本的な書き方(コンポーネントの書き方、フックの使い方)やNext.jsの機能の使い方が紹介されます。

この章の説明はかなり筋がいいと感じました。各フックの使い方をしっかりと説明し、意義を正しく説明するのが意外と難しいuseMemoなどについても紙面を割いて説明しています。それに合わせて、再レンダリングを防ぐといった、React開発において重要な点が説明されています。

細かい粗を探すとすれば、classNamehtmlForについて「JavaScriptでは予約語にあたるため」(p82)と説明されている点2や、「JSXのコードは(中略)webpackによって、JavaScriptのコードに変換されます。」(p81)としている点3など、これまでの章と同様に、ビルドシステムや基礎的な部分の説明が弱い印象があります。

4章 コンポーネント開発

Reactの機能を紹介したので、次はReactアプリケーションのパーツとなるコンポーネントの書き方を説明するというとても自然な流れです。

また、章の最初ではコンポーネントの分類が説明されます。具体的には、まずPresentational Component / Container Componentという区別が紹介されています。筆者個人の意見としては、フックの登場によって「コンポーネントとそれ用のカスタムフック」というより筋のいい方法に切り替わったと思っていますが、ロジックと見た目に役割を区分すること自体は依然として有効です。

また、この章ではAtomic Designが紹介され、それに合わせてReactコンポーネントもAtoms, Molecules, Organisms, Templates, Pagesの5種類に分類することが推奨されています。

実は、この章の残りはツール紹介です。具体的には、styled-components, Storybook, React Testing Libraryの使い方が説明されます。コンポーネントの書き方そのものというよりは、実務の現場でコンポーネント開発のために使われるツールの説明にも重きが置かれています。

ここで挙げられているツールに関しては、styled-componentsが意外な選択だと思いました。この系統のライブラリはSSRにあたって追加の手当てが必要で、本書でもそれは説明されています。入門にはあまり向かないような気もしますが、本書では実務の状況に合わせてライブラリをどんどん入れていく方針を採っているのでそこはあまり問題ではなさそうです。ただ、詳しくは6章のところで説明しますが、正直なところ、本書のやり方とstyled-componentsはあまり合っていなかったのではないかと思います。

React Testing LibraryについてはgetByRolegetByLabelTextなどを中心に据えた説明がされているのが良いです。しかし、第6章で実際に実践する段になるとこれらを活かせておらず、getByTestIdばかり使われているのは惜しいところです。

5章 アプリケーション開発1 〜設計・環境設定〜

ここからは、練習としてECサイトをNext.jsで作ってみる構成となります。紙面を占めるコードの量がかなり多くなりいわゆる「写経」感が増してきます(もちろん手打ちせずサポートサイトからソースコードをダウンロードすることも可能です)。まず、これから作るサイトの説明がユースケース図やアーキテクチャ図を通して説明されます。バックエンドのAPIはNext.js外の別のサーバーに用意される想定となっており、実務に近い本格的な設定です。また、題材となるアプリケーションもSSR・SSGなどを使い分ける必要があり工夫されています。

また、この章ではアプリケーション開発に向けて開発環境をセットアップし直します。Next.jsやstyled-components、ESLint、Storybookのセットアップに加えて、新たな仲間としてReact Hook FormとuseSWRとMaterial Iconsがパーティに加わります。また、React Content Loaderというライブラリも導入されます(筆者はこのライブラリは知りませんでした)。

基本的に環境構築するだけの章ですが、eslint-plugin-prettierの使用が推奨されている(p188)のは気になりました。PrettierをESLintプラグイン経由で利用するのはもう推奨されていない方法です。環境構築を簡単にするためといった理由があればこのプラグインを使うこともあるかもしれませんが、本書の環境構築は本格的で複雑なものが想定されているので、Prettierも最適な方法で入れてあげたほうがよいと思いました。これも既存のプロジェクトにメンバーとして入るなら問題ありませんが、自分がプロジェクトを立ち上げる際には最新情報を収集しましょう。

章最後のコラムではstyled-components以外のCSS in JSライブラリが紹介されていますが、選び方における観点として「捨てやすさ」が挙げられているのが渋いと思いました。CSS in JSライブラリに限らず、ライブラリを選ぶときは捨てやすさの考慮も必要です。著者らの経験が光る記述です。

6章 アプリケーション開発2 〜実装〜

本書のメインとなる章です。全章で構築された環境の上に実際にアプリケーションを作っていきます。前述のAtomic Designでの粒度が小さい方のコンポーネントから作っていく、必要に応じてutilも惜しみなく作るなど実践的な内容が目を引きます。

APIクライアント

まず最初にAPIクライアントを作っているところに感心させられました。さすがにAPIスキーマベースの型生成定義とかまでは行きませんが、APIエンドポイントごとに関数を用意して型がちゃんと定義されているというのは入門としては十分以上に思います。

styled-components上に実装されたutilコンポーネント

ただ、次の6.3「コンポーネント実装の準備」の内容には、正直度肝を抜かれました。ここでまずレスポンシブデザインについての説明があり、それをstyled-components上で簡単に書くためのutilを作成するために15ページくらい割きます。成果物は次のように使えるコンポーネントです。

<Box marginTop="10px">
  上に10pxのマージンがある
</Box>
<Box marginTop={1}>
  themingされた値を使用(1 = 8px)
</Box>
<Box marginTop={{base: 1, md: 2 }}>
  画面サイズに応じてレスポンシブに値を変える
</Box>

ここではBox, Flux, Grid が用意され、それらの基となるutilが整備されます。このutilはこれから他のコンポーネントを作る際にも使われます。

marginTop={1}の用法や、そもそもAtomic Designが言及されていることから分かるように、デザインシステムを念頭に置いた設計がされています。そうなると、ひとつ思うことがあります。それは、「Tailwind CSSでいいのでは?」ということです。かなり色々とコードを書いてようやく達成されたゴールが、Tailwind CSSとあまり変わらないように見えます。

styled-componentsが好きなのであればそれをベースにこのようなデザインシステム向けコンポーネントを構築しても構いませんが、入門書の内容としてこのような実装をベースに据えるのは問題があると感じます。実装自体にはジェネリクスなども関わっておりTypeScriptの練習としては面白いのですが、やっていることはReact.CSSPropertiesの再実装のようなことも多分に含まれており、さすがにボイラープレートが多すぎて入門書でやる意義が薄く、他の現場に応用できる可能性も低いと感じました。

採用されるCSS技法は現場によって様々だし、実は筆者個人としてはTailwind CSSはあまり好きではないのですが、それでもこの方針でやるのであれば素直にTailwind CSSを使っておくほうが、入門書としては良かったのではないかと思います。そのほうが同じゴールを簡潔に達成して読者が本題に集中できる上に、他プロジェクトへの応用性も独自utilよりは高いと思います。

また、のちのち6章のコードを読んでいくと、これらのutilはあまり良い働きをしていません。OrgamismやPageといった大きな粒度のコンポーネントからもこれらのutilが自在に使用され、Atomic Designの利点をかなり失わせているように見えます。

Atomic Designにしたがったコンポーネント分類と作成

このあとは、具体的なコンポーネントを作っていきます。まず画面の要件を見てどのような分類に属するどんなコンポーネントがあるかを検討するという流れは、(自分はあまりやったことがありませんが)再現しやすいプラクティスだと思います。

そのあとはソースコードが本の主なコンテンツとなり、合間に簡単な説明が入ります。

まずは一番小さい部品であるAtomsから作っていくのですが、筆者があまりAtomic Designに詳しくないこともあり、正直なところ、本書の内容がAtomic Designを正しく実践しているのかよく分かりません(Atomic Designに唯一の正解があるものでもないでしょうが)。

例えば、最初に作られたButtonというAtomは、variantというpropに3種類の文字列を渡すことができ(例: <Button variant="primary" />)、それに応じてあらかじめ定義されたスタイルが切り替わります。いい感じですね。それに加えて、このコンポーネントはfontSize, fontWeight, letterSpacing, display, marginTop, marginRightなど全24種のpropsを受け取ってスタイルを自由にカスタマイズできるとても使い勝手がよいコンポーネントとなっています。このことや前述の独自utilを使っていることも合わせて、このButtonというAtomは実装が3.5ページ分ある迫力あるAtomとなっています。

Atomic Designがどうとか以前に、デザインを責務とするコンポーネントで、デザインシステムを志向するのであれば、あまり自由にカスタマイズできるのはコンポーネント設計としてよろしくないのではないかと筆者は思います。識者のコメントをお待ちしています。

他にTextもめちゃくちゃ自由度の高いAtomとして実装されますが、それ以外(ShapeImageInputなど)は普通の感じです。

次にMoleculesの実装ですが、ここも自身でロジックを持たず、Atomよりは複雑な内容をAtomを使いながら表現する層となっています。ここは特筆することはとくにありませんが、コンポーネント設計の方針が定まっておらずとくに説明もない点は気になりました。例えばドロップダウンリストを表すDropdownというMoleculeはpropsで選択肢を渡すようになってる一方で、パンくずリストを表すBreadcrumbは要素一覧を渡すのではなくただのラッパーとなっており、中身を表すBreadcrumbItemというAtomを子として使う側で渡す必要があります。

Organisms, Templates, Pagesについても同様の構成で進みます。ここに関しては、Header(p294)など、せっかく作ったAtomやMoleculeを使わずに末端までスタイリングされているコンポーネントが色々と見られるのが残念です。Atomic Designやデザインシステム全般、コンポーネント分類法などについても、この本だけを参考にするのではなくさまざまな情報を収集することを推奨します。

コンポーネントのユニットテスト

この章の最後の内容としてコンポーネントのユニットテストが追加されます。DOM操作に対する反応を見るという標準的なユニットテスト方法で、具体的なコンポーネントに対してテストの書き方を学べるのはとても良いです。ただ、6章で書かれたコードはアクセシビリティがあまり意識されていないため、data-testidまみれになってしまうのが惜しいところです。実際には、なるべくdata-testidに頼らなくてすむようにマークアップを改善したほうがよいでしょう。

7章 アプリケーション開発3 〜リリースと改善〜

付録を除くと最後の章となるこの章では、まずHeroku, Vercel, Logflareといったサービスにアプリケーションを実際にデプロイしてみます。やはり作ったアプリが実際の環境で動作すると嬉しいですね。

また、SEO対策として、構造化データをページに付与する方法やOGP、sitemap.xmlの生成などを取り扱います。構造化データがここで出てくるのはなかなかよいと思いました。

さらに、ここにきてアクセシビリティが説明されます。内容はHTMLとアクセシビリティの関連についての標準的な内容で、やや辞書的な説明にはなっていますがこれに紙面を割いてくれるのはありがたいことです。

ただ、6章で実際にたくさんコードを書いてからアクセシビリティが出てくるせいで、本書の大部分を占める6章のコードはほとんどアクセシビリティの考慮がされていません。最低限リンクにはa要素を使う、ボタンにはinputやbuttonを使うといった程度で、よく見てみるとdivにonMouseDownを設定している箇所などが見受けられます。現在Webフロントエンドにおけるアクセシビリティは非常に重要ですから、できればもっと早くこれを説明して6章で実践する形にしてくれたらよかったと思います。アクセシビリティにちゃんと配慮すると実装量が必然的に増えてしまうのが仕方ない点ではありますが、それも含めてフロントエンドです。本書のようにおまけのように説明されている程度だと、興味を持った読者が自分で調べるか、幸運にも現場で教えてもらえるかしなければ、アクセシビリティへの配慮は身につかないでしょう。

他のトピックとしては、セキュリティについてもここで説明されています。XSSとかCSRFとかいったことですね。これはフロントエンドエンジニアなら覚えておいて損がない内容です。また、関連してセキュリティに関するHTTPヘッダも解説されています。ただ、X-Frame-OptionsとContent-Secrurity-Policyが両方説明されているなど、正しく理解した上で説明されているのか怪しい箇所もあり、参考にしようとしている読者は一通り自分で調べるのが賢明です(おそらく執筆期間中にIEが終了したのでその兼ね合いかもしれませんが)。

Appendix Next.jsのさらなる活用

この章では決済周りなどいくつかの外部サービスとの連携方法が書かれていますが、省略します。

この本に書かれていないこと

以上がこの本の内容の概観です。問題と思われる箇所も多少ありましたが、自分が本書に関して気になったことは、コンポーネントの設計があまり重視されていないことです。ここでいう設計とは特に、コンポーネントのインターフェースをどのようにするかということです。

例えば、画像の表示をつかさどるMoleculeであるImagePreview(p282)では、画像のURLを表すsrc(とついでにalt)がオプショナルなpropとなっています。画像の表示を責務としているのに表示する画像が無いかもしれないというのはインターフェースの設計として正しくありません。

このような、コンポーネントのインターフェースの切り方という部分が本文でも触れられず、サンプルコードでも考慮されていない箇所が多いのは、教材としてはよろしくない点だと思います。総評として「本書で到達できるレベルは『とりあえず動く』である」としたのはこのような背景から出た感想です。著者らを「フロントエンドの専門家ではない」と述べたのも、フロントエンドの基盤的な知識が見られないだけでなく、このような一定以上のレベルの知見が本文やサンプルコードから見出しにくいからです。

ちなみに、HTMLやCSSについても必要な部分だけ最小限解説されるスタイルです。本を読む際もある程度自分で調べながら読む必要があるでしょう(この本では詳しくは公式ドキュメントで、という流し方を多用しています。個人的には好きなスタイルです)。

まとめ

技術的負債に関して、負債とは借り入れるものであるから、一時の開発スピードを得るたびに借りること自体は悪くなく、あとで返せばいいのだとよく言われます。

この本は、借りるフェーズでスピードが求められる人たちにとって役立つのかもしれません。実際にReactのコードを触って直せるようになるという点ではこの本のコストパフォーマンスは悪くないと思います。

一方で、この本だけを読んでも返すフェーズができる人間になるのは難しいでしょう。質がよくメンテナンス可能なアプリケーションを作るにあたっては、「とりあえず動く」はゴールではなくスタート地点です。この本から入門したとしても、現場でしごかれるか、あるいはさらに勉強を重ねる必要があります。

書評は100点満点で点数を付けることにしているのですが、この本は30点とします。同じ出版社から本を出した手前申し訳ないのですが、嘘はつけません。筆者の持論としては、たとえ入門者向けでも記述やサンプルコード等はできる限り高いクオリティで提供すべきだと考えていますが、この本はその面が弱く筆者の好みから大きくずれています。具体的には、うっかりミスを超えた範囲の間違いが見られることや、デザインシステム周りの実装が応用性を欠いて本のコンセプトからずれており、それに伴ってサンプルコードの質も落ちていること、そして「返す側」へとステップアップするための取っ掛かりとなる知見に乏しいことが理由となります。

※点数は筆者の主観によるものです。


  1. 本書で解説対象としているReactのバージョンは明記されていませんが、本文でcreateRootの解説がありReact 18のStrictModeに言及するコラムもあることからReact 18を採用していることが分かります。
  2. 歴史的経緯としては間違いとは言えませんが、preactではclassを普通に使えることを考えると現状に沿った説明ではありません。
  3. webpackはバンドラであり、JSXからJavaScriptへの変換を担当するのはトランスパイラです。