Docker環境でAngular、AngularJSのライブリロード化

# Angular はバージョンで呼び方が違ってる件

下記のようになっております
AngularJS（1.x 系）
Angular（2.0 系 ~ latest）

# やりたいこと

docker と Angular を使用して、`ローカルのファイルが変更された時 コンテナ上でもライブリロードが効いて開発がしやすくする`

なんと今回は AngularJS 付き！(誰得)

# これなんて呼ぶか教えてください orz

下記の現象って正式な名称ついているかわからないけど
`ローカルのファイルが変更された時、ライブリロードが効いて開発がしやすくする`

`「コンテナのライブリロード化」`って以下からは呼称します

# TL;DR

docker で Angular(8.3.0) を動かす
付録：AngularJS(1.7.9) 付き

# 前提

- Angular → angular cli で生成した新規プロジェクト
- AngularJS → webpack で構築された既存プロジェクト

# 環境

```fish

Angular: 8.3.0
Angular CLI: 8.3.20
Docker desktop: 2.1.0.5

AngularJS: 1.7.9
Webpack: 4.41.2
```

# ポイント

## host に 0.0.0.0 を渡す

どちらも webpack で動いているのがみそですかね

## docker-compose.ymlでvolumesを設定
`.dockerignore`もvolumesでもnode_modulesも除外しましょう

# Angular の コンテナのライブリロード化 の流れ

1. angular-cli のインストール
2. プロジェクト新規作成
3. dockerfile, .dockerignore を追加
4. docker-compose.yml を追加
5. お疲れさまでした

## 1. angular-cli をインストール

公式が提供している angular-cli でプロジェクトを新規作成しましょう:santa:
brew でインストールするのがおすすめです

angular-cli が入っている人は飛ばしてください:santa:

```fish
brew install angular-cli
```

angular cli が入ったか確認です

```fish
ng v

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/


Angular CLI: 8.3.20
〜〜以下省略〜〜

```

## 2. 新規 angular のプロジェクトを作成

version 8.1 だったか、`--enableIvy=true`を渡せば高速でレンダリングされる Ivy 使用できるので試しに引数でわたしてみまそう

```fish
ng new angular-sample --enableIvy=true
```

## 3. dockerfile, .dockerignore を追加

`dockerfile` と、`.dockerignore` を追加しましょう:santa:
ビルドの高速化のために`.dockerignore`も忘れずに追加しましょう:santa:

dockerfile

```dockerfile
# 現バージョンでは、10.9.0以降を推奨しているので、nodeのstableの12系の最新を使用
# https://angular.jp/guide/setup-local#nodejs
FROM node:12.13.1

# ローカルフォルダのファイルを置いていくフォルダ作成
RUN mkdir /usr/src/app

# package.json と package.lockをコピー
COPY ./package*.json /usr/src/app/

# yarnの人はこちらもコピー
COPY ./yarn.lock /usr/src/app/

# yarn install する箇所を
WORKDIR /usr/src/app/

# yarn使用している人は yarn.lock を元にインストールする yarn install --frozen-lockfile でもいいと思います
RUN npm ci

# ローカルのファイルすべてコピー
COPY . /usr/src/app/

# docker上でコピーした angular-cli で ビルド実行
RUN npx ng build --aot
```

.dockerignore

```.dockerignore
node_modules
```

dockerfile はあくまでビルドまで！:santa:

無事ビルドできるか試してみてくだせぇ:santa:

```fish
docker build --rm .
```

最後に`Successfully built 4f89bd9818ae(hash値っぽいやつ)`と出ていれば OK だと思います:santa:

docker-compose.yml でサーバーを立ち上げます:santa:

## 4. docker-compose.yml を追加

### 大事なポイント

- volumes の`- $PWD/:/usr/src/app`でローカルのファイルを上書きしている
- だけど、node_modules はビルド遅くなるので除外している
- command で　`--host=0.0.0.0`を渡してる(恐らく webpack に渡している)

```docker-compose.yml
version: '3.7'

services:
  anguar-app:
    image: anguar-app
    build:
      context: $PWD/
    ports:
      - '4201:4200'
    volumes:
      - $PWD/:/usr/src/app
      - /usr/src/app/node_modules # node_modulesは除外
    command: npx ng serve --aot --host=0.0.0.0
```

## 5. お疲れさまでした

設定はお終いです、お疲れさまでした:santa:

ローカルの変更が反映されるか確かめてみましょう:santa:

```bash

docker-compose up -d;\
sleep 3;\
open http://localhost:4201;
```

