パッケージ管理の基本 - ウェブ開発を学ぶ

パッケージ管理の基本
==========

* 前のページ
* Overview: Understanding client-side tools
* 次のページ

この記事では、パッケージマネージャーを詳細に見て、プロジェクトツールの依存関係をインストールし、それらを最新の状態に保つなど、独自のプロジェクトでパッケージマネージャーを使用する方法を理解します。

|  |  |
| --- | --- |
| 前提条件： | 主要な HTML、CSS、と JavaScript 言語 |
| 目的： | パッケージマネージャーとパッケージリポジトリーとは何か、必要な理由や使用方法の基本を理解する。 |

プロジェクトの依存関係
-----------

**依存関係**とは、サードパーティ製のソフトウェアであり、おそらく他の誰かによって作成されたものであり、理想的には 1 つの問題を解決してくれます。ウェブプロジェクトには、0 から多数の範囲で任意の数の依存関係を含めることができます。また依存関係には、明示的にインストールしていないサブ依存関係が含まれる場合があります。依存関係には、独自の依存関係がある場合があります。

プロジェクトで必要になる可能性のある便利な依存関係の簡単な例は、相対日付を人間が判読できるテキストとして計算するコードです。もちろん自分でコーディングすることもできますが、他の誰かがすでにこの問題を解決している可能性が高いです。さらに、信頼できるサードパーティの依存関係は、さまざまな状況でテストされている可能性が高く、独自のソリューションよりも堅牢でクロスブラウザー互換性があります。

プロジェクトの依存関係は、React や Vue などの JavaScript ライブラリーまたはフレームワーク全体、または人間が読める日付ライブラリーのような非常に小さなユーティリティ、または以前の記事で説明した Prettier や ESLint などのコマンドラインツールである可能性があります。

最新のビルドツールがなければ、単純な `<script>` 要素を使用して、このような依存関係をプロジェクトに含めることができますが、これはすぐには機能しない可能性があります。また、コードと依存関係がウェブ上にリリースされるときに、コードと依存関係を一緒にバンドルするための最新のツールが必要になる可能性があります。バンドルとは、通常、ソフトウェアのすべての JavaScript を含むウェブサーバー上の単一のファイルを指すために使用される用語です。通常、ソフトウェアをダウンロードしてブラウザーの訪問者に表示にかかる時間を短縮するために、可能な限り圧縮されています。

さらに、現在のツールの代わりに使用したいより良いツールを見つけた場合、または更新したい依存関係の新しいバージョンがリリースされた場合はどうなりますか? これは、いくつかの依存関係についてはそれほど苦痛ではありませんが、多くの依存関係がある大規模なプロジェクトでは、この種のことを追跡するのが非常に困難になる可能性があります。npm などの **パッケージ マネージャー** を使用する方が理にかなっています。これにより、コードがクリーンに追加および削除され、他の多くの利点が得られることが保証されます。

パッケージマネージャーとは正確には何ですか？
----------------------

npm については既に触れましたが、npm 自体から離れて、パッケージマネージャーはプロジェクトの依存関係を管理するシステムです。

パッケージマネージャーは、新しい依存関係 (「パッケージ」とも呼ばれます) をインストールする方法を提供し、ファイルシステム上のパッケージの保存場所を管理し、独自のパッケージを公開する機能を提供します。

理論的には、パッケージマネージャーは必要なく、プロジェクトの依存関係を手動でダウンロードして保存することもできますが、パッケージマネージャーはパッケージのインストールとアンインストールをシームレスに処理します。使用していない場合は、手動で処理する必要があります。

* すべての正しいパッケージ JavaScript ファイルの検索。
* それらをチェックして、既知の脆弱性がないことを確認します。
* それらをダウンロードして、プロジェクト内の正しい場所に配置します。
* アプリケーションにパッケージを含めるためのコードを作成します (これは、よく読んで理解する価値のあるもう 1 つの主題である JavaScript モジュール モジュールを使用して行われます)。
* すべてのパッケージのサブ依存関係 (数十または数百になる可能性があります) に対して同じことを行います。
* パッケージを削除する場合は、すべてのファイルを再度削除します。

さらに、パッケージマネージャーは重複した依存関係 (フロントエンド開発で重要かつ一般的になるもの) を処理します。

npm (と JavaScript と Node ベースのパッケージマネージャー) の場合、依存関係をインストールする場所には 2 つのオプションがあります。前回の記事で触れたように、依存関係はプロジェクトにグローバルまたはローカルにインストールできます。グローバルにインストールする方がメリットが多い傾向にありますが、コードの移植性やバージョンのロックなど、ローカルにインストールする方がより重要です。

たとえば、プロジェクトが特定の構成の Webpack に依存している場合、そのプロジェクトを別のマシンにインストールしたり、後でそのプロジェクトに戻ったりした場合でも、構成が引き続き機能することを確認する必要があります。異なるバージョンの Webpack がインストールされている場合、互換性がない可能性があります。これを軽減するために、依存関係がプロジェクトにローカルにインストールされます。

ローカルの依存関係が本当に輝いていることを確認するには、既存のプロジェクトをダウンロードして実行するだけです。ーそれが機能し、すべての依存関係が箱から出してすぐに機能する場合、コードが移植可能であるという事実に感謝するローカル依存関係があります。

**メモ:** 利用可能なパッケージマネージャーは npm だけではありません。成功し、人気のある代替パッケージマネージャーは Yarn です。Yarn は別のアルゴリズムを使用して依存関係を解決します。これは、より高速なユーザー エクスペリエンスを意味します。pnpm など、他の多くの新しいクライアントもあります。

パッケージレジストリー
-----------

パッケージマネージャーが機能するには、どこからパッケージをインストールするかを知る必要があり、これはパッケージレジストリーの形式で提供されます。レジストリーは、パッケージが公開され、そこからインストールできる中心的な場所です。npm は、パッケージマネージャーであるだけでなく、JavaScript パッケージで最も一般的に使用されるパッケージ レジストリーの名前でもあります。npm レジストリーは npmjs.com にあります。

npm だけが選択肢ではありません。独自のパッケージ レジストリーを管理できます。Microsoft Azure などの製品を使用すると、npm レジストリーへのプロキシを作成できます (特定のパッケージをオーバーライドまたはロックできます)。GitHub もパッケージレジストリーサービス提供しています。 であり、時間が経つにつれてより多くのオプションが表示される可能性があります。

重要なのは、自分に最適なレジストリーを選択したことを確認することです。多くのプロジェクトで npm が使用されるため、モジュールの残りの例ではこれに関係します。

パッケージエコシステムの使用
--------------

パッケージマネージャーとレジストリーを使用してコマンドラインユーティリティをインストールするための例を見てみましょう。

Parcel は、開発者が開発プロセスでよく使用する別のツールです。Parcel は、依存関係の呼び出しについてコードの内容を監視し、コードが必要とするすべての依存関係を自動的にインストールするという点で賢いです。また、コードを自動的にビルドすることもできます。

### アプリを npm パッケージとしてセットアップする

まず、実験的なアプリを保存するための新しいディレクトリーを作成します。これを parcel-experiment と呼びますが、好きなように呼ぶことができます。

```bash
mkdir parcel-experiment
cd parcel-experiment
```

次に、構成ファイルを作成する npm パッケージとしてアプリを初期化しましょう — `package.json` — これにより、後でこの環境を再作成したり、パッケージを npm レジストリーに公開したりする場合に備えて、構成の詳細を保存できます (ただし、これはこの記事の範囲を超えています)。

`parcel-experiment` ディレクトリー内で、次のコマンドを入力します。

```bash
npm init
```

ここで、いくつか質問されます。npm は、回答に基づいてデフォルトの `package.json` ファイルを作成します。

* `name`: アプリを識別するための名前。
 `Return` を入力するとデフォルトの `parcel-experiment` がアプリ名になります。
* `version`: アプリの開始バージョン番号。
 再度 `Return` を入力するとデフォルトの `1.0.0` がアプリの開始バージョン番号になります。
* `description`: アプリの目的の簡単な説明。
 「npm の使い方を学ぶための簡単な npm パッケージ」など、非常に簡単なことを入力してから、 `Return` を入力します。
* `entry point`: これは、アプリの最上位の JavaScript ファイルになります。
 今のところデフォルトの `index.js` で問題ないので `Return` を入力します。
* `test command`, `git repository`, と `keywords` :
 それぞれを入力する時は、空白のままにして `Return` を入力します。
* `author`: プロジェクトの作成者。
 自分の名前を入力し、`Return` を入力します。
* `license`: パッケージを公開するためのライセンス。
 ここではデフォルトを設定するので `Return` を入力します。

これらの設定を受け入れるためにもう一度 `Return` を入力します。

`parcel-experiment` ディレクトリーに移動すると、package.json ファイルが作成されていることがわかります。それを開くと、次のようになります。

```json
{
  "name": "parcel-experiment",
  "version": "1.0.0",
  "description": "A simple npm package to learn about using npm",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Chris Mills",
  "license": "ISC"
}
```

したがって、これはパッケージを定義する構成ファイルです。今はこれでいいので、先に進みます。

### Parcel のインストール

次のコマンドを実行して、Parcel をローカルにインストールします。

```bash
npm install parcel-bundler
```

上記コマンドが全て完了すると、「最新のクライアント側開発」の準備が整います (これは、ビルドツールを使用して、開発者のエクスペリエンスを少し簡単にすることを意味します)。ただし、まず最初に、package.json ファイルをもう一度見てください。npm が新しいフィールドの依存関係を追加したことがわかります。

```json
"dependencies": {
  "parcel-bundler": "^1.12.4"
}
```

これは npm マジックの一部です。将来、コードベースを別の場所、別のマシンに移動した場合、コマンドを実行して同じセットアップを再作成できます。`npm install` を実行すると npm が依存関係を調べてインストールします。

欠点の 1 つは、Parcel が `parcel-experiment` アプリ内でしか利用できないことです。別のディレクトリーで実行することはできません。しかし、利点は欠点を上回ります。

### サンプルアプリのセットアップ

とにかく、セットアップを続けます。

Parcel は `index.html` と `index.js` ファイルが動作することを期待していますが、それ以外の場合、プロジェクトをどのように構築するかについて非常に意見がありません。他のツールは非常に異なる場合がありますが、少なくとも Parcel は最初の実験を容易にします。

そのため、 `index.html` ファイルを作業ディレクトリーに追加する必要があります。テストディレクトリーに `index.html` を作成し、次の内容を指定します。

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <title>My test page</title>
  </head>
  <body>
    <script src="./index.js"></script>
  </body>
</html>
```

次に、 `index.html` と同じディレクトリーに `index.js` ファイルを追加する必要があります。今のところ、 `index.js` は空で構いません。存在する必要があるだけです。これを今すぐ作成します。

### Parcel を楽しむ

次に、新しくインストールした Parcel ツールを実行します。ターミナルで、次のコマンドを実行します。

```bash
 parcel index.html
```

ターミナルに次のような出力が表示されるはずです。

```bash
Server running at http://localhost:1234
✨  Built in 193ms.
```

**メモ:** 「command not found」エラーをターミナルが返す場合は、上記のコマンドを `npx` ユーティリティ、つまり `npx parcel index.html`で実行してみてください。

これで、完全な JavaScript パッケージ エコシステムを活用する準備が整いました。まず、 `http://localhost:1234` で実行されているローカルウェブサーバーがあります。ここにアクセスすると、今のところ何も表示されませんが、すばらしいのは、アプリに変更を加えると、Parcel がアプリを再構築してサーバーを自動的に更新するため、更新の効果をすぐに確認できることです。

次に、いくつかのページ コンテンツについて説明します。「2時間前」、「4日前」など、人間が読める相対的な日付を表示したいとしましょう。`date-fns` パッケージの `formatDistanceToNow()` メソッドは役立ちます (同じことを行う他のパッケージもあります)。

`index.js` ファイルに次のコードを追加して保存します。

```js
import { formatDistanceToNow } from "date-fns";

const date = "1996-09-13 10:00:00";
document.body.textContent = `${formatDistanceToNow(new Date(date))} ago`;
```

`http://localhost:1234` に戻ると、作者が 18 歳になってからどれくらい経ったかがわかります。

上記のコードで特に特別なのは、インストールしていない `date-fns` パッケージの `formatDistanceToNow()` 関数を使用していることです! Parcel は、モジュールが必要であることを発見し、 `npmjs.com` パッケージ レジストリーで検索して、自動的にローカルにインストールしました。これは、 `package.json` ファイルをもう一度見ることで証明できます — `dependencies` フィールドが更新されていることがわかります。

```json
"dependencies": {
  "date-fns": "^2.12.0",
  "parcel-bundler": "^1.12.4"
}
```

Parcel は、他の誰かがこのプロジェクトを取得し、使用した依存関係をインストールするために必要なファイルも追加しました。`parcel` コマンドを実行したディレクトリーを調べると、多数の新しいファイルが見つかります。最も興味深いものは次のとおりです。

* `node_modules`: Parcel と date-fns の依存ファイル。
* `dist`: 配布ディレクトリー — これらは、自動的にパッケージ化され、Parcel がビルドして縮小したファイルであり、 `localhost:1234` で提供されているファイルです。これらは、サイトを公開してオンラインで公開するときにウェブサーバーにアップロードするファイルです。

パッケージ名を知っている限り、コードでそれを使用でき、Parcel はパッケージをローカルディレクトリー (`node_modules` の下) に取り出し、フェッチし、インストール (実際には「コピー」) します。

### 本番用のコードの構築

ただし、このコードは本番用の準備ができていません。ほとんどのビルドツール システムには、「開発モード」と「プロダクションモード」があります。重要な違いは、開発で使用する便利な機能の多く、たとえば「hot module replacement」、「live reloading」、「uncompressed and commented source code」が最終サイトでは必要ないため、本番環境では取り除かれることです。すべてを網羅しているわけではありませんが、これらは一般的なウェブ開発機能の一部であり、開発段階では非常に役立ちますが、本番環境ではあまり役に立ちません。本番環境では、サイトが肥大化するだけです。

`Ctrl` + `C` を使用して、前の Parcel コマンドを停止します。

これで、架空の展開用に最小限のサンプルサイトを準備できます。Parcel は、発行に適したファイルを生成する追加のコマンドを提供し、build オプションでバンドル (前述) を作成します。

次のコマンドを実行します。

```bash
parcel build index.html
```

次のような出力が表示されるはずです。

```bash
✨  Built in 9.35s.

dist/my-project.fb76efcf.js.map    648.58 KB     64ms
dist/my-project.fb76efcf.js        195.74 KB    8.43s
dist/index.html                        288 B    806ms
```

繰り返しますが、本番ファイルのディレクトリーは、 `dist` です。

### アプリのファイルサイズを縮小する

ただし、開発者を「助ける」すべてのツールと同様に多くの場合、トレードオフがあります。この特定のケースでは、それはファイルサイズです。JavaScript バンドル my-project.fb76efcf.js はなんと 195K にもなり、1 行のテキストを出力するだけなので非常に大きいです。確かに多少の計算は行いますが、これを行うために 195K 相当の JavaScript は絶対に必要ありません!

開発ツールを使用するときは、それが正しいことを行っているかどうかを検討する価値があります。この場合、使用している関数だけでなく、実際には `date-fns` ライブラリー全体が含まれているため、バンドルはほぼ 200K になります。

開発ツールを一切使用せず、 `<script src="">` 要素を `date-fns` のホストされたバージョンに向けていた場合、ほぼ同じことが起こっていたでしょう — サンプルページのときにすべてのライブラリーがダウンロードされます。ブラウザーに読み込まれます。

ただし、ここで開発ツールが活躍する可能性があります。ツールがマシン上にある間、ソフトウェアにコードの使用を検査し、本番環境で実際に使用している関数のみを含めるように依頼できます。これは「ツリーシェーキング」と呼ばれるプロセスです。

これは、ファイルサイズを小さくしてアプリの読み込みをできるだけ速くしたいため、非常に理にかなっています。さまざまなツールを使用すると、さまざまな方法でツリーを振ることができます。

リストは月ごとに増えていきますが、ソース コードからバンドルを生成するツールには、Webpack、Rollup、および Parcel の 3 つの主なオファリングがあります。これ以外にも利用できるようになりますが、これらは人気のあるものです。

* RollUp ツールは、そのコア機能としてツリーシェイキングとコード分割を提供します。
* Webpack にはいくつかの構成が必要です (「一部」という表現は、一部の開発者の Webpack 構成の複雑さを過小評価している可能性があります)。
* (Parcel version 2 より前の) Parcel の場合、特別なフラグが必要です — `--experimental-scope-hoisting` — ビルド中にツリーシェークが発生します。

すでにインストールされていることを考えると、今のところ Parcel に固執しましょう。次のコマンドを実行してみてください。

```bash
parcel build index.html --experimental-scope-hoisting
```

これにより大きな違いが生じることがわかります。

```bash
✨  Built in 7.87s.

dist/my-project.86f8a5fc.js    10.34 KB    7.17s
dist/index.html                   288 B    753ms
```

現在バンドルは約 10K です。かなり良くなりました。

このプロジェクトをサーバーにリリースする場合、`dist` フォルダー内のファイルのみをリリースします。Parcel は、すべてのファイル名の変更を自動的に処理してくれました。Parcel が自動的に実行した変更を確認できるように、 `dist/index.html` のソースコードを確認することをお勧めします。

**メモ:** 執筆時点では、Parcel 2 はリリースされていませんでした。ただし、Parcel の作成者はツールに少し異なる名前を付けることに良識があったため、これらのコマンドはすべて引き続き機能します。Parcel 1.x をインストールするには、 `parcel-bundler` をインストールする必要がありますが、parcel 2.x は `parcel` をインストールします。

利用可能なツールはたくさんあり、JavaScript パッケージのエコシステムは前例のない速度で成長していますが、これには長所と短所があります。常に改善が行われており、良くも悪くも選択肢が増え続けています。圧倒的なツールの選択に直面した場合、おそらく最も重要な教訓は、選択したツールで何ができるかを学ぶことです。

パッケージマネージャークライアントの大まかなガイド
-------------------------

このチュートリアルでは npm を使用して Parcel パッケージをインストールしましたが、前述のようにいくつかの代替手段があります。少なくともそれらが存在することを知って、ツール間で共通のコマンドについて漠然とした考えを持つことは価値があります。すでにいくつかの動作を見てきましたが、他のものを見てみましょう。

リストは時間の経過とともに増加しますが、執筆時点では、次の主要なパッケージマネージャーが利用可能です。

* npm at npmjs.org
* pnpm at pnpm.js.org
* Yarn at yarnpkg.com

npm と pnpm は、コマンド ラインの観点からは似ています。実際、pnpm は、npm が提供する引数オプションと完全に同等であることを目指しています。パッケージをダウンロードしてコンピューターに保存する方法が異なり、必要な全体的なディスク容量を削減することを目的としています。

以下の例では npm が示されていますが、pnpm を入れ替えると、コマンドが機能します。

多くの場合、インストールプロセスに関しては、yarn は npm よりも高速であると考えられています(マイレージは異なる場合があります)。依存関係のインストール(およびコンピューターへのコピー)を待つためにかなりの時間が浪費される可能性があるため、これは開発者にとって重要です。

**メモ:** npm パッケージマネージャーは、同じ名前を共有していても、npm レジストリーからパッケージをインストールする必要は**ありません**。pnpm と Yarn は、npm と同じ `package.json` 形式を使用でき、npm およびその他のパッケージレジストリーから任意のパッケージをインストールできます。

パッケージマネージャーで実行する一般的なアクションを確認しましょう。

### 新しいプロジェクトを初期化する

```bash
npm init
yarn init
```

上記のように、これにより一連の質問が表示され、プロジェクトを説明するための一連の質問(名前、ライセンス、説明など) が表示されます。`package.json` プロジェクトとその依存関係に関するメタ情報が含まれています。

### 依存関係のインストール

```bash
npm install date-fns
yarn add date-fns
```

上記の動作で `install` も見ました。これにより、 `date-fns` パッケージが、 `date-fns` 自体の依存関係とともに、 `node_modules` と呼ばれるサブディレクトリー内の作業ディレクトリーに直接追加されます。

デフォルトでは、このコマンドは「date-fns」の最新バージョンをインストールしますが、これも制御できます。`date-fns@1` を要求すると、最新の 1.x バージョン (1.30.1) が得られます。または、`date-fns@^2.3.0` を試すこともできます。これは、2.3.0 以降 (執筆時点では 2.8.1) の最新バージョンを意味します。

### 依存関係の更新

```bash
npm update
yarn upgrade
```

これにより、現在インストールされている依存関係が調べられ、利用可能な更新がある場合は、パッケージで指定されている範囲内で更新されます。

範囲は、 `package.json` の依存関係のバージョンで指定され、 `date-fns@^2.0.1` — この場合、キャレット文字 `^` 2.0.1 以降、3.0.0 を除くすべてのマイナーおよびパッチリリースを意味します。

これは semver と呼ばれるシステムを使用して決定されます。このシステムはドキュメントから見ると少し複雑に見えるかもしれませんが、要約情報とバージョンが `MAJOR.MINOR.PATCH` 、たとえば 2.0.1 はメジャーバージョン 2 でパッチバージョン 1 です。semver 値を試す優れた方法は、semver Calculator を使用することです。

`npm update` は依存関係を `package.json` で定義された範囲を超えてアップグレードしないことを覚えておくことが重要です — これを行うには、そのバージョンを具体的にインストールする必要があります。

### 脆弱性の監査

```bash
npm audit
yarn audit
```

これにより、プロジェクトのすべての依存関係ツリーがチェックされ、使用している特定のバージョンが脆弱性データベースに対して実行され、プロジェクトに潜在的な脆弱なパッケージがあるかどうかが通知されます。

脆弱性について学習するための出発点として 、JavaScript パッケージと他のプログラミング言語の両方をカバーする Snyk プロジェクト をお勧めします。

### 依存関係のチェック

```bash
npm ls date-fns
yarn why date-fns
```

このコマンドは、インストールされている依存関係のバージョンと、それがどのようにプロジェクトに含まれるようになったかを示します。別の最上位パッケージが `date-fns` を取り込んだ可能性があります。プロジェクトに複数のバージョンのパッケージが存在する可能性も同様にあり得ます(そして理想的ではありません)(これは非常に便利な lodash パッケージで何度も見られます)。

パッケージマネージャーはパッケージの重複を排除するために最善を尽くしますが、インストールされているバージョンを正確に調査することをお勧めします。

### その他のコマンド

npm および yarn の個々のコマンドの詳細をオンラインで確認できます。繰り返しますが、pnpm コマンドは npm と同等であり、いくつかの追加があります。

独自のコマンドを作成する
------------

パッケージマネージャーは、独自のコマンドの作成とコマンドラインからの実行もサポートしています。たとえば、次のコマンドを作成できます。

```bash
npm run dev
# or yarn run dev
```

これにより、プロジェクトを「開発モード」で開始するためのカスタム スクリプトが実行されます。実際、ローカルでの開発セットアップは本番環境での実行方法とは若干異なる傾向があるため、すべてのプロジェクトにこれを定期的に含めています。

以前の Parcel テストプロジェクトでこれを実行しようとすると、(おそらく) 「dev script is missing」 と表示されます。これは、npm、Yarn (など) が `package.json` ファイルの `scripts` プロパティで dev というプロパティを探しているためです。

Parcel はコマンド `parcel serve filename.html` を使用して開発サーバーを実行できます。これを開発中に頻繁に使用したいと考えています。

それでは、`package.json` にカスタムの省略形コマンド「dev」を作成しましょう。

前のチュートリアルに従った場合は、パーセル実験ディレクトリー内に `package.json` ファイルがあるはずです。それを開くと、その `scripts` メンバーは次のようになります。

```json
"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1",
},
```

次のように更新し、ファイルを保存します。

```json
"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1",
  "dev": "parcel serve index.html"
},
```

カスタム `dev` コマンドを npm スクリプトとして追加しました。

ターミナルで次のコマンドを実行してみてください。`parcel-experiment` ディレクトリー内にいることを確認してください。

```bash
 npm run dev
```

これにより前に見たように、Parcel が起動し、ローカルの開発サーバーで `index.html` が提供されます。

```bash
Server running at http://localhost:1234
✨  Built in 5.48s.
```

さらに、npm (および yarn) コマンドは、プロジェクトにローカルにインストールされているコマンド ライン ツールを検索してから、従来の方法(コンピューターが通常ソフトウェアを格納して検索できるようにする場所)で検索するという点で優れています。`run` コマンドの技術的な複雑さについて詳しく知ることができますが、ほとんどの場合、独自のスクリプトは問題なく実行されます。

仕事をするのに役立つあらゆる種類のものを `scripts` プロパティに追加できます。私たちは確かに持っていますし、他も持っています。

まとめ
---

これで、パッケージマネージャーのツアーは終了です。次のステップは、これまでに学んだことをすべて実践して、ツールチェーンのサンプルを構築することです。

* 前のページ
* Overview: Understanding client-side tools
* 次のページ
こちらもご覧ください
----------

* npm スクリプト リファレンス
* package.json リファレンス


Svelte をはじめる - ウェブ開発を学ぶ

Svelte をはじめる
============

* 前のページ  (en-US)
* Overview: Client-side JavaScript frameworks
* 次のページ  (en-US)

この記事では Svelte というフレームワークの簡単な紹介を行います。Svelte の仕組みと、今までのフレームワークやツールとの違いを見ていきましょう。その後は開発環境の構築、サンプルアプリの作成、プロジェクトの構造、ローカル環境での実行方法と本番環境でのビルド方法を学びます。

|  |  |
| --- | --- |
| 前提条件: |
 最低限、主要な
 HTML と
 CSS、
 JavaScript
 に精通していて、
 ターミナル / コマンドラインに関する知識があることが推奨されます。

 Svelte はソースコードから最小かつ高度に最適化された JavaScript を生成するコンパイラーです。
 アプリのコンパイルとビルドには、node と npm がインストールされたターミナルが必要です。
  |
| 目的: |
 Svelte のローカル開発環境を構築して、スターターアプリの作成とビルド、
 そして仕組みの基本を理解する。
  |

Svelte: 優れたユーザーインターフェイスを構築する新しいアプローチ
------------------------------------

Svelte はこのモジュールで扱われている他のフレームワークとは異なるアプローチでウェブアプリケーションを構築します。React や Vue などのフレームワークはアプリケーションの実行中にユーザーのブラウザーで作業の大半を行いますが、Svelte はその作業をアプリケーションのビルド時にのみ発生するコンパイルの段階で行うことにより、高度に最適化されたバニラ JavaScript を生成します。

このアプローチによってアプリケーションバンドルが小さくなり、パフォーマンスが向上するほか、モダンなツールのエコシステムをあまり経験していない人にとってもより親しみやすい開発体験が得られるようになりました。

Svelte は HTML と CSS、そして JavaScript という昔ながらのウェブ開発モデルに忠実であり、HTML と JavaScript にいくつかの拡張機能を加えただけです。これにより間違いなく他のフレームワークと比べて学ぶべき概念やツールは少ないと言えるでしょう。

現時点での主な欠点はまだ若いフレームワークであるということです。若いということは、そのエコシステムは成熟したフレームワークよりもツール、サポート、プラグイン、明確な使用パターンなどが限られており、求人も少ないです。しかし、今まで紹介した利点は、あなたが Svelte を探究することへの関心を持ってもらうのに十分なはずです。

**メモ:** 2020 年より、Svelteは最も要望の多かった機能の 1 つである TypeScript を公式にサポートするようになりました。このチュートリアルシリーズの後半で確認していきます。

このチュートリアルシリーズに戻って、より詳細な作成方法について学ぶ前に Svelte チュートリアルで基本的なコンセプトを簡単に確認することを推奨します。完了までの所要時間は約 30 分です。

ユースケース
------

Svelte はインターフェイスの一部またはアプリケーション全体の開発に使用できます。Svelte を用いてゼロから UI を開発することも、既存のアプリケーションへ段階的に組み込むことも可能です。

しかしながら、Svelte は特に以下のような状況で用いるのに適しています。

* 低消費電力デバイス向けのウェブアプリケーション: Svelte で構築されたアプリケーションはバンドルサイズが小さいため、ネットワーク接続が遅く、処理能力に制限のあるデバイスに最適です。コードが少ないということはダウンロード、解析、実行、そしてメモリー内で保持し続ける KB が少ないことを意味します。
* 高度にインタラクティブなページや複雑な視覚化: 多くの DOM 要素を表示する必要があるデータ視覚化を構築する場合、ランタイムオーバーヘッドのないフレームワークから得られるパフォーマンスの向上により、ユーザーとのインタラクションが迅速かつ応答性が高くなることを保証します。
* ウェブ開発の基礎知識がある人のオンボーディング: Svelte は学習曲線が浅いのが特徴です。HTML、CSS、JavaScript の基礎知識を持つウェブ開発者であれば、短期間で簡単に Svelte の仕様を理解してウェブアプリケーションの構築を開始することができます。

さらに Svelte をベースにしたフレームワークである Sapper (en-US) を利用すればサーバーサイドレンダリング、コード分割、ファイルベースのルーティング、オフラインサポートなどの高度な機能を備えたアプリケーションを開発することも可能です。またネイティブなモバイルアプリケーションを構築できる Svelte Native (en-US) もあります。

Svelte の仕組みについて
---------------

コンパイラーである Svelte は HTML、CSS、JavaScript を拡張して、ランタイムオーバーヘッドなしに最適な JavaScript コードを生成できます。これを実現するために Svelte は以下のような方法でバニラウェブの技術を拡張しています。

* HTML を拡張してマークアップに JavaScript の表現を与えることで、handlebars と同様の方法で条件やループを使用するディレクティブを提供しています。
* CSS を拡張してスコープの仕組みを追加することで、各コンポーネントが他のコンポーネントのスタイルと衝突するリスクなしに独自のスタイルを定義できるようにしています。
* JavaScript を拡張して言語の特定のディレクティブを再解釈することで、真のリアクティビティを実現してコンポーネントの状態管理を容易にしています。

コンパイラーは非常に特殊な状況でのみ、Svelte コンポーネントのコンテキストにだけ介入します。JavaScript 自体の拡張は最小限であり、JavaScript の構文を壊さないように、また開発者を遠ざけることのないように、慎重に選択されています。実際にほとんどの場合はバニラ JavaScript で作業することになるでしょう。

Svelte との第一歩
------------

Svelte はコンパイラーであるため、`<script src="svelte.js">` タグをページに追加してアプリにインポートすることはできません。コンパイラーを動かすためには開発環境をセットアップする必要があります。

### 必要条件

Svelte を動作させるためには Node.js がインストールされている必要があります。ここでは長期サポート (LTS) バージョンを使用することを推奨します。Node には npm (node パッケージマネージャー) と npx (node パッケージランナー) が含まれます。npm の代わりに Yarn パッケージマネージャーを使用することもできますが、このチュートリアルでは npm を使用していることを前提としています。npm と Yarn の詳細については、パッケージ管理の基礎を参照してください。

Windows を使用している場合、このチュートリアルで説明されているターミナルコマンドを使うためには Unix/macOS のターミナルと同等になるように何らかのソフトウェアをインストールする必要があります。Gitbash (git for Windows ツールセット (en-US) の一部として提供されています) と Windows Subsystem for Linux (WSL) はどちらとも適した選択肢です。これらの一般的なターミナルコマンドについての詳細は コマンドライン短期集中講座 を参照してください。

詳細については以下もご覧ください。

* "What is npm" (en-US) - nodejs.org
* "Introducing npx" (en-US) - npm Blog
* "Svelte の一番簡単な始め方" - Svelte Blog
### 最初の Svelte アプリを作成する

スターターアプリのテンプレートを作成する最も簡単な方法は、スターターテンプレートのアプリケーションをダウンロードすることです。GitHub の sveltejs/template にアクセスすればダウンロードが可能ですが、degit を使用すればダウンロードや解凍の手間を省くことができます。

スターターアプリのテンプレートを作成するためには、以下のターミナルコマンドを実行します。

```bash
npx degit sveltejs/template moz-todo-svelte
cd moz-todo-svelte
npm install
npm run dev
```

**メモ:** degit は魔法のようなものではありません。ただ最新バージョンにあたる git リポジトリーの内容をダウンロードして解凍しているだけです。これは `git clone` を使うよりもはるかに高速です。なぜならリポジトリーの履歴全てをダウンロードしたり、完全なローカルクローンを作ったりしないためです。

`npm run dev` を実行すると Svelte がアプリケーションのコンパイルとビルドを行います。するとローカルサーバーとして `localhost:8080` が起動します。Svelte はファイルの更新を監視して、ソースファイルに変更があった場合、アプリを自動的に再コンパイルして更新を行います。なおブラウザーには次のように表示されます。

![hello world と書かれたシンプルなスタートページ、下部には公式の svelte チュートリアルへのリンクがある](/ja/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_getting_started/01-svelte-starter-app.png)

### アプリケーションの構造

スターターテンプレートは以下のような構造で提供されています。
```

moz-todo-svelte
├── README.md
├── package.json
├── package-lock.json
├── rollup.config.js
├── .gitignore
├── node_modules
├── public
│   ├── favicon.png
│   ├── index.html
│   ├── global.css
│   └── build
│       ├── bundle.css
│       ├── bundle.js
│       └── bundle.js.map
├── scripts
│   └── setupTypeScript.js
└── src
    ├── App.svelte
    └── main.js
```

内容は以下のとおりです。

* `package.json` と `package-lock.json`: Node.js/npm プロジェクトを整理するために使用する情報が含まれています。このチュートリアルを完了するためにこれらのファイルを理解する必要は全くありませんが、詳細を学びたい場合は NodeJS.org の `package.json` とはどのようなファイルか？ (en-US)、もしくは パッケージ管理の基礎 でも説明しています。
* `node_modules`: これは node がプロジェクトの依存関係を保存しておく場所です。これらの依存関係は本番環境に送られることはなく、開発目的にのみ使用されます。
* `.gitignore`: プロジェクトから無視するファイルもしくはフォルダーを git に指示します。アプリを git リポジトリーに含める場合に便利です。
* `rollup.config.js`: Svelte ではモジュールバンドラーとして rollup.js (en-US) を使用しています。この設定ファイルはアプリのコンパイルとビルドの方法を rollup に指示します。 webpack (en-US) が好きな方は `npx degit sveltejs/template-webpack svelte-app` でスタータープロジェクトを作成することもできます。
* `scripts`: 必要に応じてセットアップスクリプトが含まれます。現在は `setupTypeScript.js` のみを含める必要があります。
    + `setupTypeScript.js`: このスクリプトは Svelte の TypeScript サポートを設定するものです。最後の記事で詳しく説明します。
* `src`: このディレクトリーにはアプリケーションのソースコードが入れられます。つまりアプリのコードを作成する場所です。
    + `App.svelte`: アプリの最上位コンポーネントです。今のところは 'Hello World!' をレンダリングするだけです。
    + `main.js`: アプリケーションのエントリーポイントです。これは `App` コンポーネントをインスタンス化して、HTML ページの body にバインドするだけです。
* `public`: このディレクトリーには、本番環境で公開される全てのファイルが含まれています。
    + `favicon.png`: アプリのファビコンです。現在は Svelte のロゴになっています。
    + `index.html`: これがアプリのメインページです。最初は空の HTML ページで、その後 Svelte によって生成された CSS ファイルと js バンドルが読み込まれます。
    + `global.css`: このファイルにはスコープされていないスタイルが書かれています。これはアプリケーション全体に適用される通常の CSS ファイルです。
    + `build`: このフォルダーには、生成された CSS と JavaScript のソースコードが入っています。
        - `bundle.css`: 各コンポーネントに定義されたスタイルから Svelte が生成した CSS ファイル。
        - `bundle.js`: 全ての JavaScript のソースコードからコンパイルされた JavaScript ファイル。
最初の Svelte コンポーネントを見る
---------------------

コンポーネントは Svelte アプリケーションの構成要素です。これらは HTML のスーパーセットを使用して、`.svelte` ファイルに記述されます。

`<script>`、`<style>`、マークアップの 3 つのセクションは全て任意であり、好きな順序で並べることができます。

```html
<script>
 // ここにロジックを記述
</script>

<style>
 /\* ここにスタイルを記述 \*/
</style>

<!-- ここにマークアップ (0 個以上の HTML 要素) を記述 -->
```

**メモ:** コンポーネントの形式についての詳細は、Svelte のドキュメント を参照してください。

以上を踏まえてスターターテンプレートに付属の `src/App.svelte` ファイルを見てみましょう。以下のようになっているはずです。

```html
<script>
 export let name;
</script>

<main>
  <h1>Hello {name}!</h1>
  <p>
    Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn
    how to build Svelte apps.
  </p>
</main>

<style>
 main {
 text-align: center;
 padding: 1em;
 max-width: 240px;
 margin: 0 auto;
 }

 h1 {
 color: #ff3e00;
 text-transform: uppercase;
 font-size: 4em;
 font-weight: 100;
 }

 @media (min-width: 640px) {
 main {
 max-width: none;
 }
 }
</style>
```

### `<script>` セクション

`<script>` ブロックには、コンポーネントのインスタンスが作成されたときに実行される JavaScript が含まれています。トップレベルで宣言された (またはインポートされた) 変数は、コンポーネントのマークアップから「表示」できるようになっています。トップレベルの変数は Svelte がコンポーネントの状態を処理する方法であり、デフォルトでリアクティブです。これが何を意味するかは、後ほど詳しく解説します。

```html
<script>
 export let name;
</script>
```

Svelte では変数の宣言をプロパティ (または prop) としてマークするために `export` キーワードを使って、コンポーネントのコンシューマー (他のコンポーネントなど) からアクセスができるようにします。これは Svelte が JavaScript の構文を拡張して、使い慣れた形式を維持しながら、より便利なものにした一例です。

### マークアップセクション

