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 で構築された既存プロジェクト

環境


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 でプロジェクトを新規作成しましょう
brew でインストールするのがおすすめです

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

brew install angular-cli

angular cli が入ったか確認です

ng v

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


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

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

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

ng new angular-sample --enableIvy=true

3. dockerfile, .dockerignore を追加

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

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

node_modules

dockerfile はあくまでビルドまで!

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

docker build --rm .

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

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

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. お疲れさまでした

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

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


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

docker-compose をバックグラウンドで立ち上げ

3 秒待つ

ブラウザで localhost を立ち上げる

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

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

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

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

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

付録

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

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

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

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

コンテナのライブリロード化をするには、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 でも問題なく動きます


# 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. お疲れさまでした

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

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

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

あとがき

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

最新の Angular のプロジェクトではないのですが
それでも、最新の フロントエンド は触っていたいので、AngularJS で新規でつくる機能は
componentの書き方で記述しプロジェクトを維持してます

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

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

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

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

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