docker-compose をバックグラウンドで立ち上げ
↓
3 秒待つ
↓
ブラウザで localhost を立ち上げる

変更がない状態で立ち上げると、デフォルトの Angular の画面のままです

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183059/3ba1738d-8c06-8f27-f704-77d3f8208e1f.png)



なにかローカルの変更をしてみましょう:santa:

今回は echo コマンドで、ローカルのファイルを上書きしてみましょう:santa:

```bash
echo "<h1>反映やっほー</h1>" > ./src/app/app.component.html
```

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183059/c7660e98-a702-579d-50ee-01c6097d8b1b.png)

ファイル更新しただけで、画面が反映されたので完了です:santa:

# 付録

# AngularJS(webpack 前提) の コンテナのライブリロード化 の流れ

1. うちは webpack-dev-server がこれで動いています
2. dockerfile, dockerignore を追加
3. docker-compose.yml を追加
4. お疲れさまでした

# 0. うちは webpack-dev-server がこれで動いています

devServer のとこだけ参照していただければいいかと思います:santa:

## コンテナのライブリロード化をするには、host: '0.0.0.0'を渡すとうまくいきます

```webpack.config.js
const path = require('path');
const webpack = require('webpack');

const NODE_ENV = process.env.NODE_ENV;
console.log(`${NODE_ENV} modeで実行`);

module.exports = {
  mode: NODE_ENV,
  entry: path.join(__dirname, 'src/app/entry.ts'),
  output: {
    filename: 'bundle[hash].js',
    path: path.resolve(__dirname, 'dist'),
    chunkFilename: '[name][hash].js',
    publicPath: '',
  },
  module: (省略),
  resolve: (省略),
  devtool: (省略),
  optimization: (省略),
  devServer: {
    historyApiFallback: true,
    contentBase: path.join(__dirname, 'dist'),
    publicPath: 'http://localhost:8080/',
    host: '0.0.0.0',
    port: 8080,
    stats: 'minimal',
    hot: true,
    inline: true,
    proxy: (省略)
  },
  plugins:(省略),
}

```

# 1. dockerfile, dockerignore を追加

既存のプロジェクトで webpack-dev-server で動いているが前提なのですが、必然というべきか奇跡というべきか
`dockerfile`、`.dockerignore`は一緒でただ、ビルドコマンドが違うだけです
node のバージョンが 12.13.0 でも、typescript が 3.7.2 でも問題なく動きます:santa:

```dockerfile

# dockerfile
〜Angularと一緒のため省略〜

# docker上でコピーした angular-cli で ビルド実行
RUN NODE_ENV=production npm run webpack
```

# 2. docker-compose.yml を追加

```docker-compose.yml

services:
  spa-dev:
    build:
      context: $PWD/
    image: spa-dev
    ports:
      - '8080:8080'
    volumes:
      - $PWD/:/usr/src/app
      - /usr/src/app/node_modules # node_modulesは除外
    command: NODE_ENV=development npm run webpack-dev-server
```

# 3. お疲れさまでした

検証は各自の既存プロジェクトで試してみてください:santa:

ちなみに、上記の docker の設定で

AngularJS(1.7.9)
typescript(3.7.2)
webpack(4.41.2)
webpack-dev-server(3.9.0)で問題なく動いております:santa:

# あとがき

既存の AngularJS を Angular にかえる話は出ましたが、コードが多く、リプレイスしていく工数と事業インパクトがあるのかで Go の判断が降りず:santa:

最新の Angular のプロジェクトではないのですが
それでも、最新の フロントエンド は触っていたいので、AngularJS で新規でつくる機能は
[component](https://docs.angularjs.org/guide/component)の書き方で記述しプロジェクトを維持してます:santa:

docker 化を行ったあとは、AWS 上で ECR・ECS 化も済ませ、CircleCI の Orbs を使用し CI も回しています:santa:

なので、フレームワークのバージョン以外は技術トレンドにやっとのっけられたかなと思います:santa:

Angular Element で機能単位かドメインごとで AngularJS→Angular への置き換えも考えましたが
やはり既存のコードが多く、事業インパクトと見合うかに辿り着き、でもAngular は個人的に触っているからいいですかね:santa:

同じような境遇にあっている人は少ないとは思いますが、自分はdocker化すると、ローカル環境でのライブリロードが効かなくなってしまうと勘違いし
開発の便利さが失われてしまうのであれば、docker化はあとだ！と思ってましたが
上記のhostを設定するだけで、簡単にライブリロードはできるようになりました！

webpackまわりなど、ライブリロードと関係ない箇所は省略した部分など質問がありましたら！:santa: