やりたいこと
Create React Appで作成したReactアプリケーションで環境変数を扱いたいという場面があり注意すべきことに出会ったのでそれについて書いていきます。
早速Create React Appのドキュメントを読んでみました。次のように書かれています。
Your project can consume variables declared in your environment as if they were declared locally in your JS files. By default you will have NODE_ENV defined for you, and any other environment variables starting with REACT_APP_.
つまりREACT_APP_
から始まる環境変数を使用することができるようです。
REACT_APP_NOT_SECRET_CODE
という名前で変数を宣言すると、JS側からはprocess.env.REACT_APP_NOT_SECRET_CODE
として使用できるそうです。
環境変数の定義
シェルで一時的な環境変数を追加して使用することもできます。
Bashの場合は以下のようになります。
REACT_APP_NOT_SECRET_CODE=abcdef npm start
またはプロジェクトのルートに.envファイルを作成して、そのファイルに環境変数を定義することもできます。
REACT_APP_NOT_SECRET_CODE=abcdef
以下のようにDOMAINという定義された変数を拡張して、.envファイルで使用するすることもできます。
DOMAIN=www.example.com
REACT_APP_FOO=$DOMAIN/foo
REACT_APP_BAR=$DOMAIN/bar
環境変数を変更すると、それを反映させるために、開発サーバーが起動している場合は再起動が必要になります。
注意ポイント。プライベートAPIキーなどは環境変数で使わないこと。
ドキュメントには注意書きで次のように書かれています。
WARNING: Do not store any secrets (such as private API keys) in your React app!
Environment variables are embedded into the build, meaning anyone can view them by inspecting your app's files.
訳すと以下のような意味です。
警告:Reactアプリに秘密(プライベートAPIキーなど)を保存しないでください。
環境変数はビルドに組み込まれているので、アプリのファイルを調べれば誰でも見ることができます。
ビルド時には、process.env.REACT_APP_NOT_SECRET_CODE
が環境変数REACT_APP_NOT_SECRET_CODE
の現在の値に置き換えられます。
つまり.envに環境変数を書いて.envファイルをgitignoreしておくと、GitHubに変数を公開することを防ぐことができますが、ビルドしたファイルの内容を見れば誰でも変数の内容を見ることができるようです。
例
render() {
return (
<div>
<small>You are running this application in <b>{process.env.NODE_ENV}</b> mode.</small>
<form>
<input type="hidden" defaultValue={process.env.REACT_APP_NOT_SECRET_CODE} />
</form>
</div>
);
}
これをnpm startして、ブラウザで画面を見てみます。検証をして内容を見てみると以下のようになります。REACT_APP_NOT_SECRET_CODEの内容が丸見えですね。
<div>
<small>You are running this application in <b>development</b> mode.</small>
<form>
<input type="hidden" value="abcdef" />
</form>
</div>
どうするか
クライアント側から直接シークレットキー等を使用して外部のAPIを叩いているという状態を避けるためにどうするかという問題ですが、APIキーやシークレットはバックエンドにのみが持つべきだそうです。
クライアントがバックエンドAPIにリクエストを送り、バックエンドAPIがAPIキーを使って実際のAPIコールを行い、データをクライアントに送り返すように実装するのが良いのではないかと考え、そちらの方向で実装をするようにしました。またAPIキーの使用範囲の制限などをしていたり、特に公開されても問題のないキーであれば、それを使用してフロントエンド側から外部のAPIを直接叩いても問題ないと思います。
以上です。コメント、指摘等あれば宜しくお願い致します🙇♂️