はじめに
これまでRailsでdotenvを使っていたので、同じ感覚で使えるだろと思い、今回の個人開発Reactでも採用することに。
ところが、どうも設定がうまくいかず、一時期ずっと悩んでいました。
つい最近、ようやく問題が解決したので、原因となっていた問題と共にアウトプットとして記事に残します。
また、この記事はTwitterで人気のハッシュタグ#100DaysOfCodeをつけて、
100日間プログラミング学習を続けるチャレンジに挑戦した38日目の記録です。
動作環境
- react-scripts: 1.1.4
前提条件
create-react-app
でReactプロジェクトを立ち上げていること
今までの設定方法
下記のdotenv公式サイトを参考に、READMEにならってプロジェクト直下に.env
を作成しました。
当時のdotenvのファイル内容はこんな感じ。
YOUTUBE_API_KEY=hogehogehugahuga485732
で、dotenvで設定したファイルを次のようにコンポーネントで読み込んでました。
ここでは、youtube-api-search
のAPIキーをdotenvで管理しようとしていました。
import React, { Component } from "react";
import YTSearch from "youtube-api-search";
import dotenv from "dotenv";
const API_KEY = dotenv.config(process.env.YOUTUBE_API_KEY);
console.log(API_KEY);
YTSearch({ key: API_KEY, term: "水族館" }, function(data) {
console.log(data);
});
結果、コンソールで次のようなエラーが発生していました。
{error: TypeError: fs.readFileSync is not a function
at Object.config (http://localhost:3000/static/js/b…}
xhr.js:115 GET https://www.googleapis.com/youtube/v3/search?part=snippet&key=%7B%22error%22:%7B%7D%7D&q=%E6%B0%B4%E6%97%8F%E9%A4%A8&type=video 400 ()
xhrAdapter @ xhr.js:115
(anonymous) @ dispatchRequest.js:15
dispatchRequest @ dispatchRequest.js:11
Promise.then (async)
../node_modules/axios/lib/axios.js.module.exports @ axios.js:40
axios.(anonymous function) @ axios.js:66
../node_modules/youtube-api-search/index.js.module.exports @ index.js:17
./src/components/Youtube/youtube_search_bar.js @ youtube_search_bar.js:9
__webpack_require__ @ bootstrap cce4570accfe85501067:678
fn @ bootstrap cce4570accfe85501067:88
./src/App.js @ App.css?9a66:26
__webpack_require__ @ bootstrap cce4570accfe85501067:678
fn @ bootstrap cce4570accfe85501067:88
./src/index.js @ index.css?f255:26
__webpack_require__ @ bootstrap cce4570accfe85501067:678
fn @ bootstrap cce4570accfe85501067:88
0 @ registerServiceWorker.js:117
__webpack_require__ @ bootstrap cce4570accfe85501067:678
(anonymous) @ bootstrap cce4570accfe85501067:724
(anonymous) @ bootstrap cce4570accfe85501067:724
index.js:2178 {data: {…}, status: 400, statusText: "", headers: {…}, config: {…}}
どうやら、dotenvに設定したはずの、APIキーの値が読みこまれていないようです。
解決に向けてやったこと
- dotenvリポジトリのcloseされたissueの中から、関連したものがないか検索してみる
- create-react-appのソースコードを読んでみる
いくつか検索していくうちに、create-react-appのUsers Guideに、次のような一文があることを発見。
Note: this feature is available with react-scripts@0.5.0 and higher.
To define permanent environment variables, create a file called .env in the root of your project:
REACT_APP_SECRET_CODE=abcdef
Note: You must create custom environment variables beginning with REACT_APP_. Any other variables except NODE_ENV will be ignored to avoid accidentally exposing a private key on the machine that could have the same name. Changing any environment variables will require you to restart the development server if it is running.
ここによると、create-react-appで作成したプロジェクトでdotenvを使用する場合、prefixにREACT_APP_
をつける必要があるとのこと。
ということは、もしやcreate-react-app自体に、すでにdotenvが組み込まれているのでは?
ソースコードを調べてみると。。
var dotenvFiles = [
`${paths.dotenv}.${NODE_ENV}.local`,
`${paths.dotenv}.${NODE_ENV}`,
すでにenv.js
があるじゃないですか!
つまり、わざわざdotenv.config(process.env.YOUTUBE_API_KEY);
のように書かなくても、create-react-appでは、すでにdotenvを使えるようにお膳立てしてくれているので、それに任せればいいということ。
改修後のコード
というわけで、最終的に動くようになったコードがこちら。
import React, { Component } from "react";
import YTSearch from "youtube-api-search";
const API_KEY = process.env.REACT_APP_YOUTUBE_API_KEY;
console.log(API_KEY);
YTSearch({ key: API_KEY, term: "水族館" }, function(data) {
console.log(data);
});
REACT_APP_YOUTUBE_API_KEY=hogehogehugahuga485732
これでコンソールでもエラーは出ずに、無事API経由で値を取ることができました!
(5) [{…}, {…}, {…}, {…}, {…}]
0
:
{kind: "youtube#searchResult", etag: ""XI7nbFXulYBIpL0ayR_gDh3eu1k/5XPZmUCd7jo1pdJ1-CDdosFeI-Y"", id: {…}, snippet: {…}}
1
:
{kind: "youtube#searchResult", etag: ""XI7nbFXulYBIpL0ayR_gDh3eu1k/0UIYPKhKX74Bsl8caKN0h2CyjnI"", id: {…}, snippet: {…}}
2
:
{kind: "youtube#searchResult", etag: ""XI7nbFXulYBIpL0ayR_gDh3eu1k/Kq9VGmwBXKns6SFyEP9eOBvDYoU"", id: {…}, snippet: {…}}
3
:
{kind: "youtube#searchResult", etag: ""XI7nbFXulYBIpL0ayR_gDh3eu1k/dgrrAw4tSfS0I0Tm_3HAWMZikC4"", id: {…}, snippet: {…}}
4
:
{kind: "youtube#searchResult", etag: ""XI7nbFXulYBIpL0ayR_gDh3eu1k/9cZ31PrsKQHnbREvITl_0hnheMY"", id: {…}, snippet: {…}}
length
:
5
__proto__
:
Array(0)
最後に
答えは常に公式リファレンスと公式リポジトリに書いてある。