はじめに
第1章 Node.jsを使ったビルド環境整備
第2章 Babelを使ったトランスパイル
第3章 TypeScriptを使ったコンパイル
第4章 webpackを使ったバンドルとビルド
第5章 ESLintを使った静的解析
第6章 Prettierを使ったフォーマット
第7章 Storybookを使ったコンポーネント管理
第8章 Jestを使ったテスト
第9章 0から環境を作ってみる
付録A バージョンの追従
さいごに
本書は、コピー&ペーストに頼らない環境構築ができるようになるための本です。技術書典応援祭1で出版した、「JavaScript環境構築の設定をひとつずつ丁寧に-そのプラグインってどうして必要なの!?-2」という同人誌が原案になっています。私自身がフロントエンド環境構築がとても苦手で、克服するために勉強したことを、その同人誌にまとめました。私はそのときの執筆やレビューを通して、なぜそのツール・プラグインが必要なのか を明らかにすると、理解が深まることに気付きました。そこで、「プラグインの役割に着目しながら、環境構築をおさらいできるような教材を作れないか」と思い、本書を執筆しています。本書が、環境構築が苦手という方にとって、よき教材や手引きとなればうれしいです。
フロントエンドにおける環境構築は、年々複雑化しています。昔は、スクリプトタグでライブラリを読み込むだけで、開発に必要なものをそろえていました。しかし今では、ビルドや静的検証のパイプラインを構築する、といったこともするようになっています。それに伴い、Package Manager、Transpiler、Bundler、Linter、Formatter、Test Runner、AltJSなど、たくさんの周辺ツールも生まれました。もちろん、ビルドという観点だけで見ると全部は不要ですが、開発効率を上げるという点では、押さえておきたいツールたちです。それらを押さえた上で、ビルドのパイプラインを組み立てることが要求されることもあり、ただHello Worldするだけの難易度は上がっています。
環境構築に要求されるツールが増える一方で、便利なプリセットも生まれており、簡単に構築を済ませられるツールも生まれています。たとえばcreate-react-appやNext.jsは、環境構築を代替できる便利なツールです。しかし、手組みで環境構築した経験がなければ、いざ手組みで整備しなければいけなくなった場合に苦労します。もしかしたら、将来的にビルドを別のツールと連携しながら行うことや、何らかの最適化を行うことが必要になってくるかもしれません。そのような事態に備え、環境構築は手組みでゼロからできるようになっておいた方が良いと、筆者は考えています。
そこで、環境構築スキルの習得を目指していきたいのですが、挫折するポイントが多く潜んでいます。そのため、独学では困難だと、筆者は感じています。
そもそも、仕事で環境構築をする機会は少ないです。環境構築を行う時期は、プロジェクトが立ち上がるときか、非機能要件の磨き込みに時間を割けるときです。
環境構築をデバッグするためには、ある程度が動くようにしてからではないと難しいです。そのため、どこが原因で動かないかという原因の切り分けがしづらい分野です。デバッグの末に、仮にビルドに成功しても、どの修正によって成功したかの判断がつかないこともあります。たとえば、「実は間違ったことをしていたけど、ビルドだけは通るようになった」ということもあります。
そこで本書では、環境構築に挑戦したい人に向けて、少しずつ動かしながら「こう設定すればこうなる」を理解できるような説明を心がけました。
そのため本書は、ビルド設定に困っている、自分でもビルド環境を作れるようになりたいという方向けに書かれており、JavaScript の初学者に向けては書かれていません。なるべく基本的な用語や概念も解説するようにはしましたが、それでも説明不足に感じるところがあるかもしれません。
また、各章は独立しているため、自分の読みたい章から読めます。ただし、環境構築の全体感を想像できない方は、最初から読むことをお勧めします。第9章の「0から環境を作ってみる」は、いわゆる「やってみた」という内容で、実践的なハンズオンです。写経をすれば、全体の雰囲気をつかむことができるでしょう。ソースコードも公開しています。3
タイトルではReactを扱うと書いていますが、ここで紹介するツールやエコシステムは、React以外のフレームワークやライブラリを使った開発においても使われているものです。Reactを使わない開発者にとっても、CLIやプリセットに頼らない開発をする場面では、本書が役に立つかもしれません。もし気になる場合は、目次を確認してください。
本書では、フロントエンドアプリケーションのビルドと検証をするための方法を学びます。各章では次のような内容を扱います。
・実行基盤となるNode.js(エコシステムの基盤)
・Babelによるトランスパイル(ビルド)
・TypeScript Compilerによるトランスパイル(ビルド)
・webpackによるバンドル(ビルド)
・ESLintによるリント(検証)
・Prettierによるフォーマット(検証)
・Jestによるテスト(検証)
・Storybookによるコンポーネント管理(検証)
環境構築に登場するツールの役割は、大きくビルドか検証ツールかに分けられ、それぞれに代表的なライブラリが存在します。そのライブラリの数はさほど多くはありませんが、それらに多くのプラグインを挿していくので、結果的には利用するライブラリの数が膨大になります。ビルド複雑化の原因は、大量に挿すプラグインにあると言っても過言ではありません。本書では、プラグインを挿される側のライブラリの粒度で、章を分けて整理します。そして、それぞれで利用するプラグインの役割を紹介していくことで、説明を図っています。そのため、章ごとにツールとプラグインの役割を確認しながら読み進めると、役割に関する混乱は緩和できます。
・筆者のPC環境は、macOS Catalina(Version:10.15.2)です。Node.jsの環境はv12.16.3で、nvm(v0.35.3)で管理しています。
・第9章は、完全な形でのサンプルコード4を提供しています。本書で使ったライブラリのバージョンは、ここに書かれているpackage.jsonのものです。
・各章ではコマンドの出力を表記していますが、誌面の都合で適宜編集を加えています。
・クレスウェア代表の奥野賢太郎さん(@okunokentaro)、長年TypeScriptを利用されている経験や、過去の執筆経験からアドバイスをいただき、ありがとうございました。レビューを通してお互いに異なる方針を持っていたことがわかり、それを議論できたことも楽しかったです。
・TechBowl CEOの小澤政生さん(@zawamasa)、日本最大級のエンジニアコミュニティTechTrain のメンターやメンティーにレビューを依頼できる仕組みを作ってくださり、ありがとうございました。上級者の方から初級者の方まで、幅広い意見を取り入れることができ、とても助かりました。
・TechTrainメンターの、大木優さん(@gurusu_program、株式会社TechBowl)、今川裕士さん(@ug23_、弁護士ドットコム株式会社)、徳田祥さん(@haze_it_ac)、寺嶋祐稀さん(@y_temp4)、吉野雅耶さん(@ayasamind、株式会社Fusic)、ありがとうございます。日ごろの業務の経験談にもとづいたアドバイスをいただき、ブラッシュアップさせていくことができました。
・TechTrain メンティーの門田朋己さん(@tmk815)、tktcorporationさん(@tktcorporation)、西田吉克さん(@nsd244)、小越雄太さん(@ykotti1)、ありがとうございます。説明や手順の不足を指摘していただいたことで、当初の荒削りな原稿を読みやすくできました。特に小越雄太さんには実際に説明やコードの検証をしていただいたことで、執筆する上での不安を和らげることができました。本当にありがとうございます。
Node.js®は、ChromeのV8 JavaScriptエンジンで動作するJavaScript環境です。1Node.jsは、サーバやCLIツールとして使われています。クライアントサイドJavaScriptの環境構築は、このNode.jsのエコシステム上で行います。本章では、そのNode.jsについて学びます。
Node.jsは、公式HP2からダウンロードできます。各プラットフォームごとにインストーラが用意されており、インストールできます。また、公式HPではHomebrewなどのパッケージマネージャーを使ったインストール方法も紹介されています。本書はNode.js v12.16.3を利用しますが、releaseページ3からバージョンを細かく指定して、ダウンロードすることもできます。4ご自身にあった手法でインストールしてください。
また、公式にのっとった方法ではありませんが、バージョンマネージャーを使っても良いです。本書はNode.js v12.16.3を利用しますが、バージョンマネージャーを使うと、該当バージョンをピンポイントで入れることが容易になります。既にNode.jsを持っている人にとっては、該当バージョンへの切り替えが容易になるメリットもあります。5Node.jsのVersion Managerには、さまざまなものがありますが、筆者はnvm6を利用しています。本書ではnvmのインストール方法や利用方法は説明しませんが、詳しいことはnvm公式に全て書かれているため、そちらを参照してください。7
JavaScriptプロジェクトはpackage.jsonと呼ばれるファイルで、その構成を管理します。このファイルではたとえば、次の項目を管理できます。
・パッケージ名
・バージョン
・依存ライブラリ
・エントリポイント
・script
・ライセンス
依存ライブラリをpackage.jsonファイルで管理できるため、Gitの管理下に含めておくと、依存ライブラリの更新や、その更新に失敗した際の差し戻しが容易になります。またパッケージ名・バージョン・エントリポイントは、プロジェクト自体をライブラリとして提供する際に、利用者が参照する大切な情報です。たとえば、nameはそのままnpm公式サイトでのパッケージの検索に使われます。開発やエコシステムとの連携という観点で、このファイルはとても大切なものです。
package.jsonは、npm initコマンドで作成できます。もちろん、ただのjsonファイルなので、すべて手書きしても問題ありません。
$ npm init
このコマンドを実行すると、次のようなファイルが作成されます。
{
"name": "npmtst",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
}
Node.jsには、npmと呼ばれるpackage managerとコマンドが付随しています。8このnpmを使うことで、ライブラリをダウンロードできます。
npmを使ってpackageを追加します。npm install reactなどとすれば、packageを入手できます。
どのようなpackageを保存したか9は、package.jsonに記録され、packageの実体は node_modulesというフォルダに保存されます。またそのpackage自体が持つ依存の管理には、package-lock.jsonファイルが使われます。これはlockファイルと呼ばれているものです。そのためpackage.jsonとpackage-lock.jsonさえあれば、node_modulesを削除しても環境を再現できます。
# package.jsonとpackage-lock.jsonを元にpackageをDLしてnode_modulesに保存する
$ npm install
パッケージを追加するとpackage.jsonが次のようになります。たとえば、reactを追加したときはこのようになります。
{
"dependencies": {
"react": "^16.13.1"
}
}
これはreactを依存として含めることを意味します。
一方で、このようなpackage.jsonもあります。
{
"devDependencies": {
"typescript": "^3.8.3"
}
}
ここでの違いは、dependenciesかdevDependenciesかという違いです。devDependenciesに指定されているpackageはdependenciesと違って、このプロジェクト自体がライブラリとして使われる際に依存を含めません。今回の例だと、TypeScriptコンパイラは開発用のツールであり、ライブラリとしての機能には関わってきません。そのため、dependenciesではなくdevDependenciesに指定します。このように開発時のみに使うツールかどうかで、dependenciesとdevDependenciesを使い分けます。全部dependenciesに含めると、ライブラリとして使われるときに利用者に不要なインストールを強いることになるため、気を付けましょう。devDependenciesとしてライブラリをダウンロードするためには、-Dオプションを使います。
$ npm install -D typescript
ここまでに出てきた、ライブラリをダウンロードするために利用するnpmコマンドを復習していきます。
# アプリで使うライブラリとしてreactをDL
$ npm install react
# 開発用ライブラリとしてTypeScriptをDL
$ npm install -D typescript
# package.jsonとpackage-lock.jsonを元に、そのプロジェクトに必要なライブラリをすべてDL
$ npm install
# installと打たなくても短縮形が使える
$ npm i