RareJob Tech Blog

レアジョブのエンジニア・デザイナーによる技術ブログです

Nuxtで環境に応じた環境変数をいい感じに設定する

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で環境を作っていく上でこんな感じで作っていくといいかも思える様な設定などについても、改めてご紹介できればと思っております。

最後まで読んで頂きありがとうございました。