AngularJSとGruntで稼働環境によって接続先APIを切り替える

今年の夏は、家族旅行で行った海ではしゃぎ過ぎ、温泉宿に付いた瞬間に疲れ果ててしまい肝心の温泉にあまり浸かれず、翌日全身筋肉痛となって帰宅したのがハイライトだった…..代表の国本です。

Webサービスやスマホ・アプリ開発では実際にサービスが稼働する本番環境の他に、同等のステージングや開発環境をセットで構築することが多々あるかと思います。

現在弊社のプロジェクトではクライアントサイドのフレームワークとしてAngularJSを積極的に採用しており、今回はEnvironment Specific Configuration in AngularJS Using Grunt
を参考に、Gruntを使用してAngularJSでステージングや本番環境など、稼働環境に応じて接続するAPIを切り替える方法について書いてみようと思います。

事前準備

今回は、Yeomanを使い、本ブログエントリーのために専用のenviromentsAppというアプリを作成します。

1
% yo angular enviromentsApp --coffee

アプリのサービスで利用するAPIの接続先が開発環境、ステージング、本番それぞれで異なるという想定で以下手順を進めて行きたいと思います。

generator-env-configの導入

それぞれの環境で区分したいAPIのURLを設定ファイル化するための、Yeomanのジェネレーターであるgenerator-env-configをnpm経由でインストールします。

1
% npm install generator-env-config

インストールが完了後、下記コマンドを実行し、まずは開発環境用の設定ファイルを生成します。

1
% yo env-config

実行後、config/environments/development.jsonが生成されます。

アプリ直下に生成されたconfig/enviroments配下のJSONファイルで、実行環境毎の設定値を管理します。(Railsにおけるconfig/enviromentsのイメージですね)

同じように、ステージング用、本番用のJSONファイルも生成しておきましょう。

1
2
3
4
5
6
7
8
9
10
% yo env-config staging
% yo env-config production

% ll config/environments/
total 24
drwxr-xr-x 5 kuninori wheel 170 8 26 21:09 .
drwxr-xr-x 4 kuninori wheel 136 8 26 20:50 ..
-rw-r--r-- 1 kuninori wheel 40 8 26 20:50 development.json
-rw-r--r-- 1 kuninori wheel 19 8 26 21:09 production.json
-rw-r--r-- 1 kuninori wheel 19 8 26 21:09 staging.json

今回はAPIの接続URLを実行環境毎に区分する。という想定なのでconfig/environments/配下のそれぞれの環境設定JSONファイルに下記設定を行います。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// development.json
{
"apiUrl": "http://localhost:9000"
}

// staging.json
{
"apiUrl": "http://staging.local"
}

// production.json
{
"apiUrl": "http://production.local"
}

AngularJSモジュールの生成

次に、env-configを使用してAngularJS上で実行環境毎の設定値を管理するservices.configというモジュールを作成します。
先程JSONファイルに設定されたそれぞれの環境用の設定値は、このservices.configモジュールをロードすることで利用できるようになります。

まず、下記コマンドを実行します。

1
% yo env-config:angular config

コマンド実行後、config/config.jsというファイルが生成されており、その中でservices.configモジュールが定義されています。

services.configモジュールで、JSON設定ファイル内に定義されているAPIのURL(apiUrl)を扱えるようにします。

1
2
3
4
5
6
7
'use strict';

angular.module('services.config', [])
.constant('configuration', {
// apiUrl変数を定義する
apiUrl: '@@apiUrl'
});

grunt-replaceの導入とタスクの定義

次にGruntを使用しそれぞれの環境用の設定値を動的に生成できるようにgrunt-replaceをnpmで導入し、ビルド用タスクを定義します。

まずはgrunt-replaceをインストール

1
% npm install grunt-replace --save-dev

インストール後、grunt-replaceをロードするようにGruntfile.jsの編集を行います。