マークアップセクションでは任意の HTML を挿入することができ、さらに 1 つの中括弧 (`{}`) の中に有効な JavaScript を挿入することもできます。例の場合では、`name` prop の値を `Hello` の直後に埋め込んでいます。

```html
<main>
  <h1>Hello {name}!</h1>
  <p>
    Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn
    how to build Svelte apps.
  </p>
</main>
```

Svelte は `{#if}`、`{#each}`、`{#await}` などのタグもサポートしています。これらはそれぞれ、マークアップの一部を条件付きでレンダリングしたり、要素のリストを反復処理したり、非同期的な値を扱う処理ができます。

### `<style>` セクション

CSS を扱ったことがある場合、次のスニペットは理解できるかと思います。

```html
<style>
 main {
 text-align: center;
 padding: 1em;
 max-width: 240px;
 margin: 0 auto;
 }

 h1 {
 color: #ff3e00;
 text-transform: uppercase;
 font-size: 4em;
 font-weight: 100;
 }

 @media (min-width: 640px) {
 main {
 max-width: none;
 }
 }
</style>
```

上記では `<h1>` 要素にスタイルを適用しています。それでは `<h1>` 要素をを含む他のコンポーネントはどうなるでしょうか？

Svelte ではコンポーネントの `<style>` ブロック内の CSS は、そのコンポーネントにのみスコープされます。これはコンポーネントのスタイルに基づいたハッシュ値を、選択された要素にクラスとして追加することで機能しています。

新しいブラウザのタブで `localhost:8080` を開き、*HELLO WORLD!* ラベルを右クリック、または `Ctrl` キーを押しながらクリックして *検証* を選ぶことで下の画像と同様の画面を確認することができます。

![Svelte のスターターアプリを devtools で開くとスコープされたスタイルのクラスが表示される](/ja/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_getting_started/02-svelte-component-scoped-styles.png)

アプリをコンパイルする際、Svelte は `h1` のスタイル定義を `h1.svelte-1tky8bj` に変更します。そしてコンポーネント内全ての `<h1>` 要素を `<h1 class="svelte-1tky8bj">` に置き換え、そのコンポーネントが必要とするスタイルを取得できるようにします。

**メモ:** `:global()` 修飾子を使用することでこの動作をオーバーライドし、スタイルをグローバルなセレクターに適用できます (詳細については Svelte `<style>` ドキュメント を参照してください)。

少しだけ変更を加える
----------

 どのようにアプリが構成されているのかが大体分かったので、少しだけ変更を加えてみましょう。
 この時点で `App.svelte` コンポーネントの更新を試すことができます。例えば `App.svelte` の 6 行目にある `<h1>` 要素を以下のように変更してください。

```html
<h1>Hello {name} from MDN!</h1>
```

変更を保存するだけで `localhost:8080` で実行されているアプリが自動的に更新されます。

### Svelte のリアクティビティを確認

UI フレームワークの文脈では、リアクティビティとはコンポーネントの状態が変更されたときにフレームワークが自動的に DOM を更新できることを意味します。

Svelte では、コンポーネント内の任意のトップレベル変数に新しい値を代入することでリアクティビティが発生します。例として `App` コンポーネントに `toggleName()` 関数と、それを実行するためのボタンを組み込むことで確認ができます。

`<script>` とマークアップセクションを以下のように更新してみてください。

```html
<script>
 export let name;

 function toggleName() {
 if (name === "world") {
 name = "Svelte";
 } else {
 name = "world";
 }
 }
</script>

<main>
  <h1>Hello {name}!</h1>
  <button on:click="{toggleName}">Toggle name</button>
  <p>
    Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn
    how to build Svelte apps.
  </p>
</main>
```

ボタンがクリックされるたびに、Svelte は `toggleName()` 関数を実行して、`name` 変数の値を更新します。

お分かりのように `<h1>` ラベルは自動的に更新されます。その裏側では、Svelte は仮想 DOM やその他の複雑な調整メカニズムを使うことなく、name 変数の値が変更されるたびに DOM を更新する JavaScript コードを作り出しました。

なお `on:click` で `:` を使っていることに注意してください。これは Svelte が DOM イベントをリスニングするための構文です。

main.js を見る: アプリのエントリーポイント
--------------------------

`src/main.js` を開いてみましょう。このファイルは `App` コンポーネントがインポートされて使用される場所です。またアプリのエントリーポイントでもあり、最初は以下のようになっています。

```js
import App from "./App.svelte";

const app = new App({
  target: document.body,
  props: {
    name: "world",
  },
});

export default app;
```

始めに `main.js` は使用する Svelte コンポーネントをインポートします。そして 3 行目でインスタンス化を行い、次のプロパティを持つオプションオブジェクトを渡しています。

* `target`: コンポーネントをレンダリングする DOM 要素、上記の場合は `<body>` 要素。
* `props`: `App` コンポーネントの各 prop に割り当てる値を指定する。
細かく見てみる
-------

Svelte はどのようにして、これら全てのファイルを上手く連携させているのでしょうか？

Svelte コンパイラーは各コンポーネントの `<style>` セクションを処理して `public/build/bundle.css` ファイルにコンパイルします。

次に各コンポーネントのマークアップと `<script>` セクションをコンパイルして、その結果を `public/build/bundle.js` に保存します。くわえて `src/main.js` に各コンポーネントの機能を参照するためのコードを追加します。

そして最後に `public/index.html` ファイルには生成された `bundle.css` と `bundle.js` ファイルが組み込まれます。

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />

    <title>Svelte app</title>

    <link rel="icon" type="image/png" href="/favicon.png" />
    <link rel="stylesheet" href="/global.css" />
    <link rel="stylesheet" href="/build/bundle.css" />

    <script defer src="/build/bundle.js"></script>
  </head>

  <body></body>
</html>
```

縮小版の `bundle.js` のサイズは 3KB 程度で、これには「Svelte ランタイム」(わずか 300 行の JavaScript コード) と `App.svelte` のコンパイル済みコンポーネントが含まれています。お分かりのように `bundle.js` は `index.html` から参照される唯一の JavaScript ファイルです。ウェブページに読み込まれる他のライブラリーはありません。

これは他のフレームワークからコンパイルされたバンドルよりも、はるかに小さなフットプリントです。コードバンドルの場合、ダウンロードしなければならないファイルのサイズだけが重要ではないことを考慮してください。`bundle.js` は解析され、実行され、メモリー内に保持される必要がある実行可能なコードです。したがって特に低消費電力の機器や CPU に負荷のかかるアプリケーションではこれが大きな違いを生みます。

このチュートリアルを行う
------------

このチュートリアルシリーズでは完全なウェブアプリケーションを構築していきます。Svelte についての全ての基本を学び、さらに高度なトピックスもいくつか学習します。

内容をしっかりと読むだけでも Svelte の機能を十分に理解することができますが、一緒にアプリをコーディングしながら進めていくと、このチュートリアルを最大限に活用することができます。記事を読み進めやすいように、各チュートリアルの冒頭にはアプリのソースコードを含むフォルダーを GitHub リポジトリーとして提供しています。

また Svelte はオンライン REPL を提供しており、これはマシンに何もインストールせずにウェブ上で Svelte アプリをライブコーディングするためのプレイグラウンドです。各記事には REPL が用意されているので、すぐにコーディングに取り掛かることができます。これらツールの使い方をもう少し詳しく説明しましょう。

### Git の活用

最も一般的なバージョン管理システムは Git であり、 GitHub はリポジトリーのホスティングとそれらを操作するためのいくつかのツールを提供するサイトです。

各記事のソースコードを簡単にダウンロードできるよう、GitHub を活用します。行き詰まった場合に備えて、記事を読み終えると完成するコードを取得できるようになっています。

Git をインストールした後、リポジトリーのクローンを作成するために以下を実行します。

```bash
git clone https://github.com/opensas/mdn-svelte-tutorial.git
```

そして各記事の冒頭で、以下のように対応するフォルダーに `cd` してからアプリを開発モードで起動すると現在の状態がどのようになっているのかが確認できます。

```bash
cd 02-starting-our-todo-app
npm install
npm run dev
```

Git と GitHub について詳しく知りたい場合は、有益なガイドへのリンクがまとめられている Git と GitHub を参照してください。

**メモ:** Git リポジトリーをクローンせずにファイルだけをダウンロードしたい場合は、`npx degit opensas/mdn-svelte-tutorial` のように degit ツールを使うことができます。`npx degit opensas/mdn-svelte-tutorial/01-getting-started` で特定のフォルダーをダウンロードすることもできます。degit はローカルの git リポジトリーを作成せずに指定したフォルダーのファイルだけをダウンロードします。

### Svelte REPL の活用

REPL (Read-Eval-Print Loop) とはコマンドを入力してすぐに結果を確認できるインタラクティブな環境のことで、多くのプログラミング言語が REPL を提供しています。

ただ Svelte の REPL はそれ以上のものです。完全なアプリの作成、オンラインでの保存、他の人々との共有ができるオンラインツールです。

何もインストールする必要はなく、どのマシンからでも Svelte を試すことができる最も簡単な方法です。また、Svelte のコミュニティでも広く利用されています。アイデアを共有したり、助けを求めたり、問題を報告したりする場合、それらの事柄を実演する REPL インスタンスを作成することはどのような時でも非常に役立ちます。

それでは Svelte REPL とその使い方を簡単に見てみましょう。以下のようになります。

![動作中の Svelte REPL、それぞれ左側に表示されるのがコンポーネントコード、右側が出力結果](/ja/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_getting_started/03-svelte-repl-in-action.png)

REPL を使い始めるには、ブラウザーを開いて https://svelte.dev/repl に移動します。

* 画面の左側にはコンポーネントのコードが表示され、右側にはアプリの実行中の出力が表示されます。
* コードの上にあるバーで `.svelte` と `.js` のファイルの作成や並べ替えができます。フォルダー内にファイルを作成する場合は、`components/MyComponent.svelte` のように完全なパス名を指定してください。そうすることで自動的にフォルダーが作成されます。
* そのバーの上には REPL のタイトルがあります。これはクリックすることで編集が可能です。
* 右側には下記 3 つのタブがあります。
    + *Result* タブにはアプリの出力が表示され、下部にはコンソールが用意されています。
    + *JS output* タブでは Svelte が生成した JavaScript コードの検査とコンパイラーオプションの設定ができます。
    + *CSS output* タブには Svelte によって生成された CSS が表示されます。
* タブの上には、フルスクリーンモードにしたり、アプリをダウンロードしたりするためのツールバーがあります。GitHub のアカウントでログインすると、アプリをフォークして保存することもできるようになります。また GitHub のユーザープロフィールをクリックして *Your saved apps* を選択すると、保存した全ての REPL を確認することができます。

REPL 上のファイルを変更するたびに Svelte はアプリを再コンパイルして Result タブを更新します。アプリを共有したい時は URL を共有してください。例えば、このチュートリアルシリーズの完成版アプリを実行している REPL へのリンクは https://svelte.dev/repl/378dd79e0dfe4486a8f10823f3813190?version=3.23.2 です。

**メモ:** URL で Svelte のバージョンを指定できることに注目してください。これは Svelte の特定のバージョンに関連する問題を報告する際に役立ちます。

各記事の最初と最後に REPL を提供しているため、すぐにでもコーディングを開始することができます。

**メモ:** 現在のところ、REPL はフォルダー名を正しく扱えません。もし REPL 上でチュートリアルを行っている場合は、ルートフォルダー内に全てのコンポーネントを作成してください。例えばコード中に `import Todos from './components/Todos.svelte'` などのパスを見つけたら、 `import Todos from './Todos.svelte'` などのフラットな URL に置き換えるだけです。

これまでのコード
--------

### Git

まだ行っていない場合は、GitHub リポジトリーをクローンします。

```bash
git clone https://github.com/opensas/mdn-svelte-tutorial.git
```

次に、現段階のアプリを取得するためには以下を実行します。

```bash
cd mdn-svelte-tutorial/01-getting-started
```

もしくはフォルダーのコンテンツを直接ダウンロードします。

```bash
npx degit opensas/mdn-svelte-tutorial/01-getting-started
```

`npm install && npm run dev` を実行して、アプリを開発モードで起動することを忘れないでください。

### REPL

チュートリアルを読みながら REPL でコードを書くには、下記のリンクを使ってください。

https://svelte.dev/repl/fc68b4f059d34b9c84fa042d1cce586c?version=3.23.2

まとめ
---

ローカルにインストールする方法、スターターアプリを作成する方法、基本的な動作など、Svelte について最初の紹介はこれで終わりです。次の記事では初めてのアプリケーションとなる todo リストの作成を開始します。ですが、その前にこれまでに学んだことをいくつか復習しておきましょう。

Svelte の基礎知識:

* 各コンポーネントのスクリプト、スタイル、およびマークアップを 1 つの `.svelte` ファイルで定義します。
* コンポーネントの props は `export` キーワードで宣言されます。
* Svelte コンポーネントは対応する `.svelte` ファイルをインポートするだけで使用することができます。
* コンポーネントのスタイルはスコープが設定されており、お互いに衝突することがないようになっています。
* マークアップセクションでは中括弧で囲むことにより、任意の JavaScript を含めることができます。
* コンポーネントのトップレベルで宣言された変数が、状態の構成要素となります。
* トップレベルの変数に新しい値を代入するだけでリアクティビティが発動します。
* 前のページ  (en-US)
* Overview: Client-side JavaScript frameworks
* 次のページ  (en-US)


React を始める - ウェブ開発を学ぶ

React を始める
==========

* 前のページ  (en-US)
* Overview: Client-side JavaScript frameworks
* 次のページ

この記事では React のはじめかたを説明します。React の背景と使い方について説明し、ローカル環境で基本的な React ツールチェーンを設定します。また、シンプルな基本アプリを作成して、React がどのようなプロセスで機能するのかを学んでいきます。

|  |  |
| --- | --- |
| 前提条件: |
 基本的な HTML,
 CSS,
 JavaScript 言語に親しんでいること、ターミナル/コマンドラインに関する知識があること。

React は JSX (JavaScript と XML) と呼ばれる HTML-in-JavaScript を使用します。HTML と JavaScript の両方に精通していると、JSX の学習に役立ち、アプリケーションのバグが JavaScript に関連しているか、React のより具体的なドメインに関連しているかを特定するのに役立つます。 |
| 目的: | ローカルの React 開発環境をセットアップし、開始アプリを作成して、それがどのように機能するかの基本を理解する。 |

React の基礎
---------

公式のキャッチフレーズにあるように、React はユーザーインターフェイスを構築するためのライブラリーです。React はフレームワークではなく、ウェブに限定されるものでもありません。他のライブラリーと共に使用して、特定の環境にレンダリングします。たとえば、React Native はモバイルアプリケーションの構築に使用できます。

ウェブ向けに構築するには、開発者は ReactDOM と連携して React を使用します。React と ReactDOM は、他の本当のウェブ開発フレームワークと同じ土台で頻繫に議論され、同じような問題を解決するために用いられます。React を「フレームワーク」と呼ぶとき、それは口語的な理解として扱います。

React が目指すところは、開発者が UI を構築しているときに発生するバグを最小限に抑えることです。これは、コンポーネント（ユーザーインターフェイスの一部を記述する自己完結型の論理的なコード）を使用して行われます。これらのコンポーネントを組み合わせて完全な UI を作成でき、React はレンダリング作業の大部分を抽象化して、UI デザインに集中できるようにします。

用途
--

このモジュールで取り上げられている他のフレームワークとは異なり、React はコード規則やファイル編成に関する厳密なルールを適用しません。これにより、チームは自分に最適な規則を設定し、React を好きなように採用することができます。React は、単一のボタン、一部のインターフェイス、またはアプリのユーザーインターフェイス全体を処理できます。

React はインターフェイスの一部に適用することが *できます* が、jQuery のようなライブラリーや Vue のようなフレームワークほどアプリケーションに「ドロップ」するのは簡単ではありません。React でアプリ全体を構築するのに適しています。

さらに、JSX のインターフェイスの作成など、React アプリの開発者体験にはコンパイルプロセスが必要とします。Babel のようなコンパイラーをウェブサイトに追加すると、コードの実行が遅くなるため、開発者はビルドステップでそのようなツールをセットアップすることがよくあります。間違いなく React には厳しいツール要件がありますが、学習することはできます。

この記事では、Facebook 独自の create-react-app を使って、アプリケーションのインターフェイスを構築していきます。

React における JavaScript の書き方
--------------------------

React は、そのパターンの多くに最新の JavaScript の機能を利用しています。JavaScript からの最大の違いは、JSX 構文を使うことです。JSX は JavaScript の構文を拡張して、HTML のようにコードを書くことができます。例えば次のようになります。

```jsx
const heading = <h1>Mozilla Developer Network</h1>;
```

この定数 heading は、**JSX 式**と呼ばれます。React はこのように `<h1>` タグをレンダリングすることができます。

セマンティックの観点で、 `<header>` タグで、見出しを囲みたいとします。JSX では、HTML のように、要素を相互にネストすることができます。

```jsx
const header = (
  <header>
 <h1>Mozilla Developer Network</h1>
 </header>
);
```

**メモ:** このスニペットの括弧は JSX に固有のものではなく、あなたのアプリケーションに影響を与えません。それらは、あなた（またあなたのコンピューター）にとって、内部の複数行のコードが同じ式の一部であるという意味です。次のように header を定義することもできます。

```jsx
const header = <header>
 <h1>Mozilla Developer Network</h1>
