APP/UXチームに所属しております、フロントエンドエンジニアの田原です。
前回の記事から時間が空きましたが、弊社ブログ2回目の登場です。よろしくお願いします。
(隙あらば自分語り) 私は映画が好きなのでよく映画館に観に行くのですが、
最近はコロナの影響もあり外出を極力控えているので、そうこうしている間に観たい映画の劇場公開が終わってしまうのだろうなという寂しさで胸がいっぱいになる日々を過ごしております。
(直近ではミッドサマーを観に行こうと思っていましたが、、、諦めました)
ちなみに誰も興味がないとは思うのですが一番好きな映画はインファナル・アフェア - Wikipedia(3部作)とダークナイト - Wikipediaです。(一番と言っておきながら4本も上げていますが、どうしても順位がつけられないので)
インファナル・アフェア好き!という方と中々巡り合った事がないので、これを機に好きになる方が増えると嬉しいです。
さて、前置きが長くなってしましたが、今回の本題に入らせて頂きたいと思います。
過去の記事でも紹介しておりますが弊社ではフロントエンドフレームワークにVue.js(以下、Vue)を採用し、開発をおこなっております。
Vueを使った開発経験ある点もあって、最近、新たにスタートしたProjectにおいてはNuxt.js(以下、Nuxt)を採用する運びとなりました。
※前回の記事は↓↓
rarejob-tech-dept.hatenablog.com
今回はNuxtで開発をおこなっていくにあたり、先に設定しておくと楽だなと思ったProject内での環境変数の取り扱いについてご紹介させて頂きます。
目次
環境変数の扱いについて
Nuxtを利用してProject(App)の準備を行うにあたり、create-nuxt-app
コマンドで環境の準備をおこないますが、その際に.env
ファイルが自動で生成されるので、
このファイル内でApp内で利用する環境変数を定義し読み込めるようにすることが多いと思います。
とはいえ、開発環境が多岐にわたってくると(local/dev/prod)初期設定時からの.env
ファイルのみでは扱いが少し面倒になってくるかと思います。
実現したかった事
- 環境毎対応する
.env
ファイルを定義しておき、Nuxt Appのdeployやbuildのscriptコマンドに応じて、それぞれの環境変数がApp内で参照出来るようにしたい。 - 環境毎の設定については可読性や拡張性についても考慮した作りとしたい。
- SSR対応のProject(App)ではない為、クライアントサイドからの参照ができれば良い。
対応について
1. dotenv(@nuxtjs/dotenv)をProject Appに追加
create-nuxt-app
で生成したApp(Project)に対して、dotenv(@nuxtjs/dotenv)を追加します。
github.com
※dotenvとは
カレントディレクトリに置かれた.env
ファイルを読み込み、そこに記述されたキー&バリューのペアをprocess.env 経由で参照できるようするnpm moduleです。
Nuxtで生成されたAppに対しては以下のコマンドでnuxt専用のものを追加します。
yarn add --dev @ nuxtjs / dotenv #またはnpm install --save-dev @ nuxtjs / dotenv
2. nuxt.config.jsに設定を記載
追加したdotenv moduleを利用する為にnuxt.config.jsのmoduleの項目に@nuxtjs/dotenv
を追記します。
nuxt.config.js
︙ modules: [ '@nuxtjs/dotenv' ︙ ] ︙
3. 各環境に対応するenvファイルを設定
Project Rootに各環境毎に対応する.env
ファイルを設置します。
config/
config ├── .env.dev ├── .env.local └── .env.prod
各々の.env
ファイルにApp内で利用したい環境変数を記載します。
e.g. env.local
BASE_API_ENDPOINT_URL="https://hogehoge/local"
e.g. env.dev
BASE_API_ENDPOINT_URL="https://hogehoge/dev"
︙
e.g. env.prod
BASE_API_ENDPOINT_URL="https://hogehoge/prod"
︙
※変数は複数定義してOK
4. package.jsonのscriptsでENVに各々の環境の文字列を渡すように指定する
package.json
︙ "scripts": { "dev": "ENV=local HOST=0.0.0.0 PORT=3000 nuxt", "build-local": "ENV=local nuxt build", "build-dev": "ENV=dev nuxt build", "build-prod": "ENV=prod nuxt build", },
※ENVに.envとして指定したファイル名(今回の例ではlocal/dev/prod)を渡している。
5. nuxt.config.jsに設定を追加し、config/
配下の.env
ファイルが読み込まれるように対応する
nuxt.config.js
const envPath = `config/.env.${process.env.ENV}||'local'` require('dotenv').config({ path: envPath }) export default { ︙ dotenv: { filename: envPath } }
【補足説明】
* 4で設定したscriptsでENVに文字列を渡している為、nuxt.config.js内においてprocess.env.〇〇
で文字列を取得できる。
* envPathに各.envファイルへのPathが代入され(config/.env.local等)、これによりdotenvを使って3で定義した各.envファイルへの参照が可能に
* dotenvのpathにenvPathを指定する。(ファイル名をオーバーライドする為の設定)
6. 型エラー解消
1〜5までの対応が終わっていれば、App内(.vue/.ts等)の各ファイルからprocess.env.〇〇で.env
ファイルに定義した環境変数に対して参照を行うことができます。
︙ created() { process.env.BASE_API_ENDPOINT_URL // scriptsで渡した引数の環境に応じた値が参照可能 }
ただし、process.env.〇〇という形ではApp内のどこからでも呼べてしまうのは統一性が無い&参照の際のprocess.envに型を入れたいので型の指定とplugin化を以下の様に行います。(型指定を行わない場合、Nuxt側で持っているdefaultの型がprocess.envにあたる為、想定した型で参照できない場合があります)
// environments.ts等(plugin file) export type export type EnvironmentVariables = { // nuxt default property ------------ NODE_ENV: string browser: boolean client: boolean mode: 'spa' | 'universal' modern: boolean server: boolean static: boolean APP_NAME: string // nuxt custom propety -------------- BASE_API_ENDPOINT_URL: string } export cont environments: EnvironmentVariables = { // nuxt default property ------------ NODE_ENV: process.env.NODE_ENV!, browser: process.browser!, client: process.client!, mode: process.mode!, modern: process.modern!, server: process.server!, static: process.static!, APP_NAME: process.env.APP_NAME!, // nuxt custom propety -------------- BASE_API_ENDPOINT_URL: process.env.BASE_API_ENDPOINT_URL! } export defalut (context: any, inject:(name: string, v: any) => any) => { inject('environments', environments) }
nuxt.config.js
︙ plugins: [ ︙ '@/plugins/environments' ︙ ]
準備したplugin file内で適当な名前でinjectしnuxt.config.jsにもpluginの宣言を行います。
また、TypeScript側で環境変数が設定されていることを検知させるためにtypes/enviroments.d.ts
を設定します。
import Vue from 'vue' import { EnvironmentVariables } from '@/plugins/environments' declare module 'vue/types/vue' { interface Vue { $environments: EnvironmentVariables } }
最終的にApp内でthis.$enviroments.process.env.〇〇
という様に指定した環境変数を参照することができます。
参考にさせて頂いたサイト
dotenvについて
process.envの型指定について
まとめ
各APIに対してのRequest basePathが環境によって異なることに気づいたタイミングでこの対応を行いましたが、最初にこの辺りについて対応しておいた方が楽だったなぁっと思い、備忘録も兼ねて内容を残しました。
editor formatのチーム間の設定やaxios-modulesとの付き合い方やstoreの設計、その他にもCSS-moduleやstorybookの設定周辺等、Nuxtで環境を作っていく上でこんな感じで作っていくといいかも思える様な設定などについても、改めてご紹介できればと思っております。
最後まで読んで頂きありがとうございました。