1
2
3
module.exports = function (grunt) {
// module.exports内に下記設定を追記する
grunt.loadNpmTasks('grunt-replace');

併せてgrunt-replace用のタスクをgrunt.initConfig配下に定義します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
grunt.initConfig({
replace: {
development: {
options: {
patterns: [{
json: grunt.file.readJSON('./config/environments/development.json')
}]
},
files: [{
expand: true,
flatten: true,
src: ['./config/config.js'],
dest: '<%= yeoman.app %>/scripts/services/'
}]
},
staging: {
options: {
patterns: [{
json: grunt.file.readJSON('./config/environments/staging.json')
}]
},
files: [{
expand: true,
flatten: true,
src: ['./config/config.js'],
dest: '<%= yeoman.app %>/scripts/services/'
}]
},
production: {
options: {
patterns: [{
json: grunt.file.readJSON('./config/environments/production.json')
}]
},
files: [{
expand: true,
flatten: true,
src: ['./config/config.js'],
dest: '<%= yeoman.app %>/scripts/services/'
}]
}
}

タスクが定義できたら、早速開発環境用のタスクを走らせてみましょう

1
2
3
4
5
% grunt replace:development
Running "replace:development" (replace) task
Replace ./config/config.js → app/scripts/services/config.js

Done, without errors.

タスクが正常終了後、app/scripts/services/config.jsファイルが生成されます。
config/environments/development.jsonで定義した、開発環境向けのAPIのURLがモジュールとして定義されているのが確認できます。

1
2
3
4
5
6
'use strict';

angular.module('services.config', [])
.constant('configuration', {
apiUrl: 'http://localhost:9000'
});

AngularJSアプリでservices.configモジュールをロード

これまでの手順で、それぞれの稼働環境用の変数が定義されたservices.configモジュールが生成できる環境が整ったため、生成されたservices.configモジュールをAngularJSアプリケーションからロードし利用できるようにしましょう。

まずはapp/index.htmlservices.configモジュール用のJavaScriptを読み込みます。

1
2
# config.jsをindex.htmlに追加
<script src="scripts/services/config.js"></script>

次に、app/scripts/app.coffeeからモジュールをロード。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
'use strict'

###*
# @ngdoc overview
# @name enviromentsAppApp
# @description
# # enviromentsAppApp
#
# Main module of the application.
###
angular
.module('enviromentsAppApp', [
'ngAnimate',
'ngCookies',
'ngResource',
'ngRoute',
'ngSanitize',
'ngTouch',
// services.configをロードするように追加
'services.config'
])

これでモジュールが呼び出せるので、早速コントローラーから定義されているAPI用のURLを確認してみましょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
'use strict'

###*
# @ngdoc function
# @name enviromentsAppApp.controller:MainCtrl
# @description
# # MainCtrl
# Controller of the enviromentsAppApp
###
angular.module('enviromentsAppApp')
// configurationをセット
.controller 'MainCtrl', ($scope, configuration) ->
// configuration.apiUrlで定義しているAPIのURLをアラート表示してみる
alert configuration.apiUrl

起動してみると……。

alert

定義しているAPIのURLが表示されましたね。

後は、実際にS3やWebサーバへAngularJSアプリケーションをデプロイする際に実行するGruntのビルド処理の中で
grunt replace:staginggrunt replace:productionを実行するように仕込めば、デプロイ環境に併せて
フレキシブルに環境変数が準備できます。

まとめ

いかがでしたでしょうか? 今回活用したgenerator-env-config以外にも環境ごとの設定値を良い感じに定義する手法は数多くあるかと思いますので
ご教示いただければ幸いです。

ではでは、良きAngularJSライフを‎╭( ・ㅂ・)و ̑̑

今回ご紹介したような、AngularJSなどのフレームワークを活用したフロントエンドアプリケーション開発を御希望の企業様は、是非お気軽にMMMにご相談下さいませ!

このエントリーをはてなブックマークに追加