</header>;
```

ただし、`<header>` 式を開始するタグが、対応する終了タグと同じ位置にインデントされていないため、これは少し読みにくいかもしれません。

もちろん、ブラウザーはそのままでは JSX を読むことができません。（Babel や Parcel などのツールを使用して）コンパイルすると、ヘッダー式は次のようになります。

```jsx
const header = React.createElement(
  "header",
  null,
  React.createElement("h1", null, "Mozilla Developer Network"),
);
```

コンパイルステップとコンパイル自体をスキップし、`React.createElement()` を使って、独自の UI を自分で書くことができます。ただし、こうすると JSX の宣言的なメリットが失われ、コードが読みにくくなってしまいます。コンパイルは開発プロセスとは別のステップですが、React コミュニティの多くの開発者は、JSX の読みやすさに価値があると考えています。さらに、現代のフロントエンド開発は常にビルドプロセスを伴います。古いブラウザーとの互換性を保つために現代の構文をダウンレベルしなければなりませんし、読み込みパフォーマンスを最適化するためにコードをミニファイしたくなることがあります。 Babel のような人気のあるツールはすでに JSX 対応をしているので、コンパイラーを自分で設定する必要はありません。

JSX は HTML と JavaScript を交ぜたものなので、一部の開発者にとっては直感的に使うことができます。しかしそうでない人にとってはは、交ぜられてされていることで混乱させられると言います。ただし、慣れれば、ユーザーインターフェイスをより迅速かつ直感的に構築できるようになり、他の人がコードを一目で理解しやすくなります。

JSX の詳細については、React チームの Writing Markup with JSX の記事をご覧ください。

最初の React アプリをセットアップする
----------------------

React を使用する方法はたくさんありますが、前述のように、コマンドラインインターフェイス (CLI) ツールの create-react-app を使用します。これにより、いくつかのパッケージをインストールして作成することにより、React アプリケーションの開発プロセスをスムーズにします。

`<script>` を HTML ファイルにコピーすることで create-react-app なしでウェブサイトに React を追加することは可能ですが、 create-react-app CLI は、React アプリケーションの一般的な始め方です。これを使うことで、アプリの作成に集中でき、セットアップに煩わされなくなります。

### 必要条件

create-react-app を使用するには、 Node.js をインストールする必要があります。長期サポート (LTS) バージョンを使用することをお勧めします。ノードには、npm (ノードパッケージマネージャー) および npx (ノードパッケージランナー) が含まれます。

代わりに Yarn パッケージマネージャーを使用することもできますが、この一連のチュートリアルでは npm を使用するものとします。npm と yarn の詳細については、パッケージ管理の基本を参照してください。

Windows を使用している場合、このチュートリアルで言及されている端末コマンドを使用するには、Unix / macOS 端末と同等のソフトウェアをインストールする必要があります。 **Gitbash** （git for Windows のツールセットの一部として提供）または **Linux 用の Windows サブシステム** (**WSL**) の両方が適しています。これら、および一般的な端末コマンドの詳細については、コマンドライン短期集中講座を参照してください。

また、React と ReactDOM は、かなり近代的な一連のブラウザー（IE9 以降）でのみ機能するアプリを生成することにも注意してください。これらのチュートリアルを実行するときは、Firefox、Microsoft Edge、Safari、Chrome などの最新のブラウザーを使用することをお勧めします。

詳細については、以下も参照してください。

* "About npm" on the npm blog
* "Introducing npx" on the npm blog
* The create-react-app documentation
### アプリの初期化

create-react-app は引数を 1 つ取ります。アプリに付ける名前です。create-react-app はこの名前を使用して新しいディレクトリーを作成し、その中に必要なファイルを作成します。`cd` でアプリのハードドライブ上の場所に移動したことを確認してから、ターミナルで次のコマンドを実行します。

```bash
npx create-react-app moz-todo-react
```

これは `moz-todo-react` ディレクトリーを作成し、その中でいくつかのことを行います:

* アプリの機能に不可欠な npm パッケージをインストールします。
* アプリケーションを起動および提供するためのスクリプトを記述します。
* 基本的なアプリアーキテクチャを定義するファイルとディレクトリーの構造を作成します。
* コンピュータに git がインストールされている場合、ディレクトリーを git リポジトリーとして初期化します。

**メモ:** yarn パッケージマネージャーがインストールされている場合、create-react-app は既定で npm の代わりにそれを使用します。両方のパッケージマネージャーがインストールされていて、明示的に npm を使用したい場合、create-react-app を実行するときに `--use-npm` フラグを追加できます。

```bash
npx create-react-app moz-todo-react --use-npm
```

create-react-app が機能している間、端末にいくつかのメッセージが表示されますが、正常な動作です！これには数分かかる場合がありますので、お茶でも作って待ってみましょう。

プロセスが完了したら、`moz-todo-react`ディレクトリーへ `cd` して、コマンド `npm start` を実行します。create-react-app によってインストールされたスクリプトは、localhost:3000 のローカルサーバーで提供され始め、新しいブラウザータブでアプリを開きます。ブラウザーには次のように表示されます。

![既定の create-react-app アプリケーションを示す、Firefox MacOS のスクリーンショット、localhost:3000を開く](/ja/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started/default-create-react-app.png)

### アプリケーションの構造

create-react-app は、React アプリケーションの開発に必要なすべてのものを提供します。初期のファイル構造は次のようになります。
```

moz-todo-react
├── README.md
├── node_modules
├── package.json
├── package-lock.json
├── .gitignore
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
└── src
    ├── App.css
    ├── App.js
    ├── App.test.js
    ├── index.css
    ├── index.js
    ├── logo.svg
    ├── reportWebVitals.js
    └── setupTests.js
```

**`src`** ディレクトリーはアプリケーションの実態ともいえるソースことがある場所で、私たちが触るのは主にこの部分です。

**`public`** ディレクトリーには、アプリを開発している間、ブラウザーによって読み込まれるファイルが含まれています。これらの中で最も重要なのは `index.html` です。React はこのファイルにコードを挿入して、ブラウザーで実行できるようにします。create-react-app 関数に役立つマークアップが他にもいくつかあるので、何をしているのかを理解していなければ、自分で編集しないように注意してください。このファイルの要素内の `<title>` を変更して、アプリケーション自体のタイトルを反映させる必要があります。アクセシビリティ向上のためには正しいページタイトルが重要です。

`public` ディレクトリーは、アプリをビルドしてデプロイするときにも公開されます。このチュートリアルではデプロイ自体については説明しませんが、アプリのデプロイチュートリアルで説明されているものと同様のソリューションを使用できるはずです。

この`package.json` ファイルには、Node.js / npm がプロジェクトを整理するために使用するプロジェクトに関する情報が含まれています。このファイルは React アプリケーションに固有のものではありません。create-react-app は単にそれを生成します。このチュートリアルを完了するためにこのファイルを理解する必要はまったくありませんが、詳しく知りたい場合は package.json on the npm blog を参照してください。パッケージ管理の基本のチュートリアルでも言及しています。

最初の React コンポーネント — <App/>
--------------------------

React における、**コンポーネント**とはアプリの一部をレンダリングする再利用可能なモジュールを指します。これらのパーツは大きくても小さくてもかまいませんが、通常は明確に定義され、単一責務のもとに作られます。

ブラウザーに表示されているように、`src/App.js` を開いて編集しましょう。このファイルには、最初のコンポーネント、`App`、その他の数行のコードが含まれています。

```jsx
import logo from "./logo.svg";
import "./App.css";

function App() {
  return (
    <div className="App">
 <header className="App-header">
 <img src={logo} className="App-logo" alt="logo" />
 <p>
 Edit <code>src/App.js</code> and save to reload.
 </p>
 <a
 className="App-link"
 href="https://reactjs.org"
 target="\_blank"
 rel="noopener noreferrer">
 Learn React
 </a>
 </header>
 </div>
  );
}
export default App;
```

この `App.js` ファイルは 3 つの主要な部分で構成されています。上部にいくつかの宣言されている `import`、中央にある `App`、最下部にある `export`。ほとんどの React コンポーネントはこのように書かれます。

### import 文

`import` はファイルの先頭に宣言され、`App.js` が他の場所で定義されているコードを使用するのを許可します。これらをさらに詳しく見てみましょう。

```jsx
import logo from "./logo.svg";
import "./App.css";
```

最初の文は、 `'./logo.svg'` をインポートします。最初の `./` パスのと最後の拡張子 `.svg` に注意してください。これらはファイルがローカルであり、 JavaScript ファイルではないことを示しています。実際、`logo.svg` ファイルはソースディレクトリーにあります。

2 つ目の文は、 App コンポーネント関連の CSS をインポートしています。変数名も `from` ディレクティブもないことに注意してください。これは *side-effect import* と呼ばれ、JavaScript ファイルに値をインポートしませんが、参照する CSS ファイルを最終的な CSS バンドルに追加するようにバンドルする Webpack に指示します。

2020 年の React 17 リリース以前の React のリリースでは、 React ライブラリー自体のインポートも `import React from 'react'` のように行う必要がありました。この手順をスキップするとエラーになっていました。 React は書いた JSX を `React.createElement()` に変換するので、 React のコンポーネントはすべて `React` モジュールをインポートする必要がありました。React 17 では、この文を不要にする新しい JSX 変換に書き直されたバージョンが導入され、React 16.14.0、React 15.7.0、React 0.14.10 にバックポート対応しています（詳しくは React 公式ドキュメントをご覧ください）。

### App コンポーネント

`import` の次に、`App` という名前の関数があります。ほとんどの JavaScript コミュニティは `helloWorld` のようなキャメルケース名を好みますが、 React コンポーネントは `HelloWorld` のようなパスカルケース変数名を使用して、特定の JSX 要素が React コンポーネントであり、通常の HTML タグではないことを明確にしています。`App` 関数の名前を `app` に変更すると、ブラウザーにエラーが表示されます。

アプリをもっと詳しく見てみましょう。

```jsx
function App() {
  return (
    <div className="App">
 <header className="App-header">
 <img src={logo} className="App-logo" alt="logo" />
 <p>
 Edit <code>src/App.js</code> and save to reload.
 </p>
 <a
 className="App-link"
 href="https://reactjs.org"
 target="\_blank"
 rel="noopener noreferrer">
 Learn React
 </a>
 </header>
 </div>
  );
}
```

この `App` 関数は JSX 式を返します。この式には、ブラウザーが最終的に DOM にレンダリングするものを定義します。

HTML と同じように、`attribute="value"` のように属性をもつ要素があります。3 行目では、`<div>` 開始タグに `className` 属性があります。これは HTML の`class` 属性と同じですが、 JSX は JavaScript であるため使用できません。`class` が予約されているためです。つまり、JavaScript ではすでにそれを使用しており、もし同様に使うと問題が発生するということです。同じような理由で、他のいくつかの HTML 属性は、HTML とは異なる方法で JSX で記述されています。

6 行目の `<p>` タグを「Hello, World！」に変更して、ファイルを保存します。この変更はブラウザー `http://localhost:3000` で実行されている開発サーバーですぐにレンダリングされます。次に、`<a>` タグを削除して保存します。すると、「Learn React」リンクはなくなります。

`App` コンポーネントは次のようになります。

```jsx
function App() {
  return (
    <div className="App">
 <header className="App-header">
 <img src={logo} className="App-logo" alt="logo" />
 <p>Hello, World!</p>
 </header>
 </div>
  );
}
```

### 文のエクスポート

`App.js` ファイルの一番下にある `export default App` は、`App` コンポーネントを他のモジュールで使用できるようにしています。

index を詳しくみる
------------

`src/index.js` を開きましょう。`App` コンポーネントを使用しているのがわかります。このファイルはアプリのエントリーポイントであり、最初は次のようになっています。

```jsx
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
 <App />
 </React.StrictMode>,
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
```

`App.js` と同様に、ファイルは、実行する必要のあるすべての JS モジュールとその他の資産をインポートすることから始まります。

最初の 2 つの文は `React` および `ReactDOM` ライブラリーをインポートしています。これらのライブラリーはローカルファイルではないので、インポートする際にパスや拡張子は書きません。実際、これらのライブラリーは `package.json` ファイルに依存ファイルとして掲載されています。この区別に注意して、このレッスンを読み終えてください。

`index.css` はアプリ全体に適用されるグローバルスタイルを保持します。ここに、インポートされた`App`コンポーネントも確認できます。下部の `export` により、`App.js` がインポートできるようになりました。

7 行目では、 React 要素をレンダリングする DOM 要素を指定して `ReactDOM.createRoot()` 関数を呼び出しています。`public/index.html` の中を見ていくと、 `<body>` の中にある `<div>` 要素であることがわかります。 React はこのノードのルートを作成し、その中の DOM の管理を引き継ぎます（詳しくは react 公式 ドキュメントを参照してください）。この関数は `root` を返します。

8 行目では、 DOM にレンダリングしたい React 要素、この場合は `<App />` を指定して `root.render()` メソッドを呼び出しています。開発中は厳格モードを使用して、コンポーネントによくあるバグを探します。

これらはすべて、 `<App />` を最初の要素として React アプリケーションをレンダリングすることを React に伝えます。

**メモ:** JSX では、React 要素と HTML 要素には閉じスラッシュが必要です。そのまま `<App>` または `<img>` と書くとエラーが発生します。

`reportWebVitals` は、ウェブページのユーザー使い勝手を把握することを目的とした有益な指標の集合ですが、この記事の対象ではありません。 `reportWebVitals();` の行と同様に、そのインポート行を削除することができます。

最終的な `index.js` ファイルは次のようになります。

```jsx
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
 <App />
 </React.StrictMode>,
);
```

変数と prop
--------

次に、JavaScript スキルのいくつかを使用して、コンポーネントの編集と React でのデータの操作をもう少し快適にします。JSX 内での変数の使用方法について説明し、データをコンポーネントに渡す方法である prop を紹介します (その後、変数を使用してアクセスできます)。

### JSX の変数

`App.js` に戻り、8 行目に注目しましょう。

```jsx
<img src={logo} className="App-logo" alt="logo" />
```

ここでは、`<img />` タグの `src` 属性値は中括弧で囲まれています。これは、JSX が変数を認識する方法です。React が `{logo}` を表示し、アプリの 2 行目のインポートを参照していることを確認してから、logo ファイルを取得してレンダリングします。

独自の変数を作ってみましょう。`App` の return 文の前に `const subject = 'React';` を追加します。すると、`App` コンポーネントは次のようになります。

```jsx
function App() {
  const subject = "React";
  return (
    <div className="App">
 <header className="App-header">
 <img src={logo} className="App-logo" alt="logo" />
 <p>Hello, World!</p>
 </header>
 </div>
  );
}
```

次のように、8 行目を変更して `subject` 変数を "world" という単語の代わりに使用します。

```jsx
function App() {
  const subject = "React";
  return (
    <div className="App">
 <header className="App-header">
 <img src={logo} className="App-logo" alt="logo" />
 <p>Hello, {subject}!</p>
 </header>
 </div>
  );
}
```

保存すると、ブラウザーに "Hello, React!" が "Hello, World!" の代わりに表示されます。

変数は便利ですが、設定したばかりの変数は React の機能をあまり活用していません。そこで、 prop の登場です。

### コンポーネントの prop

**prop** とは、Reactコンポーネントに渡されるデータのことです。 React の prop は HTML の属性に相当します。 HTML 要素が属性を持つのに対し、 React コンポーネントは prop を持ちます。 prop はコンポーネント呼び出しの中に記述され、 HTML の属性と同じ構文 `prop="value"` を使用します。 React では、データフローは一方向です。 prop は親コンポーネントから子コンポーネントにのみ渡すことができます。また prop は読み取り専用です。

`index.js`を開き、`<App/>` に最初の prop を渡しましょう。

`<App/>` コンポーネントに `subject` という prop を追加して、値は `Clarice` とします。完了すると、コードは次のようになります。

```jsx
root.render(<App subject="Clarice" />);
```

`App.js` に戻り、App 関数自体をもう一度見てみましょう。この関数は次のようになっています（簡潔にするために `return` で短くしています）。

```jsx
function App() {
  const subject = "React";
  return (
    // return statement
  );
}
```

`App` 関数の引数を変更して、`props` を引数として受け入れられるようにし、知数 `subject` を削除しましょう。
 他の引数と同様 `props` に、`console.log()` を入力して、ブラウザーのコンソールにそれを表示させます。 `return` 文の前にこのように書いてください。

```jsx
function App(props) {
  console.log(props);
  return (
    // return statement
  );
}
```

 この変更に伴い、 {subject} は未定義になるので、とりあえず `Hello, {subject}!` の行はコメントアウトしてください。
 ファイルを保存し、ブラウザーの JavaScript コンソールを確認します。次のようなログが表示されるはずです。
```

Object { subject: "Clarice" }
```

オブジェクトプロパティ `subject` は、`<App />` コンポーネント呼び出しに追加した `subject` プロパティに対応し、文字列 `Clarice` はその値に対応します。React のコンポーネントプロップは、常にこのようにオブジェクトに集約されます。

`subject` は props の一つになりました。App.js でこれを使ってみましょう。`subject` 定数を変更して、`React` という文字列として定義する代わりに `props.subject` の値を読み取るようにします。これで、 `Hello, {subject}!` という行のコメントを解除することもできますし、必要であれば、 `console.log()` を削除することもできます。

```jsx
function App(props) {
  const subject = props.subject;
  return (
    // return statement
  );
}
```

 保存すると、アプリは「Hello、Clarice！」と挨拶するはずです。`index.js` に戻り、`subject` の値を編集して保存すると、テキストが変更されます。
 なお、この変更を通して `Hello` の行を残したければ、JSX 変数を `{props.subject}` に更新することもできます。

まとめ
---

これで、React をローカルでインストールする方法、スターターアプリを作成する方法、基本的にどのように機能するかなど、React の入門が終わりました。次の記事では、最初に適したアプリケーションである todo リストの作成を開始します。ただし、その前に、私たちが学んだことのいくつかをおさらいしましょう。

React では:

* コンポーネントは必要なモジュールをインポートでき、ファイルの下部でエクスポートする必要があります。
* コンポーネント関数は `PascalCase` で名前が付けられます。
* JSX 変数は、`{so}` のように中括弧で囲むことで読み取ることができます。
* 一部の JSX 属性は HTML 属性とは異なるため、JavaScript の予約語と競合しません。例えば `class`、HTML では `className` JSX に変換されます。複数単語の属性はキャメルケースであることに注意してください。
* prop は、コンポーネント呼び出し内の属性と同じように記述され、コンポーネントに渡されます。
* 前のページ  (en-US)
* Overview: Client-side JavaScript frameworks
* 次のページ


Angular をはじめる - ウェブ開発を学ぶ

Angular をはじめる
=============

* 前のページ  (en-US)
* Overview: Client-side JavaScript frameworks
* 次のページ

今度は、Google の Angular フレームワークを見てみましょう。これは、よく目にするもう 1 つの人気のあるオプションです。 この記事では、Angular が提供するものを確認し、前提条件をインストールしてサンプルアプリをセットアップし、Angular の基本的なアーキテクチャを確認します。

|  |  |
| --- | --- |
| 前提条件: |
HTML、
 CSS、
 JavaScript に精通していること、
 ターミナル/コマンドラインに関する知識があること。
  |
| 目的: | ローカルの Angular 開発環境をセットアップするには、スターターアプリを作成し、 そしてそれがどのように機能するかの基本を理解します。 |

Angular とはなんですか ?
-----------------

Angular は、TypeScript でビルドする開発プラットフォームです。 Angular には次のものが含まれます。

* スケーラブルなウェブアプリケーションを構築するためのコンポーネントベースのフレームワーク
* ルーティング、フォーム管理、クライアント/サーバー通信など、さまざまな機能をカバーする、十分に統合されたライブラリのコレクション
* コードの開発、ビルド、テスト、更新を支援する一連の開発者ツール

Angular を使用してアプリケーションを構築する場合、単一の開発者プロジェクトからエンタープライズレベルのアプリケーションまで拡張できるプラットフォームを利用しています。 Angular は、更新を可能な限り簡単にするように設計されているため、最小限の労力で最新の開発を利用できます。 何よりも、 Angular エコシステムは、170 万人を超える開発者、ライブラリ作成者、コンテンツ作成者からなる多様なグループで構成されています。

Angular プラットフォームの探索を開始する前に、 Angular CLI について知っておく必要があります。 Angular CLI は、Angular アプリケーションを開発するための最も速く、最も簡単で、推奨される方法です。 Angular CLI を使用すると、多くのタスクを簡単に実行できます。 ここではいくつかの例を示します。

|  |  |
| --- | --- |
| `ng build` | Angular アプリを出力ディレクトリーにコンパイルします。 |
| `ng serve` | アプリケーションのビルド・起動をして、ファイルの変更時に再構築します。 |
| `ng generate` | セマンティックに基づいてファイルを生成または変更します。 |
| `ng test` | 対象のプロジェクトで単体テストを実行します。 |
| `ng e2e` | Angular アプリケーションをビルドして提供し、end to end のテストを実行します。 |

Angular CLI は、アプリケーションを構築するための大事なツールであることがわかります。

構築に必要なもの
--------

このチュートリアルシリーズでは、 to-do list アプリケーションの作成について説明します。 このアプリケーションを介して、Angular を使用してアイテムを管理、編集、追加、削除、およびフィルタリングする方法を学習します。

前提条件
----

ローカルシステムに Angular をインストールするには、次のものが必要です。

* **Node.js**
 Angular には、Node.js の現在のアクティブな LTS、またはメンテナンス LTS バージョンが必要です。特定のバージョン要件については、package.json ファイルの`engines`キーを参照してください。
 Node.js のインストールの詳細については、nodejs.org を参照してください。
 システムで実行されている Node.js のバージョンがわからない場合は、ターミナルウィンドウで、 `node-v` を実行してください。
* **npm パッケージマネージャー**
 Angular、Angular CLI、および Angular アプリケーションは、多くの機能をnpm パッケージに依存しています。
 npm パッケージをダウンロードしてインストールするには、npm パッケージマネージャーが必要です。
 このガイドでは、npm client コマンドラインインターフェイスを使用します。このコマンドラインインターフェイスは、デフォルトで `Node.js` とともにインストールされます。
 npm クライアントがインストールされていることを確認するには、ターミナルウィンドウで `npm-v` を実行します。
アプリケーションをセットアップする
-----------------

 Angular CLI を使用して、Angular アプリケーションを生成、構築、テスト、およびデプロイするためのコマンドをターミナルで実行できます。
 Angular CLI をインストールするには、ターミナルで次のコマンドを実行します。

```js
npm install -g @angular/cli
```

 Angular CLI コマンドはすべて `ng` で始まり、その後に CLI で実行する操作が続きます。
 デスクトップディレクトリーで、次の `ng new` コマンドを使用して、`todo`と いう名前の新しいアプリケーションを作成します。

```js
ng new todo --routing=false --style=css
```

`ng new` コマンドは、デスクトップ上に最小限のスターター Angular アプリケーションを作成します。
 追加のフラグ `--routing` と `--style` は、アプリケーションでナビゲーションとスタイルを処理する方法を定義します。
 このチュートリアルでは、これらの機能について後で詳しく説明します。

より厳密なタイプチェックを実施するように求められた場合は、yes で応答できます。

次の `cd` コマンドを使用して新しいプロジェクトに移動します。

```js
cd todo
```

`todo` アプリケーションを実行するには、`ng serve` を使用します。

```js
ng serve
```

CLI が analytics についてプロンプトを表示したら、`no` と答えます。

 ブラウザーで、 `http://localhost:4200/` に移動して、新しいスターターアプリケーションを表示します。
 ソースファイルのいずれかを変更すると、アプリケーションは自動的にリロードされます。

`ng serve` の実行中に、コマンドを実行するために 2 番目のターミナルタブまたはウィンドウを開くことができます。
 アプリケーションの実行を停止したい場合は、ターミナルで `Ctrl+c` を押してください。

Angular アプリケーションに慣れてください
------------------------

 このチュートリアルで焦点を当てているアプリケーションソースファイルは、 `src/app` にあります。
 CLI が自動的に生成するキーファイルには、次のものが含まれます。

1. `app.module.ts`: アプリケーションが使用するファイルを指定します。
 このファイルは、アプリケーション内の他のファイルの中央ハブとして機能します。
2. `app.component.ts`: クラスとも呼ばれ、アプリケーションのメインページのロジックが含まれています。
3. `app.component.html`: `AppComponent` の HTML が含まれています。 このファイルの内容は、テンプレートとも呼ばれます。
 テンプレートは、ブラウザーに表示されるビューまたは内容を決定します。
4. `app.component.css`: `AppComponent` のスタイルが含まれています。 このファイルは、アプリケーション全体ではなく、特定のコンポーネントにのみ適用されるスタイルを定義する場合に使用します。

 Angular のコンポーネントは、テンプレート、スタイル、クラスの 3 つの主要部分で構成されています。
 たとえば、 `app.component.ts` 、 `app.component.html` 、および `app.component.css` は一緒に `AppComponent` を構成します。
 この構造により、ロジック、ビュー、およびスタイルが分離され、アプリケーションの保守性と拡張性が向上します。

このようにして、最初からベストプラクティスを使用しています。

Angular CLI は `app.component.spec.ts` と呼ばれるコンポーネントテスト用のファイルも生成しますが、このチュートリアルではテストに入らないため、そのファイルは無視してかまいません。

コンポーネントを生成するたびに、CLI は指定した名前のディレクトリーにこれらの 4 つのファイルを作成します。

Angular アプリケーションの構造
-------------------

 Angular は TypeScript で構築されています。
 TypeScript は JavaScript のスーパーセットであり、有効な JavaScript が有効な TypeScript であることを意味します。
 TypeScript は、単純な JavaScript よりもタイピングとより簡潔な構文を提供します。これにより、より保守しやすいコードを作成し、バグを最小限に抑えるためのツールが提供されます。

 コンポーネントは、Angular アプリケーションの構成要素です。
 コンポーネントには、 `@Component()` デコレータ、HTML テンプレート、およびスタイルを持つ TypeScript クラスが含まれます。

### クラス

 このクラスは、コンポーネントに必要なロジックを配置する場所です。
 このコードには、関数、イベントリスナー、プロパティ、サービスへの参照などを含めることができます。
 クラスは、 `feature.component.ts` などの名前のファイルにあります。ここで、`feature` はコンポーネントの名前です。
 したがって、 `header.component.ts` 、`signup.component.ts` 、または `feed.component.ts` などの名前のファイルを作成できます。
 HTML と CSS の場所を Angular に指示するメタデータを持つ `@Component()` デコレータを使用してコンポーネントを作成します。
 一般的なコンポーネントは次のとおりです。

```js
import { Component } from "@angular/core";

@Component({
  selector: "app-item",
  // the following metadata specifies the location of the other parts of the component
  templateUrl: "./item.component.html",
  styleUrls: ["./item.component.css"],
})
export class ItemComponent {
  // your code goes here
}
```

 このコンポーネントは `ItemComponent` と呼ばれ、そのセレクターは `app-item` です。
 セレクターは、他のテンプレート内に配置することで、通常の HTML タグと同じように使用できます。
 セレクターがテンプレート内にある場合、ブラウザーはそのコンポーネントのテンプレートをレンダリングします。
 このチュートリアルでは、2 つのコンポーネントを作成し、一方を他方のコンポーネント内で使用する方法について説明します。

 Angular のコンポーネントモデルは、強力なカプセル化と直感的なアプリケーション構造を提供します。
 コンポーネントを使用すると、アプリケーションの単体テストが容易になり、コードの全体的な可読性が向上します。

### HTML テンプレート

 すべてのコンポーネントには、そのコンポーネントのレンダリング方法を宣言する HTML テンプレートがあります。
 このテンプレートは、インラインまたはファイルパスで定義できます。

外部 HTML ファイルを参照するには、`templateUrl` プロパティを使用します。

```js
@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
})
export class AppComponent {}
```

インライン HTML を作成するには、 `template` プロパティを使用して、バッククォート内に HTML を作成します。

```js
@Component({
  selector: "app-root",
  template: `<h1>Hi!</h1>`,
})
export class AppComponent {}
```

 Angular は、コンポーネントから動的な値を挿入できる追加の構文で HTML を拡張します。
 Angular は、コンポーネントの状態が変化すると、レンダリングされた DOM を自動的に更新します。
 この機能の使用法の 1 つは、次の例に示すように、動的テキストを挿入することです。

```html
<h1>{{ title }}</h1>
```

 二重中括弧は、Angular にその中のコンテンツを補間するように指示します。
 `title` の値は、コンポーネントクラスから取得されます。

```js
import { Component } from "@angular/core";

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"],
})
export class AppComponent {
  title = "To do application";
}
```

アプリケーションがコンポーネントとそのテンプレートをロードすると、ブラウザーには次のように表示されます。

```html
<h1>To do application</h1>
```

### スタイル

 コンポーネントは、アプリケーションの `styles.css` ファイルからグローバルスタイルを継承し、それらを独自のスタイルで拡張またはオーバーライドできます。
 コンポーネント固有のスタイルを `@Component()` デコレータに直接書き込むか、CSS ファイルへのパスを指定できます。

コンポーネントデコレータにスタイルを直接含めるには、`styles` プロパティを使用します。

```js
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styles: ['h1 { color: red; }']
})
```

通常、コンポーネントは、`styleUrls` プロパティを使用して別のファイルのスタイルを使用します。

```js
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
```

コンポーネント固有のスタイルを使用すると、CSS を整理して、保守と移植が容易になります。

まとめ
---

Angular の最初の紹介は以上です。 この時点で、Angular アプリをセットアップして構築する準備ができており、Angular がどのように機能するかについての基本的な理解が必要です。 次の記事では、その知識を深め、やることリストアプリケーションの構造を構築し始めます。

* 前のページ  (en-US)
* Overview: Client-side JavaScript frameworks
* 次のページ


クライアントサイドフレームワークの概要 - ウェブ開発を学ぶ

クライアントサイドフレームワークの概要
===================

* Overview: Client-side JavaScript frameworks
* 次のページ  (en-US)

JavaScript とフレームワークの簡単な歴史を見て、フレームワークがなぜ存在するのか、そしてそれが私たちに何をもたらすのか、学習するフレームワークの選択をどのように考え始めるか、そしてクライアント側フレームワークの代替手段は何があるのかをこの分野の一般的な概要からフレームワークの考察を始めます。

|  |  |
| --- | --- |
| 前提条件: | HTML、
 CSS、
 JavaScript に精通していること。
  |
| 目的: | クライアントサイド JavaScript フレームワークがどのようにして登場したのか、それによって何が解決されるのか、どのような代替案があるのか、どのように一つを選べばよいかを理解すること。 |

簡単な歴史
-----

1996 年に JavaScript が登場すると、それまで静的なドキュメントで構成されていたウェブに、ところどころの操作の可能性と興奮が加わりました。 ウェブは単に *ものを読む* だけではなく、 *何かをする* ための場所になりました。 JavaScript の人気は着実に高まりました。 JavaScript を扱う開発者は、直面した問題を解決するためのツールを作成し、**ライブラリー**と呼ばれる再利用可能なパッケージにパッケージ化して、他のユーザーとソリューションを共有できるようにしました。このライブラリーの共有エコシステムは、ウェブの成長を形作るのに役立ちました。

現在、 JavaScript はウェブに不可欠な部分となり、すべてのウェブサイトの 98% で使用されており、ウェブは現代生活に不可欠な部分です。ユーザーは論文を書いたり、予算を管理したり、音楽をストリーミングしたり、映画を鑑賞したり、テキスト、音声、またはビデオチャットを使って遠距離の他のユーザーと瞬時にコミュニケーションしたりできます。ウェブを使用すると、これまでコンピューターにインストールされたネイティブアプリケーションでのみ可能であったことが実行できるようになります。これらの最新の複雑でインタラクティブなウェブサイトは、**ウェブアプリケーション**と呼ばれることがよくあります。

最新の JavaScript フレームワークの出現により、非常に動的でインタラクティブなアプリケーションの構築がはるかに簡単になりました。**フレームワーク**は、ソフトウェアの構築方法についての意見を提供するライブラリーです。これらの意見により、アプリケーションの予測可能性と均一性が可能になります。予測可能性により、ソフトウェアを巨大なサイズに拡張しながらも保守可能になります。予測可能性と保守性は、ソフトウェアの健全性と寿命にとって不可欠です。

JavaScript フレームワークは、あなたが毎日使用するウェブサイトの多くを含む、現代のウェブ上の優れたソフトウェアの多くを強化しています。現在この記事を読んでいる MDN Web Docs は、React/ReactDOM フレームワークを使用してフロントエンドを強化します。

どのようなフレームワークがあるのでしょうか?
----------------------

さまざまなフレームワークが存在しますが、現在「ビッグ 4 」は次のとおりであると考えられています。

### Ember

Ember は、 SproutCore プロジェクトで開始された作業の継続として、2011 年 12 月に最初にリリースされました。これは古いフレームワークであり、React や Vue などの最新の代替フレームに比べてユーザー数は少ないですが、その安定性、コミュニティサポート、いくつかの賢いコーディング原則により、依然としてかなりの人気を誇っています。

Ember の学習を開始する (en-US)

### Angular

Angular は、Google の Angular チームと個人および企業のコミュニティが主導するオープンソースのウェブアプリケーションフレームワークです。これは、 AngularJS を構築したのと同じチームによる完全な書き直しです。 Angular は 2016 年 9 月 14 日に正式にリリースされました。

Angular は、宣言型 HTML テンプレートを使用するコンポーネントベースのフレームワークです。ビルド時に、開発者に対して透過的に、フレームワークのコンパイラーがテンプレートを最適化された JavaScript 命令に変換します。 Angular は、JavaScript のスーパーセットである TypeScript を使用します。これについては、次の章でもう少し詳しく説明します。

Angular の学習を開始する

### Vue

オリジナルの AngularJS プロジェクトに取り組み、そこから学んだエヴァン・ユーは、2014年に Vue をリリースしました。 Vue はビッグ 4 の中では最も歴史が浅いが、最近人気が急上昇しています。

Vue は、 AngularJS と同様に、独自のコードの一部で HTML を拡張します。それとは別に、主に最新の標準 JavaScript に依存しています。

Vue の学習を開始する (en-US)

### React

Facebook は 2013 年に React をリリースしました。この時点で、Facebook はすでに React を使用して社内の問題の多くを解決していました。技術的には、 React 自体はフレームワークではありません。これは UI コンポーネントをレンダリングするためのライブラリーです。 React は、アプリケーションを作成するために他のライブラリーと組み合わせて使用されます。 React と React Native を使用すると、開発者はモバイルアプリケーションを作成できます。 React と ReactDOM を使用すると、ウェブアプリケーションなどを作成できます。

React と ReactDOM は一緒に使用されることが多いため、React は口語的に JavaScript フレームワークとして理解されています。このモジュールを読み進めるにつれて、その口語的な理解に基づいて作業していきます。

React は、 JSX として知られる HTML のような構文で JavaScript を拡張します。

React の学習を開始する

何故フレームワークが存在するのでしょうか?
---------------------

フレームワークの作成にインスピレーションを与えた環境について説明しましたが、実際には、開発者がフレームワークを作成する必要性を *なぜ* 感じたのかというと、そうではありません。その理由を探るには、まずソフトウェア開発の課題を検討する必要があります。

一般的な種類のアプリケーション、 To-Do リスト作成ツールを考えてみましょう。これについては、今後の章でさまざまなフレームワークを使用して実装する方法を見ていきます。このアプリケーションでは、ユーザーがタスクのリストの表示、新しいタスクの追加、タスクの削除などを実行できるようにする必要があります。そして、アプリケーションの基礎となるデータを確実に追跡および更新しながらこれを実行する必要があります。ソフトウェア開発では、この基礎となるデータは状態として知られています。

私達のそれぞれの目標は、理論的には単独では単純です。データを反復処理してレンダリングできます。オブジェクトに追加して新しいタスクを作成できます。識別子を使用してタスクを検索、編集、削除できます。アプリケーションではユーザーがこれら *すべて* をブラウザー経由で実行できるようにする必要があることを思い出すと、いくつかの課題が見え始めます。**本当の問題は、アプリケーションの状態を変更するたびに、それに合わせて UI を更新する必要があるということです。**

この問題の難しさは、To Do リストアプリの *1* つの機能、つまりタスクのリストのレンダリングだけを見て調べることができます。

DOM の変更の冗長性
-----------

HTML 要素を構築し、適切なタイミングでブラウザーにレンダリングするには、驚くほどの量のコードが必要です。状態が次のように構造化されたオブジェクトの配列であるとします。

```js
const state = [
  {
    id: "todo-0",
    name: "Learn some frameworks!",
  },
];
```

それらのタスクの 1 つをユーザーにどのように表示すればよいでしょうか? 各タスクをリスト項目として表現したいとします。つまり、(順序なしリスト要素 `<ul>` 内の) HTML `<li>` 要素です。どうやって作るのでしょうか？それは次のようになります。

```js
function buildTodoItemEl(id, name) {
  const item = document.createElement("li");
  const span = document.createElement("span");
  const textContent = document.createTextNode(name);

  span.appendChild(textContent);

  item.id = id;
  item.appendChild(span);
  item.appendChild(buildDeleteButtonEl(id));

  return item;
}
```

ここでは、 `document.createElement()` メソッドを使用して `<li>` を作成し、さらに数行のコードで必要なプロパティと子を作成しています。

前のスニペットの 10 行目は、別のビルド関数 `buildDeleteButtonEl()` を参照しています。これは、リスト項目要素を構築するために使用したパターンと同様のパターンに従います。

```js
function buildDeleteButtonEl(id) {
  const button = document.createElement("button");
  const textContent = document.createTextNode("Delete");

  button.setAttribute("type", "button");
  button.appendChild(textContent);

  return button;
}
```

このボタンはまだ何も実行しませんが、削除機能の実装を決定すると後で実行されます。ページ上に項目をレンダリングするコードは次のようになります。

```js
function renderTodoList() {
  const frag = document.createDocumentFragment();
  state.tasks.forEach((task) => {
    const item = buildTodoItemEl(task.id, task.name);
    frag.appendChild(item);
  });

  while (todoListEl.firstChild) {
    todoListEl.removeChild(todoListEl.firstChild);
  }
  todoListEl.appendChild(frag);
}
```

これで、UI 専用のコードが 30 行を *はるかに* 超えています。つまり、 DOM 内で *何かを* レンダリングするためだけに、後でリスト項目のスタイルを設定するために使用できるクラスを追加する必要はありません。

DOM を直接操作して、この例のように要素の作り方、プロパティを変更する方法、要素を互いの内側に配置する方法、ページ上にそれらを表示する方法など DOM の仕組みについて多くのことを理解する必要があります。このコードは実際にユーザー操作を処理したり、タスクの追加や削除に対処したりするものはありません。これらの機能を追加する場合は、適切なタイミングで適切な方法で UI を更新することを忘れないでください。

JavaScript フレームワークは、この種の作業をはるかに簡単にするために作成されました。 JavaScript フレームワークは、より良い *開発者体験* を提供するために存在します。これらは JavaScript にまったく新しい機能をもたらすわけではありません。これらにより、JavaScript の機能に簡単にアクセスできるようになり、今日のウェブに合わせて構築できるようになります。

このセクションのコードサンプルの動作を確認したい場合は、 CodePen 上のアプリの動作バージョン をチェックアウトしてください。これにより、ユーザーは次の機能を追加したり、新しいタスクを削除します。

このセクションで使用される JavaScript について詳しくは、以下をご覧ください。

