りゅーそう
元高校地歴科教員。現在microCMSでエンジニアをしています。
Saitama.jsというLT会を運営中です。
発言はすべて個人の意見です。
gatsby
2020/07/20
2022/01/23
GatsbyとNetlifyの環境変数の扱いで少し戸惑い時間を無駄にしてしまったので、これからGatsbyをいじろうかなという人は私の屍を超えていってください。
※以前誤ったことを描いていたので大幅にリライトしました。申し訳ありませんでした。
基本的にはこちらの公式ドキュメントに書いてあることです。ただ、自分は理解に苦しんだのでなんとなくGatsbyの環境変数を扱っている人は当記事で完全理解を目指してください。
Environment Variables | Gatsby
まずは基本です。
Gatsbyに限らず、API_KEYなどの漏洩するとセキュリティ上問題となる値は.envファイルで管理します。
以下はmicroCMSのAPI_KEYとGoogleアナリティクスの例になります。
X_API_KEY=xxxxxx-xxxxxxx-xxxxxxx-xxxxxxx
X_WRITE_API_KEY=xxxxxxxx-xxxxxxxx-xxxxxxx
GA_TRACKING_ID=xxxxxxxxxxxx-xxxxx
Gatsbyでは.env.developmentと.env.productionというような名称でファイルを作成することで開発環境と本番環境で使用する値を別々に管理することができます。
//.env/development
X_API_KEY=xxxxxx-xxxxxxx-xxxxxxx-xxxxxxx
X_WRITE_API_KEY=xxxxxxxx-xxxxxxxx-xxxxxxx
GA_TRACKING_ID=xxxxxxxxxxxx-xxxxx
//.env.production
X_API_KEY=xxxxxx-xxxxxxx-xxxxxxx-xxxxxxx
X_WRITE_API_KEY=xxxxxxxx-xxxxxxxx-xxxxxxx
GA_TRACKING_ID=xxxxxxxxxxxx-xxxxx
これらの値を環境ごとに使用するためにはgatsby-config.jsの先頭に設定を書く必要があります。dotenvが必要になるのでインストールしましょう。
yarn add dotenv
npm | dotenv
.gitignoreに.env.*を加えて、管理から外すのを忘れずに
gatsby-config.jsの先頭に以下のように書いて設定します。
//gatsby-config.js
require('dotenv').config({
path: `.env.${process.env.NODE_ENV}`,
});
module.exports = {
// plugin setting
};
これで gatsby developを実行した際には.env.developmentが、gatsby buildを実行した際には.env.productionに設定した値が使用されます。
.env.*で設定した値はブラウザで実行することはできません。例えば以下のように使用してURLにアクセスすることはできません。
//.env.development
BASE_URL=https://ryusou-mtkh.microcms.io/api/v1/
//フロントエンドのコードURLにアクセスしてAPIを叩くコード
//Gatsbyでこのようなコードを書くことはあまりないと思いますが、あくまで例です
const content = await fetch(BASE_URL, ・・・)
ですが、GATSBY_と接頭につけるとブラウザ上でもアクセスすることができます。
//.env.development
GATSBY_BASE_URL=https://ryusou-mtkh.microcms.io/api/v1/
アクセスできるということは当然ブラウザ上のコードからもアクセスできてしまうということなので、API_KEYなどの重要な情報につけては絶対にいけません。
使用するのはURLなど、第三者にアクセスされても問題がない値に制限してください。これらの値はわざわざ環境変数にする必要もなく、変数として定義できるので、GATSBY_は基本的には使わないというのが良いと思います。
あくまで、自分の狭い世界でのgatsbyを使用していて環境変数を使用するのは以下の3パターンかと思います。
(追加あったらTwitterなどにコメントお願いします。)
単純に変数と同じような使い方です。前章で述べたものももちろんですが,
Netlifyなどを使用しているとNetlify PluginなどでCl回すなどの選択肢も一応あります。Netlifyは.env.productionの値を読んでくれるので便利です。
この点ではあまり扱いに考慮することはそれほどないでしょう。
以下のように定義すればOKです。
//.env.production
//Netlifyでlighthouseを回すプラグインの設定
THRESHOLDS={"performance":0.9,"accessibility":0.9,"best-practices":0.9,"seo":0.9,"pwa":1.0}
Jamstack流行っていますね。HeadlessCMSでコンテンツ管理を行ってGatsbyのSSGを使ってコンテンツを表示する方法です。
当ブログでもmicroCMSを使用しています。
このAPI_KEYはアクセスされるとセキュリティ上問題があるので取り扱いには注意が必要です。
ただ、Gatsbyを使ったJamstack構成においては考慮する点は多くありません。
GatsbyでHeadlessCMSの情報を取得するにはgatsby-config.jsでpluginを使用して設定しますが、その際にはデプロイされる事前にレンダリングされるのでこれらの値がブラウザ上からアクセスされる心配はありません(逆に言えばコンテンツを扱う際にはgatsby-config.jsから設定するようにしましょう)。
//gatsby-config.js
require('dotenv').config({
path: `.env.${process.env.NODE_ENV}`,
});
module.exports = {
plugins: [
{
resolve: `gatsby-plugin-google-analytics`,
options: {
trackingId: `${process.env.GA_TRACKING_ID}`,
head: true,
respectDNT: true,
},
},
{
resolve: 'gatsby-source-microcms',
options: {
apiKey: process.env.X_API_KEY,
serviceId: 'ryusou-mtkh',
apis: [
{
endpoint: 'posts',
},
],
},
},
],
};
このあたりの仕組みはJamstackの魅力ですね!
以前まで、.envで環境変数を設定すればAPI-KEYは隠蔽されると思っていましたが、コンパイルされたコードをブラウザのデベロッパーツール などを引用すれば見えてしまうそうです。
詳しくはこちら:
https://microcms.io/blog/nuxt-secure-api-key
なのでHeadlessCMSや外部APIにアクセスする際には必ずバックエンド側でAPI-KEYを処理するようにしましょう。
GatsbyだとNetlify Functionsがおすすめです。
Netlify Functions
この辺りのCORSなどの設定を簡潔に設定してくれるNetlify devもとても便利です。
https://docs.netlify.com/cli/get-started/#installation
このあたり記事を今度また書く予定です。お楽しみに。
Gatsby(限らずですが)の環境変数の扱いには十分注意して管理しましょう。特にブラウザ上で参照する際はその値はもれても大丈夫な値かをよく検討することが大切です。
SPA、SSGとフロントエンド周りでいろいろできるようになった今こそ、セキュリティに注意をして実装していきましょう!(自分に向けて)