【初心者向け🔰】はじめての Angular 17、環境構築の全手順（用語解説付き）

## 概要
Web アプリのフロントを簡単に構築できるフレームワーク **「Angular」** を初めて触れる人向けの備忘録。

Agular の **バージョン「17」** を導入する手順を記載する。

### 前提
- Node.js が導入済みであること
  - 本記事では、Node.js の説明・構築手順は説明しない
- 本記事では、macOS での作業を説明
  - Windows の方は、都度、読み替えてください🙏
- バージョン
  - Node: v20.10.0
    - npm: v10.2.3
  - Angular: v17.0.7
  - Angular CLI: v17.0.7

## Angular とは
**「Angular（アンギュラー）」** とは、Google 製のWebアプリケーションのフロントエンド開発を簡単にするフレームワークです。
オープンソースなフレームワークやライブラリとして、よく比較されるのが **「React」「Vue」** です。

一言で表すと、**「Web 画面を簡単に作ることに特化した技術」** です。
サーバ側（バックエンド）が必要な場合は、クラウドのサービスを利用するか、別途、開発して用意する必要があります。

### 特徴

- Googleが開発した技術で、多くの Google プロジェクトでも使用されている
  - 当然、Gooole 製サービスとの相性が良い（Firebase, Chrome など）
  - Angular と親和性の高い技術も用意されている（Angular CLI, Angular Material など）
- TypeScript（.ts）で書くが基本。JavaScript（.js）ももちろん可能
- 「フルスタックフレームワーク」であり、単独でフロントエンド開発に必要な機能が初めから一通り揃っている
  - "学習コストが高い" と言われていたが、他の技術を組み合わせる必要が無い点や、開発者ポータルの充実の点では、総合的な学習コストが低い
  - よく比較される React や Vue の場合、単独利用ではなく、Next や Nuxt など別の技術を組み合わせる場合が多い
- バージョンのアップデート頻度がとても早い
- バージョンアップ手順を支援する Web サイト **「Angular Update Guide」** が存在するため、バージョンアップで破壊的な大幅変更が発生しても対応が可能
  - v2 から最新版まで対応
  - https://update.angular.io
  - https://update.angular.io/?locale=ja-JP （日本語版）
- 日本ではあまり人気がない（執筆時現在）。日本語のドキュメントや解説動画も非常に少ない（ほとんどない）

## 環境構築手順
以下、Node.js さえ入っていれば、環境構築からアプリ起動まで、たった数分で完了します。

### Angular CLI の導入
**「[Angular CLI](https://github.com/angular/angular-cli)」** は、Angular の開発操作を支援する、公式の開発支援コマンドラインツールです。
これを導入すると `ng` コマンドが使用できる様になり、このコマンドで、アプリの新規作成、コンポーネント追加などの開発操作などが簡単にできる様になります。

これが無くてもルール通りにファイルを配置すれば動きますが、効率が非常に悪いので、導入は強く推奨します。

どの場所でも良いので、以下を実行して PC にグローバルインストールしましょう。
```bash
# インストールコマンド
npm install -g @angular/cli

# または省略形
npm i -g @angular/cli
```

インストールが完了したら、ちゃんと動くか確認してみます。

```bash
# バージョン確認コマンド
$ ng version

# 実行結果
     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/
    

Angular CLI: 17.0.7
Node: 20.10.0
Package Manager: npm 10.2.3
OS: darwin x64

Angular: 
... 

Package                      Version
------------------------------------------------------
@angular-devkit/architect    0.1700.7 (cli-only)
@angular-devkit/core         17.0.7 (cli-only)
@angular-devkit/schematics   17.0.7 (cli-only)
@schematics/angular          17.0.7 (cli-only)
```

### Angular アプリケーションを生成
コマンドで Angular アプリケーションを生成します。
生成コマンドを実行すると、インタラクティブ（対話的）に質問に答えて必要なファイルを自動生成する仕組みです。

下記は、適当に回答して生成した一例です。実際には、ご自身の目的に合わせて回答を変えてください。

```bash
# アプリ生成コマンド: "demo-app" というアプリを生成
$ ng new demo-app

# ---------- 以下、実行結果 ----------
# Q1. どのスタイルシート言語形式にする？ (カーソルで選んでエンターキーで決定)
? Which stylesheet format would you like to use? (Use arrow keys)
❯ CSS 
  SCSS   [ https://sass-lang.com/documentation/syntax#scss                ] 
  Sass   [ https://sass-lang.com/documentation/syntax#the-indented-syntax ] 
  Less   [ http://lesscss.org                                             ]

# Q2. SSR/サーバサイドレンダリング とか プリレンダリング とか使う？ (デフォルトは No)
? Do you want to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering)? (y/N) 

# 自動生成中…
CREATE demo-app/README.md (1061 bytes)
CREATE demo-app/.editorconfig (274 bytes)
    :
   (略)
    :
⠹ Installing packages (npm)...

# 以下の表示で生成完了
✔ Packages installed successfully.
    Successfully initialized git.
```

アプリの作成・構築は以上で完了です。簡単ですね 🙌✨

### 起動して動作確認
以下のコマンドで、Web アプリが起動します。

```bash
# 生成されたアプリのディレクトリに移動
$ cd demo-app 

# アプリ起動
$ ng serve   

# 実行結果
Initial Chunk Files | Names         |  Raw Size
polyfills.js        | polyfills     |  82.71 kB | 
main.js             | main          |  23.17 kB | 
styles.css          | styles        |  95 bytes | 

                    | Initial Total | 105.97 kB

# 以下が出れば、起動成功
Application bundle generation complete. [1.357 seconds]
Watch mode enabled. Watching for file changes...
  ➜  Local:   http://localhost:4200/
```

表示にも出ている通り、URL `http://localhost:4200` にアクセスすると画面が表示されます。
Web ブラウザを立ち上げ、アドレスバーに **「localhost:4200」** と打ってエンターキーを押してください。

![demo_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/61590b42-0d76-8508-343f-1aa46aa89ece.png)

停止する場合は、以下のコマンドでアプリが停止します（Web ブラウザを閉じても、アプリは勝手に停止しないので注意）。

| OS | 停止コマンド |
|---|---|
| macOS / Linux | control + C |
| Windows | Ctrl + C |

## ホットリロード機能
Angular には「ホットリロード」機能（言い方は諸説ある）がついています。
これはアプリ起動中にソースコードを変更して保存すると、リアルタイムに表示内容に反映してくれる便利な機能です。

ファイル構成は後述しますが、とりあえず、実際にやってみましょう。
まず、アプリを起動してから、以下のソースコードを変更してみてください。

```diff_typescript:src/app/app.component.ts
  import { Component } from '@angular/core';
  import { CommonModule } from '@angular/common';
  import { RouterOutlet } from '@angular/router';

  @Component({
    selector: 'app-root',
    standalone: true,
    imports: [CommonModule, RouterOutlet],
    templateUrl: './app.component.html',
    styleUrl: './app.component.css'
  })
  export class AppComponent {
-   title = 'demo-app';
+   title = 'こんにちは'; // この様に変更してみる
  }
```

上記の様に変更後、保存（option + S または Ctrl + S）をすると、下図の様に表示が変わります。

![demo_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/c37c5fb9-6d1b-101b-2be5-dff5ad38a9c1.png)

この様に、実際の変化を見ながら、効率的に開発作業ができます。

## package.json について
これは Angular ではなく Node.js の話になるので、基本や詳細は割愛しますが、
アプリケーション自動生成時は、以下のような中身になっています。
この中で主要なキーワードのみを取り上げて解説します。

```json
{
  "name": "demo-app",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^17.0.0",
    "@angular/common": "^17.0.0",
    "@angular/compiler": "^17.0.0",
    "@angular/core": "^17.0.0",
    "@angular/forms": "^17.0.0",
    "@angular/platform-browser": "^17.0.0",
    "@angular/platform-browser-dynamic": "^17.0.0",
    "@angular/router": "^17.0.0",
    "rxjs": "~7.8.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.14.2"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^17.0.7",
    "@angular/cli": "^17.0.7",
    "@angular/compiler-cli": "^17.0.0",
    "@types/jasmine": "~5.1.0",
    "jasmine-core": "~5.1.0",
    "karma": "~6.4.0",
    "karma-chrome-launcher": "~3.2.0",
    "karma-coverage": "~2.2.0",
    "karma-jasmine": "~5.1.0",
    "karma-jasmine-html-reporter": "~2.1.0",
    "typescript": "~5.2.2"
  }
}
```

### 主要なキーワード

| キーワード | 用途 |
|---|---|
| name | アプリケーションの名前<br>node モジュールとして外部公開する場合などに表示される名前 |
| version | このアプリのバージョン<br>手動またはツールを使って変更・管理する |
| scripts | `npm run` コマンドで使用できる「引数」と「処理内容」を定義する場所<br>※ 後で説明します |
| dependencies | このアプリケーションで使用している他の node モジュール<br>（本番でも使うもの） |
| devDependencies | このアプリケーションで使用している他の node モジュール<br>（開発時のみ使うもの）  |

npm install コマンドで外部の node モジュールを新たにインストールする時に、

- `npm install {モジュール名}` を実行すると、`dependencies` に追記されます。
- `npm install -D {モジュール名}` を実行すると、`devDependencies` に追記されます。

`dependencies` と `devDependencies` は、エンジニア向けに記載として分かれているだけで、どっちに格納されていても動きとしてはほぼ変わりません。よくわからない場合は、全て `dependencies` でも問題はないです。

ここには、トップレベルのモジュール名が記載されますが、更にそのモジュール内部で使用されている別のモジュールが存在した場合、**package-lock.json** に詳細な情報が追記される様になっています。

### npm コマンド
スクリプト定義を見ると以下の様になっているはずです。

```diff_json:package.json
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test"
  },
```

scripts の引数 **「start」** に注目してください。
前述では、アプリのローカル起動に `ng serve` を実行しましたが、ここに同じコマンドが書いてありますね。

つまり、現状は `npm run start` と実行しても、同じコマンドが実行され、アプリの起動ができることを意味します。

```bash
# 以下の２つは全く同じ処理を実行する
ng serve
npm run start
```

この例では、普通に実行した方がコマンドが短くて楽に見えますが、実際はもっと長くて複雑なコマンドに修正する場合もあるし、こういったコマンドや仕様に詳しくない人もいるので、ここに記載しておいた方が総合的に扱いやすいです。

## ファイル構成
ファイル構成が気になるマニアックな人のために、初期構成の中身を解説します 🙌

アプリ自動生成すると、ファイル構成は以下のようになっているはずです（今回はスタイルシートに "CSS" を採用した場合）。

```bash
  demo-app/  # 自動生成したディレクトリ
    ├ .vscode/
    ├ node_modules/
    ├ src/
    |  ├ app/
    |  |  ├ app.component.html
    |  |  ├ app.component.css
    |  |  ├ app.component.spec.ts
    |  |  ├ app.component.ts
    |  |  ├ app.config.ts
    |  |  └ app.routes.ts
    |  ├ assets/
    |  |  └ .gitkeep
    |  ├ favicon.ico
    |  ├ index.html
    |  ├ main.ts
    |  └ styles.css
    ├ .editorconfig
    ├ .gitignore
    ├ angular.json
    ├ package-lock.json
    ├ package.json
    ├ README.md
    ├ tsconfig.app.json
    ├ tsconfig.json
    └ tsconfig.spec.json
```

これらが何を意味するのかは、以下の通りです。
（この構成内容を覚える必要はありませんので、目を通すくらいで OK です）

|ディレクトリまたはファイル名|内容|
|---|---|
| demo-app | `ng new` コマンドで自分が指定したアプリ名のディレクトリ<br>このディレクトリ名は後から自由に編集しても動作には問題ない |
| .vscode | コードエディタ VS Code の設定ファイルを入れるディレクトリ<br>アプリケーションの仕様や動作には関係ない |
| node_modules | アプリケーションの中で使用する、外部の node モジュールがダウンロード・インストールされる場所<br>アプリ生成初回のみ自動で出来あがる<br>このフォルダは削除しても問題ない<br>（`npm install` コマンドを実行すれば、また自動で全て生成される） |
| src | メインとなるソースコードや画像などのファイルを管理するディレクトリ<br>※ ここがメインの開発作業場所となる |
| src/**app** | src の中にある、アプリケーションのプログラムを作っていく場所 |
| src/app/**app.component.html** | 自動生成されたアプリケーションの画面の HTML ファイル<br>中身はサンプルコードが既に書かれている |
| src/app/**app.component.css** | 自動生成されたアプリケーションの画面の CSS ファイル<br>中身は空 |
| src/app/**app.component.spec.ts** | アプリケーションのコンポーネントをテストするためのファイル<br>テストのためのプログラムなので削除してもアプリは動作する<br>中身はサンプルコードが既に書かれている |
| src/app/**app.component.ts** | 自動生成されたアプリケーションのコンポーネントファイル<br>このコンポーネントファイルに .html と .scss(.css) ファイルがぶら下がる関係となる<br>中身はサンプルコードが既に書かれている |
| src/app/**app.config.ts** | アプリケーションの動作仕様を設定するファイル<br>全体的なアプリ動作仕様を追加する場合に追記するファイルの１つ |
| src/app/**app.routes.ts** | ルーティング、つまり、画面遷移を管理するためのファイル<br>URL と対応するコンポーネントの関係をここに書いたりする |
| src/**assets** | 画像やその他の静的なファイルが格納されるディレクトリ |
| src/assets/**.gitkeep** | 空のディレクトリを Git に追跡させるためのダミーファイル<br>Git は空のディレクトリを差分管理してくれないので、ダミーの中身として用意されている<br>何か画像などのファイルが格納されたら削除してよいファイル |
| src/**favicon.ico** | ファビコン画像ファイル<br>Web ブラウザのタブの左端に表示される画像アイコン |
| src/**index.html** | アプリケーションとして一番最初に土台となる画面の HTML ファイル<br>この中で main.ts で生成された画面が表示される |
| src/**main.ts** | アプリケーションとして一番最初に起動する画面の処理ファイル<br>この中で app ディレクトリのコンポーネントが呼ばれて表示される |
| src/**styles.css** | index.html のスタイルシートファイル (つまり装飾処理を書くファイル) |
| .editorconfig | VS Code に限らない、エディタの設定ファイル<br>アプリケーションの仕様や動作には関係ない |
| .gitignore | Gitの無視設定ファイル。ここ書かれたファイルやディレクトリは<br>差分を無視される ＝ Git 管理されない |
| angular.json | Angular のビルドや設定に関するメインの構成ファイル |
| package-lock.json | プロジェクトの依存関係の詳細なバージョン情報が記述されたファイル<br>npm install した時に何がダウンロードされるかの詳細が書いてある |
| package.json | プロジェクトの依存関係とスクリプトの設定が記述されたファイル<br>npm run コマンドの設定や使用 node モジュールの基本情報はここに書かれる<br>npm install した時に何がダウンロードされるかが書いてある |
| README.md | プロジェクトに関する説明やドキュメントが書かれたファイル<br>アプリケーションの動作には無くても関係ない<br>追記しなくても問題ないが、GitHub などのトップページに中身が表示される |
| tsconfig.app.json | アプリケーション用の TypeScript 言語設定ファイル<br>TypeScript → JavaScript 変換時のルールなど |
| tsconfig.json | プロジェクト全体の TypeScript 設定ファイル |
| tsconfig.spec.json | テスト時に使用される TypeScript 設定ファイル |

この中で、具体的に触っていくのは、主に **app** の中身だけです。
その中に、表示する画面の部品や通信処理など行うファイルを追加していきます。

## Angular のコンポーネントが表示される仕組み
こちらも、気になるマニアックな人のために、画面表示の流れを簡単に解説します 🙌

### 超ざっくりとした解説
Angular のざっくりとした動作イメージとしては以下の通りです。

```
index.html の画面を表示
  -> main.ts がコンポーネントを呼び出す (この時、設定 app.config も行われる)
  -> main.ts で呼ばれたコンポーネント (app.component.ts) が表示部品を提供する
```

そして、表示された画面の URL を変更すると app.routes.ts に書かれたルールに従って、表示するコンポーネントを切り替えるという仕組みになっています。

「技術的になぜそうなるのか？」は一旦置いておくと、仕組みだけならそこまで複雑ではありません。

### もう少し詳細な解説
もう少し詳細に、各ファイルの中身がどのように使われるのかを簡単に説明します。

まず、最初に画面に表示される **index.html** を見てください。

```html:demo-app/src/index.html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>DemoApp</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-root></app-root>
</body>
</html>
```

`<app-root></app-root>` というタグが呼ばれていますが、HTML には `<app-root>` なんてタグは **存在しません。**

では、何が呼ばれているのかというと、技術的な仕組みは割愛しますが、`<app-root>` 名前のタグを定義している **「app.component.ts」** が呼ばれています。

```ts:demo-app/src/app/app.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, RouterOutlet],
  templateUrl: './app.component.html',
  styleUrl: './app.component.scss'
})
export class AppComponent {
  // ここには自由に処理などが書かれる。空でも良い。
}
```

`.component.ts` ファイルは、コンポーネントを定義する TypeScript で書かれたファイルです。

コンポーネント、つまり、『**TypeScript（実質は JavaScript）＋ HTML + CSS** の３つがセットになった画面の表示部品』
…に対して、新しい HTML のカスタムタグとして名前を設定し、画面の１部品として利用できるように定義されています。

- `.component.html`： コンポーネントの表示内容が HTML で書かれる
- `.component.css`： コンポーネントの装飾が CSS で書かれる（scss, sass, less も同様）
- `.component.ts`： コンポーネントの処理が TypeScript で書かれる。このファイルが親となる

カスタムタグ名を決めているのは **「selector（セレクタ）」** という場所で、
「app.component.ts」 には `selector: 'app-root'` と書かれていますね。
つまりこれは、 `<app-root>` という新しい HTML のタグ（部品）を HTML に書けば、このコンポーネントが部品として HTML 上に表示されることを意味します。

ここでセレクタに設定する名前は、他のコンポーネントと重複しないユニークな名前でなければいけません。
もちろん、既存の HTML に存在するタグの名前とも重複してはいけません。そのため、基本的には **「２単語以上の英単語を組み合わせた名前にしましょう（例：my-tag ）」** というマナーがあります。

しかし、コンポーネントを定義しただけでは、存在しないタグを直ちに HTML で使える訳ではありません。
ここでまた技術的な詳細は割愛しますが、`main.ts` が Angular 独自の仕組みによって、新たに定義したカスタムタグを index.html に提供しています。

```ts:demo-app/src/main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { AppComponent } from './app/app.component';

bootstrapApplication(AppComponent, appConfig)
  .catch((err) => console.error(err));
```

main.ts が動くことで、Angular として定義したオリジナルのタグが、index.html で表示できる様になっているということです。

## まとめ

- Angular は Google 製の Webアプリのフロントエンドのフレームワーク（Web 画面開発が簡単になる技術）
- 環境構築は数分で完了する
- フルスタックなフレームワークであることが特徴で、これ１つあればほぼどんな画面も作れる
- Angular CLI を導入して、開発・保守作業を簡単にする
- 基本的に触るのは「app」ディレクトリの中身だけ
- 動かしながら作業結果を画面で確認できる「ホットリロード」機能がある
- フロントエンド用の技術なので、バックエンドが必要なら、別途用意する必要がある