* `document.createElement()`
* `document.createTextNode()`
* `document.createDocumentFragment()`
* `eventTarget.addEventListener()`
* `node.appendChild()`
* `node.removeChild()`
UI を構築する別の方法
------------

すべての JavaScript フレームワークは、ユーザーインターフェイスをより *宣言的に* 記述する方法を提供します。つまり、UI がどのように見えるべきかを記述するコードを作成でき、フレームワークはそれを舞台裏の DOM で実行します。

新しい DOM 要素を繰り返し構築する標準的な JavaScript のアプローチは、一見しただけでは理解するのが困難でした。対照的に、次のコードブロックは、 Vue を使用してタスクのリストを記述する方法を示しています。

```html
<ul>
  <li v-for="task in tasks" v-bind:key="task.id">
    <span>{{task.name}}</span>
    <button type="button">Delete</button>
  </li>
</ul>
```

これだけです。このスニペットにより、約 32 行のコードが 6 行に減ります。 ここでの中括弧と `v-` 属性に馴染みがなくても大丈夫です。 Vue 固有の構文については、モジュールの後半で学習します。ここで理解すべきことは、このコードはそれが表す UI に似ているのに対し、 Vanilla Javascript コードはそうではないということです。

Vue のおかげで、 UI を構築するために独自の関数を作成する必要がなくなりました。フレームワークは、最適化された効率的な方法でそれを処理します。ここでの私たちの唯一の役割は、各項目がどのように見えるべきかを Vue に記述することでした。 Vue に精通している開発者は、プロジェクトに参加すると何が起こっているのかをすぐに理解できます。これは Vue だけではありません。フレームワークを使用すると、チームだけでなく個人の効率も向上します。

これと *似たようなこと* を Vanilla Javascript でも実現できます。テンプレートリテラル文字列を使用すると、最終的な要素がどのようになるかを表す HTML の文字列を簡単に作成できます。これは、 To Do リストアプリケーションのような単純なものには便利なアイデアかもしれませんが、数千のデータレコードを管理し、ユーザーインターフェイスに同じ数の固有の要素をレンダリングする可能性がある大規模なアプリケーションでは維持できません。

フレームワークが私たちに与えてくれるその他のこと
------------------------

フレームワークが提供する他の利点を見てみましょう。前にも述べたように、フレームワークの利点は Vanilla Javascript でも実現可能ですが、フレームワークを使うことで、これらの問題を自分で解決しなければならないという認知的な負荷をすべて取り除くことができます。

### ツール

このモジュールに含まれるフレームワークはそれぞれ大規模で活発なコミュニティを持っているので、それぞれのフレームワークのエコシステムは開発者の経験を向上させるツールを提供します。これらのツールによって、テスト(アプリケーションがあるべきように動作することを保証する) や lint (コードがエラーフリーでスタイルが一貫していることを保証する)のようなものを簡単に追加できます。

**メモ:** ウェブツールのコンセプトについてもっと詳しく知りたい方は、クライアントサイドツールの概要をご覧ください。

### コンパートメント化

ほとんどの主要なフレームワークは、開発者がユーザーインターフェイスのさまざまな部分を *コンポーネント* 、つまり相互に通信できる保守可能で再利用可能なコードの塊に抽象化することを推奨しています。特定のコンポーネントに関連するすべてのコードは 1 つのファイル (またはいくつかの特定のファイル)に保存できるため、開発者はそのコンポーネントに変更を加えるためにどこに行けばよいかを正確に知ることができます。 Vanilla Javascript アプリでは、これを効率的かつスケーラブルな方法で実現するには、独自の規則セットを作成する必要があります。多くの JavaScript 開発者は、自分のデバイスに任せると、 UI の一部に関連するすべてのコードが 1 つのファイル全体に、または別のファイル全体に分散されてしまう可能性があります。

### ルーティング

ウェブの最も重要な機能は、ユーザーがあるページから別のページに移動できることです。ウェブは結局のところ、相互リンクされたドキュメントのネットワークです。このウェブサイト上のリンクをたどると、ブラウザーがサーバーと通信し、表示する新しいコンテンツを取得します。そうすると、アドレスバーの URL が変わります。この新しい URL を保存して、後でそのページに戻ったり、他のユーザーと共有して同じページを簡単に見つけたりすることができます。ブラウザーはナビゲーション履歴を記憶しており、前後に移動することもできます。これは **サーバー側ルーティング** と呼ばれます。

最新のウェブアプリケーションは通常、新しい HTML ファイルを取得してレンダリングしません。ユーザーをウェブ上の新しいアドレスに誘導することなく、単一の HTML シェルをロードし、その中の DOM (**シングルページアプリ**、または **SPA: Single Page Aoolication** と呼ばれます) を継続的に更新します。新しい疑似ウェブページは通常、 *ビュー* と呼ばれ、デフォルトではルーティングは行われません。

SPA が十分に複雑で、十分な独自のビューをレンダリングする場合、アプリケーションにルーティング機能を組み込むことが重要です。人々は、アプリケーション内の特定のページにリンクしたり、ナビゲーション履歴を前後に移動したりできることに慣れていますが、これらの標準的なウェブ機能が壊れるとエクスペリエンスが低下します。この方法でクライアントアプリケーションによってルーティングが処理される場合、それは適切にも**クライアントサイドルーティング**と呼ばれます。

JavaScript とブラウザーのネイティブ機能を使用してルーターを作成することは *可能* ですが、人気があり積極的に開発されているフレームワークには、ルーティングを開発プロセスのより直感的な部分にする付属ライブラリーがあります。

フレームワークを使用する際の考慮事項
------------------

有能なウェブ開発者になるには、仕事に最適なツールを使用する必要があります。 JavaScript フレームワークはフロントエンドアプリケーションの開発を容易にしますが、すべての問題を解決する特効薬ではありません。このセクションでは、フレームワークを使用する際に考慮すべき点について説明します。フレームワークがまったく必要ない場合もあることを念頭に置いてください。フレームワークを目的だけで使用することのないように注意してください。

### ツールに精通している

Vanilla Javascript と同様に、フレームワークは学習に時間がかかり、癖があります。プロジェクトにフレームワークを使用することを決定する前に、そのフレームワークが自分にとって不利になるのではなく、自分にとって役立つように、その機能を十分に学習する時間を確保し、チームメイトもそのフレームワークに慣れているかどうかを確認してください。

### オーバーエンジニアリング

もしあなたのウェブ開発プロジェクトが数ページの個人的なポートフォリオで、それらのページにインタラクティブな機能がほとんどない、もしくは全くないのであれば、フレームワーク（とその JavaScript のすべて）は全く必要ないかもしれません。とはいえ、フレームワークは一枚岩ではないし、小規模なプロジェクトに適したものもある。 Smashing Magazine の記事で、 Sarah Drasner は、ウェブページの小さな部分をインタラクティブにするツールとして、Vue が jQuery を置き換えることができるということを書いています。

### より大きなコードベースと抽象化

フレームワークを使用すると、舞台裏で DOM インタラクションを処理することで、より宣言的なコードを作成でき、場合によっては全体的にコードが *少なくなる* 場合もあります。 この抽象化は開発者としてのエクスペリエンスに最適ですが、無料ではありません。作成した内容を DOM の変更に変換するには、フレームワークが独自のコードを実行する必要があり、その結果、最終的なソフトウェアのサイズが大きくなり、操作にかかる計算コストが高くなります。

追加のコードは避けられず、ツリーシェイキング(ビルドプロセス中にアプリで実際に使用されていないコードの削除)をサポートするフレームワークを使用すると、アプリケーションを小さく保つことができますが、これは依然として必要な要素です。特に携帯電話など、ネットワークやストレージに制約のあるデバイスでのアプリのパフォーマンスを考慮する際には、この点に留意してください。

フレームワークの抽象化は、 JavaScript だけでなく、ウェブの性質そのものとの関係にも影響します。ウェブ用にどのように構築しても、最終結果、つまりユーザーが最終的に対話するレイヤーは HTML です。アプリケーション全体を JavaScript で記述すると、 HTML とそのさまざまなタグの目的を見失い、セマンティックではなくアクセスできない HTML ドキュメントが作成される可能性があります。実際、 JavaScript に完全に依存し、 JavaScript なしでは機能しない脆弱なアプリケーションを作成することも可能です。

フレームワークが問題の原因ではありません。優先順位を間違えると、アプリケーションは壊れやすく、肥大化し、アクセスできなくなる可能性があります。ただし、フレームワークにより、開発者としての優先順位がさらに高まります。複雑なウェブアプリを作成することを優先する場合、それは簡単です。ただし、優先順位によってパフォーマンスとアクセシビリティが慎重に守られていない場合、フレームワークによって脆弱性、肥大化、アクセス不能性が増幅されてしまいます。フレームワークによって強化された現代の開発者の優先順位は、多くの場所でウェブの構造を逆転させています。 現在のウェブでは、堅牢なコンテンツ優先のドキュメントネットワークの代わりに、 JavaScript が優先され、ユーザーエクスペリエンスが最後に配置されることが多くなっています。

フレームワーク主導のウェブでのアクセシビリティ
-----------------------

前のセクションで述べたことを踏まえて、アクセシビリティについてもう少し詳しく説明しましょう。ユーザーインターフェイスをアクセスしやすくするには、常にある程度の思考と努力が必要ですが、フレームワークによってそのプロセスが複雑になる場合があります。 ARIA ライブリージョン やフォーカス管理などのネイティブブラウザー機能にアクセスするには、多くの場合、高度なフレームワーク API を使用する必要があります。

場合によっては、フレームワークアプリケーションによって、従来のウェブサイトには存在しないアクセシビリティの障壁が生じることがあります。この最大の例は、前述したように、クライアント側のルーティングです。

従来の(サーバーサイド)ルーティングでは、ウェブをナビゲートすると予測可能な結果が得られます。ブラウザーはページの上部にフォーカスを設定することを認識し、支援技術がページのタイトルをアナウンスします。これらのことは、新しいページに移動するたびに発生します。

クライアント側ルーティングでは、ブラウザーは新しいウェブページを読み込まないため、フォーカスを自動的に調整したり、新しいページタイトルをアナウンスしたりする必要があることを認識しません。フレームワークの作成者は、これらの機能を再現する JavaScript の作成に膨大な時間と労力を費やしてきましたが、それでも、これほど完璧に実行できるフレームワークはありませんでした。

結論としては、 *すべての* ウェブプロジェクトの最初からアクセシビリティを考慮する必要がありますが、そうしないと、フレームワークを使用する抽象化されたコードベースで重大なアクセシビリティの問題が発生する可能性が高くなることに留意してください。

フレームワークの選び方
-----------

このモジュールで説明する各フレームワークは、ウェブアプリケーション開発に対して異なるアプローチを取ります。それぞれが定期的に改善されたり変化したりしており、それぞれに長所と短所があります。適切なフレームワークを選択することは、チームとプロジェクトに依存するプロセスであり、何があなたのニーズに合っているかを明らかにするために、あなた自身で調査する必要があります。とはいえ、選択肢をより効果的に調査するために、いくつかの質問を挙げてみました

1. フレームワークはどのブラウザーをサポートしていますか？
2. フレームワークではどのようなドメイン固有言語が使用されますか？
3. このフレームワークには強力なコミュニティがあり、優れたドキュメント(およびその他のサポート)が利用可能ですか？

このセクションの表は、各フレームワークが現在提供している *ブラウザーのサポート* と、**ドメイン固有言語**を一目でわかるようにまとめたものです。

大まかに言うと、ドメイン固有言語（DSL）は、ソフトウェア開発の特定の分野に関連するプログラミング言語です。フレームワークの文脈では、 DSL は JavaScript や HTML のバリエーションで、そのフレームワークでの開発を容易にします。重要なことは、どのフレームワークも特定の DSL を使うことを開発者に *要求* しませんが、ほとんどすべてのフレームワークが特定の DSL を念頭に置いて設計されているということです。フレームワークが推奨する DSL を使わないという選択は、そうでなければ開発者のエクスペリエンスを向上させる機能を逃してしまうことを意味します。

新しいプロジェクトを選択するときは、フレームワークのサポートマトリックスと DSL を真剣に検討する必要があります。ブラウザーのサポートが一致しないと、ユーザーの障害となる可能性があります。 DSL サポートが一致しないと、あなたとあなたのチームメイトにとって障害となる可能性があります。

| Framework | Browser support | Preferred DSL | Supported DSLs | Citation |
| --- | --- | --- | --- | --- |
| Angular | モダン | TypeScript | HTML-based; TypeScript | 公式ドキュメント |
| React | モダン | JSX | JSX; TypeScript | 公式ドキュメント |
| Vue | モダン (IE9+ in Vue 2) | HTML-based | HTML-based, JSX, Pug | 公式ドキュメント |
| Ember | モダン (IE9+ in Ember version 2.18) | Handlebars | Handlebars, TypeScript | 公式ドキュメント |

**メモ:** 「HTML-based」と説明した DSL には正式な名前がありません。これらは実際には真の DSL ではありませんが、非標準の HTML であるため、強調する価値があると考えられます。

### フレームワークには強力なコミュニティがありますか？

コミュニティの規模はアクセスしやすい数字と直接相関しないため、これはおそらく測定するのが最も難しい指標です。プロジェクトの GitHub スターの数や週ごとの npm ダウンロードを確認して人気を知ることができますが、いくつかのフォーラムを検索したり、他の開発者に相談したりするのが最善の場合もあります。コミュニティの規模だけでなく、コミュニティがどれほど歓迎的で包括的であるか、利用可能なドキュメントがどれほど優れているかも重要です。

### ウェブ上の意見

この問題については、私たちの言葉をそのまま鵜呑みにしないでください。ウェブ上では議論が行われています。ウィキメディア財団は最近、フロントエンドに Vue を使用することを選択し、フレームワークの採用に関するコメント要求( RFC )を投稿しました。 RFC の著者である Eric Gardner は、時間をかけてウィキメディアプロジェクトのニーズと、特定のフレームワークがチームにとって良い選択である理由を概説しました。この RFC は、フロントエンドフレームワークの使用を計画するときに自分で行うべき調査の優れた例として役立ちます。

JavaScript の現状調査アンケート は、 JavaScript 開発者からの有益なフィードバックを集めたものです。フレームワークの使用とフレームワークに対する開発者の感情の両方に関するデータなど、 JavaScript に関連する多くのトピックをカバーしています。現在、数年分のデータが入手可能であり、フレームワークの人気を把握することができます。

Vue チームは Vue を他の一般的なフレームワークと徹底的に比較しました。この比較には多少の偏りがあるかもしれません(彼らはそれを指摘しています)が、それでも貴重な情報源です。

クライアント側フレームワークの代替
-----------------

ウェブ開発プロセスを迅速化するツールを探していて、プロジェクトで集中的なクライアントサイド JavaScript が必要ないことがわかっている場合は、ウェブを構築するための他のいくつかのソリューションのいずれかを利用できます。

* コンテンツ管理システム
* サーバーサイドレンダリング
* 静的サイトジェネレーター
### コンテンツ管理システム

**コンテンツ管理システム** (**CMS: Content-management systems**) は、ユーザーが自分で直接コードを書かずにウェブ用のコンテンツを作成できるツールのことです。大規模なプロジェクト、特にコーディング能力に乏しいコンテンツ・ライターからのインプットを必要とするプロジェクトや時間を節約したいプログラマーにとっては良いソリューションです。しかし CMS のセットアップにはかなりの時間を要し、 CMS を利用するということは、少なくともウェブサイトの最終的なアウトプットをコントロールする手段を放棄することを意味します。例えば、選択したCMSがデフォルトでアクセシブルなコンテンツを作成しない場合、これを改善するのは難しいことが多いです。

一般的な例としては、 Wordpress 、 Joomla 、 Drupal などがあります。

### サーバーサイドレンダリング

**サーバーサイドレンダリング** (**SSR: Server-side rendering**) は、単一ページアプリケーションをレンダリングするのが *サーバー* の仕事であるアプリケーションアーキテクチャです。これは、JavaScript アプリケーションを構築する最も一般的で最も簡単な方法である *クライアントサイドレンダリング* の逆です。サーバーサイドレンダリングは、レンダリングされた HTML ファイルをクライアントのデバイスに送信するだけなので、クライアントのデバイスでは簡単ですが、クライアント側でレンダリングされるアプリケーションに比べてセットアップが難しい場合があります。

このモジュールで説明されているフレームワークはすべて、クライアントサイドのレンダリングだけでなくサーバーサイドのレンダリングもサポートしています。 React については Next.js 、Vue については Nuxt.js(はい、わかりにくいです、いいえ、これらのプロジェクトは関係ありません!)、 Ember の場合は FastBoot、 Angular の場合は Angular Universal をチェックしてください。

**メモ:** SSR ソリューションの中にはコミュニティによって作成および保守されているものもありますが、フレームワークの保守者によって提供される「公式」ソリューションもあります。

### 静的サイトジェネレーター

静的サイトジェネレーターは、複数ページのウェブサイトのすべてのウェブページ(関連する CSS や JavaScript を含む)を動的に生成し、任意の数の場所に公開できるようにするプログラムです。公開ホストは例えば、 GitHub ページブランチ、 Netlify インスタンス、または選択したプライベートサーバーにすることができます。このアプローチには多くの利点があり、主にパフォーマンス(ユーザーのデバイスは JavaScript を使用してページを構築していません。すでに完成しています)とセキュリティ(静的ページは攻撃ベクトルが少ない)に関するものです。これらのサイトでは、必要に応じて JavaScript を引き続き利用できますが、 JavaScript に「依存」しているわけではありません。静的サイトジェネレーターは、他のツールと同様に学習に時間がかかるため、開発プロセスの障壁となる可能性があります。

静的サイトには、必要な数の固有のページを含めることができます。フレームワークを使用すると、クライアント側の JavaScript アプリケーションを迅速に作成できるようになりますが、静的サイトジェネレーターを使用すると、個別に作成する必要があった HTML ファイルを迅速に作成できます。フレームワークと同様、静的サイトジェネレーターを使用すると、開発者はウェブページの共通部分を定義するコンポーネントを作成し、それらのコンポーネントを組み合わせて最終ページを作成できます。静的サイトジェネレーターのコンテキストでは、これらのコンポーネントは **テンプレート** と呼ばれます。静的サイトジェネレーターによって構築されたウェブページは、フレームワークアプリケーションのホームとなることもあります。たとえば、静的に生成されたウェブサイトの特定のページで、ユーザーがそのページにアクセスしたときに React アプリケーションを起動したい場合は、それが可能です。

静的サイトジェネレーターはかなり昔から存在しており、最近のウェブの歴史の中で少しずつ復活を遂げています。 Hugo 、 Jekyll 、Eleventy および Gatsby などのいくつかの強力なオプションが利用可能になりました。。

静的サイトジェネレーター全体について詳しく知りたい場合は、Tatiana Mac の Eleventy の初心者ガイドを参照してください。シリーズの最初の記事では、静的サイトジェネレーターとは何か、そしてそれがウェブコンテンツを公開する他の手段とどのように関連するのかについて説明します。

まとめ
---

