Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
6
Help us understand the problem. What is going on with this article?
@TsuyoshiUshio@github

Angular 4 で Connection String や Secret を Environment Variables から取得する

More than 3 years have passed since last update.

The twelve-factor app にある通り、環境依存の情報は、環境変数から設定するようにしたい。しかし、SPA の Angular とかだったらどうするんだろう?きっとこれは基礎的なことなのだけど、意外と自分には難しかったので、今まで学んだことを自分のために、ブログにしておきたい。

Environment Variables を Angular (4) から使う

ベストプラクティス的なものがないのかなぁ。と色々調べて見たけど、Facebook でなきを入れていたらヒントをもらえた。

Screen Shot 2017-10-18 at 7.20.37 PM.png

環境変数を取り込む仕組みのあれこれ。

ちなみに、Angular では、環境変数は取り込めない。よくよく考えると、SPA は、ブラウザにダウンロードされて使うのだから、そらそうだ。

上記の記事を読んでいると、どうやら、Angular には、environment という仕組みがあるらしい。そのenvironmentを環境によって変えられる様子。

src/environments/
├── environment.prod.ts
└── environment.ts

ここを、プロジェクトをビルドする時に切り替える。例えばこんな感じ。

_environment.prod.ts

export const environment = {
  production: true,
  hostUrl: "http://some.prod"
};

_environment.ts

export const environment = {
  production: false,
  hostUrl: "http://some.dev"
}

app.component.html に 下記のコードを入れておく。

<h2> ServerName: {{hostUrl}}</h2>
$ ng serve 

Screen Shot 2017-10-18 at 7.41.04 PM.png

だと、デフォルトが起動する。

$ ng serve --environment prod

Screen Shot 2017-10-18 at 7.41.58 PM.png

これでプロダクションが起動した。

環境変数を埋め込む

少なくとも Angular CLIを使っている時はこの方式で行けそう。いきなり本物のプロジェクトに盛り込むより、プロジェクトを生成してみよう。

$ ng new host-inject

この状態から、環境変数を取り込んで見たい。環境変数は Angular では直接取り込めない。色々読んでいると、ビルド時に、プリコンパイルして盛り込むというのが良さげ。

NOTE: 最初、process.env を直接実行しようとしたけど、これは見つかららないと言われる。ちなみにこれは、tsconfig.app.json の下記の部分を追加すると、解消された。

"CompilerOptions": {
  typs["node"],
    :
}

scripts/prebuild.ts というファイルを作ってみる。 テンプレート environment.ts.template を元に、環境変数を取り込んで作成をするシンプルなもの。

import * as fs from 'fs';
import * as path from 'path';
import * as ejs from 'ejs';

const environmentFilesDirectory = path.join(__dirname, '../src/environments');
const targetEnvironmentTemplateFileName = 'environment.ts.template';
const targetEnvironemntFileName = 'environment.ts';

const defaultEnvValues = {
    SOME_HOST: "http://default.com"
}

const environmentTemplate = fs.readFileSync(
    path.join(environmentFilesDirectory, targetEnvironmentTemplateFileName),
    {encoding: 'utf-8'}
);
let obj:any = (<any>Object).assign({}, defaultEnvValues, process.env);
const output = ejs.render(environmentTemplate, obj);
fs.writeFileSync(path.join(environmentFilesDirectory, targetEnvironemntFileName), output);
process.exit(0);

ちなみに、(<any>Object).assign の部分は当初、Object に assign が見つからないと怒られた。<any> をつけて解決。

enviornment.ts.template

export const environment = {
  production: false,
  hostUrl: "<%= SOME_HOST %>"
};

これを実行するために、package.json に、

"prebuild": "tsc scripts/prebuild.ts && node scripts/prebuild.js",

を追加した。

プリビルドする。

$ npm run prebuild

しっかり、ファイルがジェネレートされた。

$ env
SOME_HOST=http://some.com

environment.ts

export const environment = {
  production: false,
  hostUrl: "http://some.com"
};

バッチリできている。先ほど紹介してもらった記事を見ても、ジェネレートする方法が一番スッキリきた。

本当にこの方式で問題ないのか?

問題は、この方式だと、結局のところ、ブラウザから URL が見れちゃったりするんじゃないの?と思ったが、意外に見えないようだ。もちろん、enviornments の下をうっかり公開する設定にしてないことが大切だとは思うが。よく、SPA を Blob Storage に置くとかの例があるが、ああいうのはどうしているんだろう。Azure Functions Proxy などで制限する感じだろうか。次はその辺をやってみたい。

ちなみに、全てのソースコードはこちらに置いています。

Resource

6
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
TsuyoshiUshio@github
プログラマ。自分の学習用のブログです。内容は会社とは一切関係ありません。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
6
Help us understand the problem. What is going on with this article?