フロントエンド・エンジニアのための環境変数入門 第1回 環境変数とは
OSなどの実行環境で共通の変数として使える環境変数の使い方を解説します。環境に設定された変数をプログラムから参照することで、環境ごとにその動作を切り替えられます。知っていると、とても便利です。
環境変数とは
環境変数とは、コンピュータの上で働くプロセスの実行環境に存在している変数のことです。 私たちが使っているOS上に定義されたグローバル変数のようなものと言ってもよいかもしれません。OS上で動くアプリケーションから、ちょっとしたスクリプトまで、実行中のプロセスは環境変数を参照して、その動作を切り替えられます。
Node.jsのグローバル変数は、そのNode.jsプログラムが終了すれば消えてしまいますが、環境変数の生存期間はより長く、プログラムが実行される環境そのものが動いている間です。したがって、ある環境で働くNode.jsプログラムは、それらが別々のプロセスであっても、その環境における環境変数を共有します。
たとえばUnixあるいはUnixライク、UnixベースなOSではHOME
という環境変数からユーザーのホームディレクリのパスを読み取れます。OSに定義されている環境変数はターミナル上で、変数や文字列を表示できるコマンドであるecho
を使って私たちの手元でも確認できます。
以下は筆者のmacOSのターミナル上で環境変数HOME
の内容を表示した例です。このとき変数の値を参照するには変数名の頭に$
をつけるか、変数名を${変数名}
で囲みます。
HOMEの値を表示
echo $HOME
> /Users/ykhs
Node.jsと環境変数
Node.js上で環境変数を読み取る場合はJavaScriptのコードからprocess.env
オブジェクトにアクセスします。以下はNode.js上で環境変数HOME
を表示する例です。これを筆者の環境で実行した場合も先の例と同様に /Users/ykhs
という結果が表示されます。
Node.js上でHOMEの値を表示
console.log(process.env.HOME);
// => /Users/ykhs
また、ブラウザで実行中のJavsScriptから環境変数へアクセスする手段は存在しません。process
という名前空間も定義されておらず、次のキャプチャのようにようにそれが未定義であるというエラーが返されます。
ブラウザから環境変数にアクセスする手段はない。
実際には、クライアントサイド用に書かれたJavaScriptコードにprocess.env
という記述が登場していることはあります。これはwebpackなどによるビルドを前提としており、webpackの機能を使って、ビルドが行われる環境での設定値をクライアント用コードに注入することを期待したものです。
たとえばprocess.env.NODE_ENV
というコードはwebpackによるビルドを経て"production"
という文字列に置換されたりします。最終的にクライアントサイドで実行されるコードでprocess.env
へのアクセスが行われるわけではありません。
webpackと環境変数については、このシリーズ中で今後、紹介していきたいと思います。
Node.jsに環境変数を渡す
シェル環境におけるコマンド全般の話でもありますが、UnixライクなOS上で環境変数を設定しながらNode.jsを実行する一番簡潔な方法を紹介します。
次のようなJavaScriptファイルがあったとします。これは環境変数MESSAGE
の内容を表示するだけのコードです。
MESSAGEの値を表示する(app.js)
console.log(process.env.MESSAGE);
そして次のようにenv <環境変数名>=<値> <コマンド>
と呼び出すことで、その場限りの環境変数が設定された状態でコマンドを実行できます。ここで設定した環境変数は呼び出したコマンドにしか影響しないので、その後のOSの動作に影響を与えることはありません。
シェルによっては先頭のenv
を省略できます。
これはnode
コマンドでも可能なので、次のようにしてJavaScriptへ任意の環境変数を渡せます。これでhello!
という出力が得られるはずです。
任意の値を設定しながら実行する(app.js)
env MESSAGE=hello! node app.js
> hello!
未定義の環境変数にアクセスした場合にはundefined
となります。
未定義の環境変数にアクセスする(app.js)
env node app.js
> undefined
Node.jsに渡る環境変数はすべて文字列となります。数値のつもりで渡した環境変数がJavaScriptとしては文字列扱いになっているかもしれないので注意しましょう。
次のコードで環境変数に渡ってきた値の型を調べます。
変数の値の型を調べる(app2.js)
console.log(typeof process.env.MESSAGE);
環境変数に数値を渡したつもりですが、文字列型と判定されました。
42という値の型は文字列(app2.js)
env MESSAGE=42 node app2.js
> string
複数の環境変数を渡すこともできます。次のコードで確かめてみます。
複数の環境変数を準備する(app3.js)
console.log(process.env.MESSAGE);
console.log(process.env.MESSAGE_2);
スペースを空けて環境変数の設定を続けて書くことで複数の環境変数を渡せます。
2つの環境変数の値を設定して実行する(app3.js)
env MESSAGE=hello! MESSAGE_2=42 node app3.js
> hello!
> 42
Node.jsで使われる環境変数の種類
Node.jsあるいはWebプログラミングでは、環境変数をコードのデプロイ先に応じて切り替える用途に使われるケースが多くあります。このセクションではそれらのケースにおいて、どのように環境変数が使用されるかを紹介します。
NODE_ENV
Node.jsを扱っていてよく目にする環境変数はNODE_ENV
でしょう。これは主に、Node.jsプログラムの実行される環境が本番環境かどうかを判定する際に使われます。Node.jsで動作するコードを書くプログラマは基本的にNODE_ENV
が"production"
であれば本番環境と判定して動作するコードを書きますし、世に存在するライブラリも同様に動作します。
このNODE_ENV
が"production"
ではない場合は、本番環境ではない開発環境であると判定してデバッグログを表示したり、本番用の最適化を施さずに動作するような分岐が行われる実装が多くあります。
NODE_ENV
によく設定される値には、主にこの"production"
か、開発環境であることを明示するための"development"
があります。他にはテストとして実行中であることを示す"test"
が使われることもあります。テストフレームワークであるJestは、自動的にNODE_ENV
に"test"
をセットします。
こうしたNODE_ENV
を見て動作を切り替える挙動は、Node.jsが規定した動作ではなく慣習として広まっている知識です。そのため勝手にNODE_ENV
に好きな値を設定することは自由であるものの、この慣習にしたがっておくことが懸命です。
もしNODE_ENV
関係で思わぬ動作があれば用いているツールの中にJestのような、自動的にNODE_ENV
へ値をセットするような機能を持ってないか調べてみるとよいでしょう。
アプリケーションの設定値
サーバーアプリケーションや単体の関数など、本番環境にデプロイしてインターネット経由での呼び出しに応じるNode.jsアプリケーションの設定値を、ローカル環境での開発時や開発環境へのデプロイ時に応じて切り替えることにも環境変数を利用します。
これは開発しているものに合わせて、さまざまな種類のものが登場してくると思いますが、たとえば次のような値は環境変数で管理する値の候補になります。
- 利用するWeb APIのドメイン
- 外部サービスのAPIキー
- 外部サービスの設定値
- データベースの設定値
ローカルではローカルのモックサーバーにリクエストをするようにして、リモートの開発環境ではリモートの開発サーバー、本番環境では本番のサーバーにリクエストするといった動作を切り替えるために使われたりします。
リポジトリにコミットしたくない値
これは先に述べたアプリケーションの設定値と重複する内容ではあります。秘匿しなければならない値がリポジトリへコミットされることのないように、コード中から排除するために環境変数が利用されることも多くあります。
GitHubの公開リポジトリへpushする場合に気をつけなければならないのはもちろんのこと、限定公開リポジトリであったとしても、リポジトリの公開範囲と秘匿したい設定値を公開できる範囲はまた別の話です。非公開リポジトリなら大丈夫だと現時点で思っていても、将来公開リポジトリに変更するかもしれません。そのときに秘匿したい値のコミットログが見えてしまう可能性があります。
GitHubなどで誤って公開されたAPIキーが盗まれることによってクラウドサービスの不正利用に遭うケースもあります。利用しているサービスからこの値は公開しないことと案内されていれば、それに従いましょう。秘密鍵、シークレットキー、プライベートキー、あるいはシークレットトークンなど、秘密であることを連想するフレーズが現れたときにも注意しましょう。
一度GitHubにpushしてしまうと、その履歴を改変するのも面倒なので、開発当初から環境変数の利用が意識されているとよいです。
まとめ
今回は環境変数とはなにかについて、主にNode.jsの視点から説明しました。
次回はローカル環境での環境変数管理に便利なdotenvライブラリについて紹介する予定です。