これで、フレームワークの紹介は終わりになります。まだコードを教えていませんが、そもそもフレームワークを使用する理由と、フレームワークの選択方法について有益な背景を提供できたことを願っています。 1 つ目は、もっと学びたい、夢中になってみたいという気持ちになっていただければ幸いです。

次の記事では、より低いレベルまで掘り下げて、フレームワークが提供する傾向にある特定の種類の機能と、フレームワークがなぜそのように機能するのかを見ていきます。

* Overview: Client-side JavaScript frameworks
* 次のページ  (en-US)


To Do アイテムのフィルタリング - ウェブ開発を学ぶ

To Do アイテムのフィルタリング
==================

* 前のページ
* Overview: Client-side JavaScript frameworks
* 次のページ

次に、ユーザーが To Do アイテムをフィルタリングできるようにする機能を追加して、アクティブなアイテム、完了したアイテム、またはすべてのアイテムを表示できるようにしましょう。

|  |  |
| --- | --- |
| 前提条件: |
HTML、
 CSS、
 JavaScript に精通していること、
 ターミナル/コマンドラインに関する知識があること。
  |
| 目的: | アプリにフィルタリング機能を追加します。 |

フィルタリングコード
----------

フィルタリングは、以前に `app.component.ts` に追加した `filter` プロパティに基づいて構成されています。

```ts
filter: 'all' | 'active' | 'done' = 'all';
```

filter のデフォルト値は `all` ですが、 `active` または `done` にすることもできます。

フィルター コントロールの追加
---------------

`app.component.html` で、次の HTML を **Add** ボタンの前、アイテムをリストするセクションの上に追加します。
 次のスニペットでは、HTML の既存のセクションがコメントになっているため、ボタンを配置する場所を正確に確認できます。

```html
<!-- <button class="btn-primary" (click)="addItem(newItem.value)">Add</button>
 -->

<!-- Buttons that show all, still to do, or done items on click -->
<div class="btn-wrapper">
  <button
 class="btn btn-menu"
 [class.active]="filter == 'all'"
 (click)="filter = 'all'">
    All
  </button>

  <button
 class="btn btn-menu"
 [class.active]="filter == 'active'"
 (click)="filter = 'active'">
    To Do
  </button>

  <button
 class="btn btn-menu"
 [class.active]="filter == 'done'"
 (click)="filter = 'done'">
    Done
  </button>
</div>

<!-- <h2>{{items.length}} item(s)</h2>
 <ul>... -->
```

ボタンをクリックすると `filter` 値が変更され、Angular がアクティブなボタンにスタイルを適用し、表示する `items` を決定します。

* ユーザーが **All** ボタンをクリックすると、すべてのアイテムが表示されます。
* ユーザーが **To do** ボタンをクリックすると、 `done` の値が `false` のアイテムが表示されます。
* ユーザーが **Done** ボタンをクリックすると、 `done` 値が `true` のアイテムが表示されます。

 角括弧 `[]` を使用したクラス属性バインディングは、ボタンのテキストの色を制御します。
 クラスバインディング `[class.active]` は、 `filter` の値が式と一致する場合に `active` クラスを適用します。
 たとえば、ユーザーが **Done** ボタンをクリックして `filter` 値を `done` に設定すると、クラス バインディング式 `filter == 'done'` は `true` に評価されます。
 `filter` 値が `done` の場合、Angular は `active` クラスを **Done** ボタンに適用し、テキストの色を緑色にします。
 ユーザーが他のボタンのいずれかをクリックするとすぐに、 `filter` の値は `done` ではなくなるため、緑色のテキスト色は適用されなくなります。

まとめ
---

簡単でしたね！ `app.component.ts` には既に `filter` コードがあるので、アイテムのフィルタリングをコントロールする為にテンプレートを編集するだけで済みました。 次の - そして最後の - 記事では、Angular アプリを本番環境で構築する方法を検討し、学習の旅を続けるための追加のリソースを提供します。

* 前のページ
* Overview: Client-side JavaScript frameworks
* 次のページ


item コンポーネントの作成 - ウェブ開発を学ぶ

item コンポーネントの作成
===============

* 前のページ
* Overview: Client-side JavaScript frameworks
* 次のページ

コンポーネントは、アプリケーションを構成する方法を提供します。 この記事では、リスト内の個々の item を処理するコンポーネントを作成し、チェック、編集、および削除機能を追加する方法について説明します。 ここでは、Angular イベントモデルについて説明します。

|  |  |
| --- | --- |
| 前提条件: |
HTML、
 CSS、
 JavaScript に精通していること、
 ターミナル/コマンドラインに関する知識があること。
  |
| 目的: | イベントが更新を処理するためにどのように機能するかなど、コンポーネントの詳細を学習します。 チェック、編集、および削除機能を追加します。 |

コンポーネントの新規作成
------------

コマンドラインで、次の CLI コマンドを使用して `item` という名前のコンポーネントを作成します。

```bash
ng generate component item
```

`ng generate component` コマンドは、指定した名前でコンポーネントとフォルダーを作成します。
 ここで、フォルダーとコンポーネントの名前は `item` です。
 `item` ディレクトリーは `app` フォルダー内にあります。

`AppComponent` と同様に、 `ItemComponent` は次のファイルで構成されています。

* `item.component.html` は、 HTML ファイルです。
* `item.component.ts` は、 logic ファイルです。
* `item.component.css` は、 styles ファイルです。

HTML ファイルと CSS ファイルへの参照は、 `item.component.ts` の `@Component()` デコレーターメタデータで確認できます。

```js
@Component({
  selector: 'app-item',
  templateUrl: './item.component.html',
  styleUrls: ['./item.component.css'],
})
```

ItemComponent の HTML を追加
------------------------

`ItemComponent` は、完了したアイテムをチェックしたり、編集したり、削除したりする方法をユーザーに提供するタスクを引き継ぐことができます。

`item.component.html` のプレースホルダーコンテンツを次のように置き換えて、アイテムを管理するためのマークアップを追加します。

```html
<div class="item">
  <input
 [id]="item.description"
 type="checkbox"
 (change)="item.done = !item.done"
 [checked]="item.done" />
  <label [for]="item.description">{{item.description}}</label>

  <div class="btn-wrapper" \*ngIf="!editable">
    <button class="btn" (click)="editable = !editable">Edit</button>
    <button class="btn btn-warn" (click)="remove.emit()">Delete</button>
  </div>

  <!-- This section shows only if user clicks Edit button -->
  <div \*ngIf="editable">
    <input
 class="sm-text-input"
 placeholder="edit item"
 [value]="item.description"
 #editedItem
 (keyup.enter)="saveItem(editedItem.value)" />

    <div class="btn-wrapper">
      <button class="btn" (click)="editable = !editable">Cancel</button>
      <button class="btn btn-save" (click)="saveItem(editedItem.value)">
        Save
      </button>
    </div>
  </div>
</div>
```

 最初の入力はチェックボックスであるため、ユーザーはアイテムが完了したときにアイテムをチェックできます。
 チェックボックスの `<input>` と `<label>` にある二重中括弧 `{{}}` は、Angular の補間を示します。
 Angular は `{{item.description}}` を使用して、 `items` 配列から現在の `item` の説明を取得します。
 次のセクションでは、コンポーネントがデータを共有する方法について詳しく説明します。

 現在のアイテムを編集および削除するための次の 2 つのボタンは、 `<div>` 内にあります。
 この `<div>` には `*ngIf` があります。これは、DOM の構造を動的に変更するために使用できる組み込みの Angular ディレクティブです。

この `*ngIf` は、 `editable` が `false` の場合、この `<div>` が DOM にあることを意味します。 `editable` が `true` の場合、Angular はこの `<div>` を DOM から削除します。

```html
<div class="btn-wrapper" \*ngIf="!editable">
  <button class="btn" (click)="editable = !editable">Edit</button>
  <button class="btn btn-warn" (click)="remove.emit()">Delete</button>
</div>
```

 ユーザーが **Edit** ボタンをクリックすると、「編集可能」が true になり、この `<div>` とその子が DOM から削除されます。
 ユーザーが **Edit** をクリックする代わりに **Delete** をクリックすると、 `ItemComponent` は `AppComponent` に削除を通知するイベントを発生させます。

`*ngIf` も次の `<div>` にありますが、 `editable` 値 `true` に設定されています。
 この場合、 `editable` が `true` の場合、Angular は `<div>` とその子要素 `<input>` と `<button>` を DOM に配置します。

```html
<!-- This section shows only if user clicks Edit button -->
<div \*ngIf="editable">
  <input
 class="sm-text-input"
 placeholder="edit item"
 [value]="item.description"
 #editedItem
 (keyup.enter)="saveItem(editedItem.value)" />

  <div class="btn-wrapper">
    <button class="btn" (click)="editable = !editable">Cancel</button>
    <button class="btn btn-save" (click)="saveItem(editedItem.value)">
      Save
    </button>
  </div>
</div>
```

`[value]="item.description"` を使用すると、 `<input>` の値は現在のアイテムの `description` にバインドされます。
 このバインディングにより、アイテムの `description` が `<input>` の値になります。
 したがって、 `description` が `eat` の場合、 `description` はすでに `<input>` にあります。
 このように、ユーザーがアイテムを編集するとき、 `<input>` の値はすでに `eat` です。

`<input>` のテンプレート変数 `#editedItem` は、Angular がユーザーがこの `<input>` に入力したものをすべて `editedItem` という変数に格納することを意味します。
 `keyup` イベントは `saveItem()` メソッドを呼び出し、ユーザーが **Save** をクリックする代わりに Enter キーを押すことを選択した場合、 `editedItem` 値を渡します。

 ユーザーが **Cancel** ボタンをクリックすると、 `editable` が `false` に切り替わり、DOM から編集用の入力とボタンが削除されます。
 `editable` が `false` の場合、Angular は **Edit** と **Delete** ボタンを使用して `<div>` を DOM に戻します。

**Save** ボタンをクリックすると、 `saveItem()` メソッドが呼び出されます。
 `saveItem()` メソッドは `#editedItem` `<input>` から値を取得し、アイテムの `description` を `editedItem.value` 文字列に変更します。

AppComponent の準備
----------------

 次のセクションでは、 `AppComponent` と `ItemComponent` の通信に依存するコードを追加します。
 `app.component.ts` に以下を追加して、最初に AppComponent を構成します。

```js
remove(item) {
  this.allItems.splice(this.allItems.indexOf(item), 1);
}
```

`remove()` メソッドは JavaScript の `Array.splice()` メソッドを使用して、関連するアイテムの `indexOf` にある 1 つのアイテムを削除します。
 平易な英語では、これは `splice()` メソッドが配列からアイテムを削除することを意味します。
 `splice()` メソッドの詳細については、`Array.prototype.splice()` に関する MDN Web Docs の記事を参照してください。 。

ItemComponent にロジックを追加
----------------------

`ItemComponent` UI を使用するには、関数やデータの出入り方法などのロジックをコンポーネントに追加する必要があります。

`item.component.ts` で、JavaScript インポートを次のように編集します。

```js
import { Component, Input, Output, EventEmitter } from "@angular/core";
import { Item } from "../item";
```

`Input`, `Output`, および `EventEmitter` を追加すると、 `ItemComponent` が `AppComponent` とデータを共有できるようになります。
 `Item` をインポートすることにより、 `ItemComponent` は `item` が何であるかを理解することができます。

Further down `item.component.ts`, replace the generated `ItemComponent` class with the following:

`item.component.ts` 内で、生成された `ItemComponent` クラスを次のように置き換えます。

```js
export class ItemComponent {

  editable = false;

  @Input() item: Item;
  @Input() newItem: string;
  @Output() remove = new EventEmitter<Item>();

  saveItem(description) {
    if (!description) return;
    this.editable = false;
    this.item.description = description;
  }
}
```

`editable` プロパティは、ユーザーがアイテムを編集できるテンプレートのセクションを切り替えるのに役立ちます。
 `editable` は、 `*ngIf` ステートメント `*ngIf="editable"` と同じ HTML のプロパティです。
 テンプレートでプロパティを使用する場合は、クラスでも宣言する必要があります。

`@Input()`, `@Output()`, 及び `EventEmitter` は、2 つのコンポーネント間の通信を容易にします。
 `@Input()` は、データがコンポーネントに入るための出入り口として機能し、 `@Output()` は、データがコンポーネントから出て行くための出入り口として機能します。
 `@Output()` は `EventEmitter` 型である必要があります。これにより、別のコンポーネントと共有する準備ができているデータがあるときに、コンポーネントがイベントを発生させることができます。

`@Input()` を使用して、プロパティの値がコンポーネントの外部から取得できることを指定します。
 `@Output()` を `EventEmitter` と組み合わせて使用して、プロパティの値がコンポーネントを離れることができるように指定して、別のコンポーネントがそのデータを受け取れるようにします。

`saveItem()` メソッドは引数として `description` を取ります。
 `description` は、リスト内のアイテムを編集するときにユーザーが HTML の `<input>` に入力するテキストです。
 この `description` は、 `#editedItem` テンプレート変数を持つ `<input>` からの同じ文字列です。

 ユーザーが値を入力せずに **Save** をクリックした場合、 `saveItem()` は何も返さず、 `description` を更新しません。
 この `if` ステートメントがない場合、ユーザーは HTML の `<input>` に何も入力せずに **Save** をクリックすると、 `description` は空の文字列になります。

ユーザーがテキストを入力して save をクリックすると、 `saveItem()` は `editable` を false に設定します。これにより、テンプレートの `*ngIf` が編集機能を削除し、再び **Edit** と **Delete** ボタンをレンダリングします。

この時点でアプリケーションをコンパイルする必要がありますが、ブラウザーで新機能を確認できるように、 `AppComponent` で `ItemComponent` を使用する必要があります。

AppComponent で ItemComponent を使用
--------------------------------

親子関係のコンテキストで 1 つのコンポーネントを別のコンポーネントに含めると、必要な場所でコンポーネントを柔軟に使用できます。

`AppComponent` は、他のコンポーネントを含めることができるアプリケーションのシェルとして機能します。

`AppComponent` で `ItemComponent` を使用するには、 `AppComponent` テンプレートに `ItemComponent` セレクターを配置します。
 Angular は、 `@Component()` デコレーターのメタデータ内にあるコンポーネントのセレクターを指定します。
 この例では、セレクターは `app-item` です。

```js
@Component({
  selector: 'app-item',
  templateUrl: './item.component.html',
  styleUrls: ['./item.component.css']
})
```

`AppComponent` 内で `ItemComponent` セレクターを使用するには、コンポーネントクラスに定義したセレクターに対応する要素 `<app-item>` を `app.component.html` に追加します。
 `app.component.html` の現在の順序付けされていないリストを次の更新されたバージョンに置き換えます。

```html
<h2>
  {{items.length}}
  <span \*ngIf="items.length === 1; else elseBlock">item</span>
  <ng-template #elseBlock>items</ng-template>
</h2>

<ul>
  <li \*ngFor="let item of items">
    <app-item (remove)="remove(item)" [item]="item"></app-item>
  </li>
</ul>
```

 The double curly brace syntax, `{{}}`, in the `<h2>` interpolates the length of the `items` array and displays the number.
 `<h2>` の二重中括弧構文 `{{}}` は、 `items` 配列の長さを取得し、数値を表示します。

`<h2>` の `<span>` は `*ngIf` と `else` を使用して、 `<h2>` が "item" と "items" のどちらを表示するかを決定します。
 リストに item が 1 つしかない場合は、 "item" を含む `<span>` が表示されます。
 それ以外の場合、 `items` 配列の長さが `1` 以外の場合、構文 `#elseBlock` で `elseBlock`と名付けた `<ng-template>` の代わりに `<span>` が表示されます。
 デフォルトでコンテンツをレンダリングしたくない場合は、Angular の `<ng-template>` を使用できます。
 この場合、 `items` 配列の長さが `1` でない場合、 `*ngIf` は `<span>` ではなく `elseBlock` を表示します。

`<li>` は、Angular の repeater directive `*ngFor` を使用して、 `items` 配列内のすべてのアイテムを反復処理します。
 `*ngIf`のような Angular の `*ngFor` は、より少ないコードを記述しながら DOM の構造を変更するのに役立つもう 1 つの directive です。
 `items` ごとに、Angular は `<li>` とその中のすべてを繰り返します。これには `<app-item>` が含まれます。
 これは、配列内のアイテムごとに、Angular が `<app-item>` の別のインスタンスを作成することを意味します。
 配列内の任意の数のアイテムに対して、Angular はその数の `<li>` 要素を作成します。

いくつか例を挙げると、 `<div>`, `<span>`, や `<p>`, などの他の要素にも `*ngFor` を使用できます。

`AppComponent` には、アイテムを削除するための `remove()` メソッドがあります。これは、 `ItemComponent` の `remove` プロパティにバインドされています。
 角括弧内の `item` プロパティ `[]` は、 `AppComponent` と `ItemComponent` の間の `item` の値をバインドします。

 これで、リストからアイテムを編集および削除できるようになります。
 アイテムを追加または削除すると、アイテムの数も変更されます。
 リストをより使いやすくするには、 `ItemComponent` にいくつかのスタイルを追加します。

ItemComponent にスタイルを追加
----------------------

 コンポーネントのスタイルシートを使用して、そのコンポーネントに固有のスタイルを追加できます。
 次の CSS は、基本的なスタイル、ボタンのフレックスボックス、およびカスタムチェックボックスを追加します。

次のスタイルを `item.component.css` に貼り付けます。

```css
.item {
  padding: 0.5rem 0 0.75rem 0;
  text-align: left;
  font-size: 1.2rem;
}

.btn-wrapper {
  margin-top: 1rem;
  margin-bottom: 0.5rem;
}

.btn {
  /\* menu buttons flexbox styles \*/
  flex-basis: 49%;
}

.btn-save {
  background-color: #000;
  color: #fff;
  border-color: #000;
}

.btn-save:hover {
  background-color: #444242;
}

.btn-save:focus {
  background-color: #fff;
  color: #000;
}

.checkbox-wrapper {
  margin: 0.5rem 0;
}

.btn-warn {
  background-color: #b90000;
  color: #fff;
  border-color: #9a0000;
}

.btn-warn:hover {
  background-color: #9a0000;
}

.btn-warn:active {
  background-color: #e30000;
  border-color: #000;
}

.sm-text-input {
  width: 100%;
  padding: 0.5rem;
  border: 2px solid #555;
  display: block;
  box-sizing: border-box;
  font-size: 1rem;
  margin: 1rem 0;
}

/\* Custom checkboxes
Adapted from https://css-tricks.com/the-checkbox-hack/#custom-designed-radio-buttons-and-checkboxes \*/

/\* Base for label styling \*/
[type="checkbox"]:not(:checked),
[type="checkbox"]:checked {
  position: absolute;
  left: -9999px;
}
[type="checkbox"]:not(:checked) + label,
[type="checkbox"]:checked + label {
  position: relative;
  padding-left: 1.95em;
  cursor: pointer;
}

/\* checkbox aspect \*/
[type="checkbox"]:not(:checked) + label:before,
[type="checkbox"]:checked + label:before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 1.25em;
  height: 1.25em;
  border: 2px solid #ccc;
  background: #fff;
}

/\* checked mark aspect \*/
[type="checkbox"]:not(:checked) + label:after,
[type="checkbox"]:checked + label:after {
  content: "\2713\0020";
  position: absolute;
  top: 0.15em;
  left: 0.22em;
  font-size: 1.3em;
  line-height: 0.8;
  color: #0d8dee;
  transition: all 0.2s;
  font-family: "Lucida Sans Unicode", "Arial Unicode MS", Arial;
}
/\* checked mark aspect changes \*/
[type="checkbox"]:not(:checked) + label:after {
  opacity: 0;
  transform: scale(0);
}
[type="checkbox"]:checked + label:after {
  opacity: 1;
  transform: scale(1);
}

/\* accessibility \*/
[type="checkbox"]:checked:focus + label:before,
[type="checkbox"]:not(:checked):focus + label:before {
  border: 2px dotted blue;
}
```

まとめ
---

 これで、アイテムを追加、編集、および削除できるスタイル付きの AngularToDo リストアプリケーションができました。
 次のステップは、特定の条件を満たすアイテムを確認できるようにフィルタリングを追加することです。

* 前のページ
* Overview: Client-side JavaScript frameworks
* 次のページ


React アプリのコンポーネント化 - ウェブ開発を学ぶ

React アプリのコンポーネント化
==================

* 前のページ
* Overview: Client-side JavaScript frameworks
* 次のページ  (en-US)

この時点では、アプリは一枚岩です。アプリに何かをさせる前に、管理しやすく、記述しやすいコンポーネントに分解する必要があります。 React には、何がコンポーネントで何がコンポーネントでないかという難しいルールはありません。それはあなた次第なのです！この記事では、アプリをコンポーネントに分解するための賢明な方法を紹介します。

|  |  |
| --- | --- |
| 前提条件: | HTML、CSS、JavaScript のコア言語に精通していること、ターミナル/コマンドラインの知識があること。 |
| 目的: | Todo リストアプリをコンポーネントに分割するための賢明な方法を示すこと。 |

最初のコンポーネントの定義
-------------

コンポーネントの定義は、ある程度練習をするまでは難しいと思われるかもしれませんが、要点は以下の通りです。

* アプリの明らかな「塊」を表している場合、それはおそらくコンポーネントです。
* よく再利用されるのであれば、それはおそらくコンポーネントです。

2 番目の項目には特に価値があります。一般的な UI 要素からコンポーネントを作成することで、コードを一箇所で変更することができ、そのコンポーネントが使用される場所のどこでも変更内容を確認することができます。また、すぐにすべてをコンポーネントに分割する必要もありません。 2 つ目の項目をヒントに、UI の中で最も再利用され、最も重要な部分である TODO リスト項目からコンポーネントを作成してみましょう。

`<Todo />` の作成
--------------

コンポーネントを作る前に、そのための新しいファイルを作らなければなりません。実際は、コンポーネント用の新しいディレクトリーの作成が必要です。次のコマンドは、 `components` ディレクトリーを作成し、その中に `Todo.js` というファイルを作成します。これらを実行する前に、アプリのルートにいることを確認してください。

```bash
mkdir src/components
touch src/components/Todo.js
```

新しい `Todo.js` ファイルは今は空です。ファイルを開いて最初の行に次を入力してください。

```js
import React from "react";
```

今回は `Todo` というコンポーネントを作る予定なので、以下のように `Todo.js` にもそのためのコードを追加していきます。このコードでは、関数の定義とエクスポートを一行で定義しています。

```js
export default function Todo() {
  return (

  );
}
```

ここまでは問題ありませんが、このコンポーネントは何かを返さなければなりません！`src/App.js` に戻って、最初の `<li>` をコピーし、 `Todo.js` に貼り付けると、以下のようになります。

```js
export default function Todo() {
  return (
    <li className="todo stack-small">
      <div className="c-cb">
        <input id="todo-0" type="checkbox" defaultChecked={true} />
        <label className="todo-label" htmlFor="todo-0">
          Eat
        </label>
      </div>
      <div className="btn-group">
        <button type="button" className="btn">
          Edit <span className="visually-hidden">Eat</span>
        </button>
        <button type="button" className="btn btn\_\_danger">
          Delete <span className="visually-hidden">Eat</span>
        </button>
      </div>
    </li>
  );
}
```

**メモ:** コンポーネントは常に何かを返さなければなりません。もし今後あなたが何も返さないコンポーネントをレンダリングしようとしたら、React はブラウザーにエラーを表示するでしょう。

これで `Todo` コンポーネントは完成しました。`App.js` で、ファイルの先頭付近に次の行を追加して `Todo` をインポートします。

```js
import Todo from "./components/Todo";
```

このコンポーネントをインポートすると、`App.js` の `<li>` 要素をすべて `<Todo />` コンポーネント呼び出しに置き換えることができます。 `<ul>` は以下のようになるはずです。

```js
<ul
  role="list"
  className="todo-list stack-large stack-exception"
  aria-labelledby="list-heading">
  <Todo />
  <Todo />
  <Todo />
</ul>
```

ブラウザーに戻ってみると、何か不幸なことに気づくでしょう。リストが、最初のタスクを 3 回繰り返すようになりました。

![Todo リストアプリの Todo コンポーネントラベルがコンポーネントにハードコードされているため、繰り返し使用されています。](/ja/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components/todo-list-repeating-todos.png)

私たちがすべきことは、食べることだけではありません。そう、他にもすべきことがあります。— そう、TODO があります。次に、異なるコンポーネント呼び出しで別々のコンテンツをレンダリングする方法を見てみましょう。

*一意の* `<Todo />` を作成
--------------------

コンポーネントが強力なのは、UI の一部を再利用し、その UI のソースを 1 か所で参照できるからです。問題は、通常、各コンポーネントのすべてを再利用するのではなく、ほとんどの部分を再利用しつつ小さな部分を変更したいということです。そこで props の出番です。

### `name` に何が入るでしょう？

完了させたいタスクの名前を追跡するために、それぞれの `<Todo />` コンポーネントが一意の名前を表示するようにしなければなりません。

`App.js` では、それぞれの `<Todo />` に name の prop を与えます。先ほどのタスクの名前を使ってみましょう。

```js
<Todo name="Eat" />
<Todo name="Sleep" />
<Todo name="Repeat" />
```

ブラウザーを更新すると...以前と全く同じものが表示されます。`<Todo />` に props を与えましたが、まだ使っていません。 `Todo.js` に戻って解決しましょう。

最初に `Todo()` 関数の定義を変更して、 `props` を引数として受け取るようにします。 `props` がコンポーネントによって正しく受信されているかどうかを確認したい場合は、先ほどと同様に `console.log()` で `props` を取得することができます。

コンポーネントが `props` を取得していることを確認したら、 `Eat` を `name` の prop で置き換えることができます。覚えておいてください。 JSX の式の途中では、中括弧を使って変数の値を注入します。

これらをまとめると、`Todo()` 関数は次のようになるはずです。

```js
export default function Todo(props) {
  return (
    <li className="todo stack-small">
      <div className="c-cb">
        <input id="todo-0" type="checkbox" defaultChecked={true} />
        <label className="todo-label" htmlFor="todo-0">
          {props.name}
        </label>
      </div>
      <div className="btn-group">
        <button type="button" className="btn">
          Edit <span className="visually-hidden">{props.name}</span>
        </button>
        <button type="button" className="btn btn\_\_danger">
          Delete <span className="visually-hidden">{props.name}</span>
        </button>
      </div>
    </li>
  );
}
```

\*これで、\*ブラウザーには 3 つの一意のタスクが表示されるようになりました。しかし、もう一つの問題が残っています。これらはすべて既定でチェックされています。

![Todo リストアプリには、異なる Todo ラベルが付けられており、それらはコンポーネントに props として渡されます。](/ja/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components/todo-list-unique-todos.png)

### それは `completed` ですか？

元の静的リストでは、`Eat` だけがチェックされていました。もう一度言いますが、`<Todo />` コンポーネントを構成する UI のほとんどを再利用しつつ、一つだけ変更したいのです。これは別の props が良い仕事をしてくれます！ `App.js` での各 `<Todo />` の呼び出しには、完了したことを示す新しい props を与えます。最初の (`Eat`) は `true` の値を持ち、残りは `false` にします。

```js
<Todo name="Eat" completed={true} />
<Todo name="Sleep" completed={false} />
<Todo name="Repeat" completed={false} />
```

先ほどと同様に、これらの props を実際に使用するためには `Todo.js` に戻る必要があります。`<input />` の `defaultChecked` 属性の値が `completed` した props と同じになるように変更します。これで、Todo コンポーネントの `<input />` 要素は次のようになります。

```js
<input id="todo-0" type="checkbox" defaultChecked={props.completed} />
```

そして、ブラウザーを更新すると、`Eat` だけがチェックされていることが表示されるようになるはずです。

![Todo リストアプリで、チェックの状態が異なるようになった。- あるチェックボックスはチェックされ、他のチェックボックスはチェックされない。](/ja/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components/todo-list-differing-checked-states.png)

各 `<Todo />` コンポーネントの `completed` prop を変更すると、ブラウザーはそれに応じてレンダリングされた同等のチェックボックスをチェックしたり、チェックを外したりします。

### `id` をください

現在、`<Todo />` コンポーネントはすべてのタスクに `todo-0` という `id` 属性を与えています。これは悪い HTML です、なぜなら id 属性 は一意でなければならないからです（CSS や JavaScript などで文書フラグメントの一意な識別子として使用されます）。つまり、各 `Todo` に対して一意の値を取る `id` prop をコンポーネントに与えるべきです。

最初と同じパターンに従うために、`<Todo />` コンポーネントの各インスタンスに `todo-i` の形式で ID を与えてみましょう。 `i` は毎回 1 つずつ大きくなっていきます。

```js
<Todo name="Eat" completed={true} id="todo-0" />
<Todo name="Sleep" completed={false} id="todo-1" />
<Todo name="Repeat" completed={false} id="todo-2" />
```

ここで `Todo.js` に戻り、`id` prop を使うようにします。これは `<input />` 要素の `id` 属性の値とラベルの `htmlFor` 属性の値を置き換える必要があります。

```js
<div className="c-cb">
  <input id={props.id} type="checkbox" defaultChecked={props.completed} />
  <label className="todo-label" htmlFor={props.id}>
    {props.name}
  </label>
</div>
```

ここまでは順調ですか？
-----------

今のところ React をうまく使っていますが、もっとうまくできるかもしれません。今のコードは反復的です。`<Todo />` コンポーネントをレンダリングする 3 つの行はほぼ同じですが、 1 つだけ違う点があります。それぞれの prop の値です。

JavaScript のコアな能力の一つであるイテレーション（反復処理）を使えば、コードをきれいにすることができます。イテレーションを使うためには、まず自分のタスクを再考する必要があります。

データとしてのタスク
----------

それぞれのタスクには現在、 3 つの情報が含まれています: 名前、チェック済みかどうか、そして一意な ID です。このデータはうまくオブジェクトに変換されます。複数のタスクがあるので、このデータを表現するにはオブジェクトの配列が有効です。

`src/index.js` で、 import の後 `ReactDOM.render()` より前の行で以下の `const` を作成してください。

```js
const DATA = [
  { id: "todo-0", name: "Eat", completed: true },
  { id: "todo-1", name: "Sleep", completed: false },
  { id: "todo-2", name: "Repeat", completed: false },
];
```

次に、 `tasks` という名前の props として `<App />` に `DATA` を渡します。`src/index.js` の最終行は以下のようになるはずです。

```js
ReactDOM.render(<App tasks={DATA} />, document.getElementById("root"));
```

この配列は、 App コンポーネントで `props.tasks` として利用できるようになりました。よかったら `console.log()` で確認してください。

**メモ:** すべて大文字の（`ALL_CAPS` のような）定数名に JavaScript で特別な意味があるわけではありません。他の開発者に「このデータはここで定義された後は変更されません」と伝えるための慣習です。

反復処理によるレンダリング
-------------

オブジェクトの配列をレンダリングするには、それぞれのオブジェクトを `<Todo />` コンポーネントに変換しなければなりません。 JavaScript では、データを別のものに変換するための配列メソッド `Array.prototype.map()` を提供しています。

`App()` の `return` 文の上に、`taskList` という新しい `const` を作り、`map()` を使って変換します。まず、 `tasks` の配列を、各タスクの名前というシンプルなものに変えてみましょう。

```js
const taskList = props.tasks?.map((task) => task.name);
```

`<ul>` のすべての子を `taskList`に置き換えてみましょう。

```js
<ul
  role="list"
  className="todo-list stack-large stack-exception"
  aria-labelledby="list-heading">
  {taskList}
</ul>
```

これで、すべてのコンポーネントを再表示できるようになりましたが、まだやるべきことがあります。現在、ブラウザーは各タスクの名前を構造化されていないテキストとして表示しています。私たちが HTML の構造を見失っているからです。— `<li>` とチェックボックス、ボタンのことです。

![Todo リストアプリで、Todo アイテムのラベルが1行にまとまって表示されています。](/ja/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components/todo-list-unstructured-names.png)

この問題を解決するには、 `map()` 関数から `<Todo />` コンポーネントを返す必要があります — JSX では、JavaScript とマークアップ構造を混在させることができることを覚えておいてください。今あるものの代わりに、次のものを試してみましょう。

```js
const taskList = props.tasks.map((task) => <Todo />);
```

アプリをもう一度見てみましょう。タスクは以前のように見えますが、タスク自体の名前がありません。私たちがマッピングした各タスクには、`id`、`name`、`checked` のプロパティがあり、`<Todo />` コンポーネントに渡したいことを覚えておいてください。これらの知識をまとめると、次のようなコードになります。

```js
const taskList = props.tasks.map((task) => (
  <Todo id={task.id} name={task.name} completed={task.completed} />
));
```

今では、アプリは以前のように見え、私たちのコードの繰り返しも少なくなりました。

固有なキー
-----

React は配列からタスクをレンダリングしているので、それらを適切にレンダリングするために、どれがどれなのかを追跡しなければなりません。どれがどれなのかを把握して、適切にレンダリングする必要があります。 React は自分自身で推測で物事を把握しようとしますが、それを助けるために `key` prop を`<Todo />` コンポーネントに渡すことで助けてあげることができます。`key` は React で管理されている特別な prop です。`key` という単語を他の目的で使用することはできません。

キーは固有であるべきなので、各タスクオブジェクトの `id` をキーとして再利用します。`taskList` は次のように更新します。

```js
const taskList = props.tasks.map((task) => (
  <Todo
    id={task.id}
    name={task.name}
    completed={task.completed}
    key={task.id}
  />
));
```

**反復処理でレンダリングするものには、常に固有なキーを渡す必要があります。** ブラウザー上では何も明らかな変化はありませんが、もし固有なキーを使用していない場合、 React はコンソールに警告し、アプリは奇妙な動作をするかもしれません。

アプリの残り部分をコンポーネント化
-----------------

最も重要なコンポーネントを整理したので、アプリの残りの部分をコンポーネント化することができます。アプリの残りの部分をコンポーネント化します。ここでコンポーネントは次のいずれかであることを覚えておいてください。コンポーネントが UI の一部か、再利用された UI の一部、またはその両方であることを覚えておいて、さらに 2 つのコンポーネントを作ります。

* `<Form/>`
* `<FilterButton/>`

両方とも必要ですので、ファイルをターミナルコマンドで一括して行いましょう。ターミナルで次のコマンドを実行してください。アプリのルートディレクトリーにいることに注意してください。

```bash
touch src/components/Form.js src/components/FilterButton.js
```

### `<Form />`

`components/Form.js` を開いて、以下のようにしてください。

* Todo.js で行ったように、ファイルの先頭で React をインポートします。
* 新しい `Form()` コンポーネントを`Todo()` と同じ基本構造で作成し、そのコンポーネントをエクスポートします。
* `<form>` タグとその間のものを `App.js` の中からコピーして、`Form()` の `return` 文の中に貼り付けます。
* `Form` をファイルの最後でエクスポートします。

`Form.js` ファイルは次のようになります。

```js
import React from "react";

function Form(props) {
  return (
    <form>
      <h2 className="label-wrapper">
        <label htmlFor="new-todo-input" className="label\_\_lg">
          What needs to be done?
        </label>
      </h2>
      <input
        type="text"
        id="new-todo-input"
        className="input input\_\_lg"
        name="text"
        autoComplete="off"
      />
      <button type="submit" className="btn btn\_\_primary btn\_\_lg">
        Add
      </button>
    </form>
  );
}

export default Form;
```

### <FilterButton />

`FilterButton.js` を `Form.js` のようにします。でもコンポーネントの `FilterButton()` を呼び出し、 `<div>` 要素内の最初のボタンの HTML をコピーして `App.js` の `filters` の `class` を `return` 文に入れます。

ファイルの内容は以下のようになります。

```js
import React from "react";

function FilterButton(props) {
  return (
    <button type="button" className="btn toggle-btn" aria-pressed="true">
      <span className="visually-hidden">Show </span>
      <span>all </span>
      <span className="visually-hidden"> tasks</span>
    </button>
  );
}

export default FilterButton;
```

**メモ:** ここでは、最初に `<Todo />` コンポーネントで行ったのと同じ間違いをしていることに気づくかもしれません。つまり、それぞれのボタンは同じものになるということです。これでいいのです。このコンポーネントの修正は、後ほどで行います。（フィルターボタンへ戻る (en-US)）

すべてのコンポーネントのインポート
-----------------

新しいコンポーネントを使ってみましょう。

さらにいくつかの `import` 文を `App.js` の上に追加して、インポートします。

次に、`App()` の `return` 文を更新して、私たちのコンポーネントをレンダリングするようにします。コンポーネントのレンダリングを行うと、`App.js` は次のようになります。

```js
import React from "react";
import Form from "./components/Form";
import FilterButton from "./components/FilterButton";
import Todo from "./components/Todo";

function App(props) {
  const taskList = props.tasks.map((task) => (
    <Todo
      id={task.id}
      name={task.name}
      completed={task.completed}
      key={task.id}
    />
  ));
  return (
    <div className="todoapp stack-large">
      <h1>TodoMatic</h1>
      <Form />
      <div className="filters btn-group stack-exception">
        <FilterButton />
        <FilterButton />
        <FilterButton />
      </div>
      <h2 id="list-heading">3 tasks remaining</h2>
      <ul
        role="list"
        className="todo-list stack-large stack-exception"
        aria-labelledby="list-heading">
        {taskList}
      </ul>
    </div>
  );
}

export default App;
```

これで、React アプリでインタラクティブな処理を行う準備が*ほぼ*整いました。

まとめ
---

この記事では、アプリをコンポーネントにうまく分割し、それらを効率的にレンダリングする方法について、詳しく説明しました。さて、次は React でイベントを処理する方法を見て、いくつかのインタラクティブ機能を追加していきます。

* 前のページ
* Overview: Client-side JavaScript frameworks
* 次のページ  (en-US)