1
Help us understand the problem. What are the problem?
Organization

Vue + Dotenv で環境別の開発・運用を考える

はじめに

Vue.js で SPA のフロントを構築し始めると、開発・検証・本番と環境別に違う情報を管理することになるかと思います。

そこで環境別の情報を .env ファイルに記述し、CI/CD に乗せて運用していく中で、ソース管理やファイル構成に困ったことはないでしょうか?

そんな時の一例を紹介しますので、何かの一助になれば幸いです!

※ 一個人の見解ですので必ずしも正解や正攻法ではありません。より良い方法があればお気軽にフィードバック頂ければと思います。

課題

.env ファイルに環境別の情報(サーバー情報や接続情報など)を記述して、Vue.js のフロントエンドを構築しました。

しかし、運用していくと以下のような課題が発生してきました。

  • Git のブランチを環境別に作っているため、環境設定ファイルを管理しにくい
    • develop ブランチ内に、 staging 環境の環境設定ファイルがある…等
  • 環境別ファイルをソースコードと別リポジトリで管理すると、今度は開発がやりにくい
    • ソースコードリポジトリのブランチを切り替えたら、環境設定リポジトリも切り替える必要がある…等

解決方法

本記事では下記のステップで各課題を解決していきます。

  1. 環境別の変数をファイルごとに管理する
    1.1. 環境別の構成
  2. 環境別ファイルをGitで管理する
    2.1. 環境別の構成(Git管理向け)
    2.2. 運用例
    2.3. 開発方法

構成・前提

Vue CLI で SPA として構築します。

項目 バージョン
Vue CLI 4.5.9
Vue.js 2.6.11
npm 8.1.0

なお、ローカル開発環境のOSは、Windows10を想定しています。

環境別の構成

環境別ファイルを構成する上で、Vue CLI の「モードと環境変数」を参考にします。

Qiita記事だと下記が参考になります。

環境

本記事では下記の環境を想定します。

環境名 内容
development 開発環境
staging 検証環境
production 本番環境

.env ファイル

環境に従って、モードごとの .env ファイルを作成します。

作成した .env ファイルは下記のファイル構成の通り配置します。

ファイル構成

    app
    ├─ node_modules
    ├─ public
    │   ├─ favicon.ico
    │   └─ index.html
    │
    ├─ src
    │   ├─ assets
    │   │   └─ logo.png
    │   │ 
    │   ├─ components
    │   │   └─ HelloWorld.vue
    │   │
    │   ├─ App.vue
    │   └─ main.js
    │ 
    ├─ .env.development        # 追加
    ├─ .env.production         # 追加
    ├─ .env.staging            # 追加
    ├─ .gitignore
    ├─ babel.config.js
    └─ package.json

ルートディレクトリ(app)下に .env.[mode] ファイルが環境分並びます

.env ファイル内容

例として、.env.staging の内容を記載します。

.env.staging
NODE_ENV='production'
VUE_APP_MODE='staging'

ポイント
環境変数 VUE_APP_MODE がモードを表す変数になります。
.env.[mode][mode] 部分を変数の値として設定します。

注意点
紛らわしいですが、NODE_ENV は Node.js の環境変数となるため、値('production')は関係ありません。

package.json

モードを適用してビルドできるように package.json を編集します。

package.json
...
  "scripts": {
    "serve": "vue-cli-service serve --mode staging",
    "build-development": "vue-cli-service build --mode development",
    "build-staging": "vue-cli-service build --mode staging",
    "build-production": "vue-cli-service build --mode production",
    "lint": "vue-cli-service lint"
  },
...

環境変数の確認

main.js

確認のため、環境変数としてビルドされた process.env.VUE_APP_MODE の値を出力します。

main.js
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

console.log(process.env)  // 追加

new Vue({
  render: h => h(App),
}).$mount('#app')

ローカルサーバー起動

モードを staging に指定してローカルサーバーを起動します。

image.png

NODE_ENVVUE_APP_MODE が出力されました(他のキーはデフォルトで設定されます)。

image.png

この時点で、環境別ファイルの設定は完了しているので、これでも問題なく開発していけます。

しかし、上述している運用的な課題を解決するべく、もう少し手を加えます。

環境別の構成(Git管理向け)

今回は「環境別ファイルを独立した別のリポジトリで、かつ環境ごとのブランチで管理したい。」という要件がありました。
しかし、標準機能として扱える .env.[mode] ファイルは、ルートディレクトリに配置する必要があります。
そこで、Node.js のライブラリである dotenv と、dotenv-expand を用いて、ファイル構成や環境別ファイルを変更していきます。

dotenv + dotenv-expand

プロジェクトに dotenv と dotenv-expand をインストールします。

npm install dotenv --save-dev
npm install dotenv-expand --save-dev

envフォルダ

環境別ファイルを格納するフォルダおよび環境別ファイルを新規作成します。

ファイル構成

app
├─ env                     # 追加
│   ├─ development         # 追加
│   │   └─ .env            # 追加
│   │   
│   ├─ production          # 追加
│   │   └─ .env            # 追加
│   │   
│   └─ staging             # 追加
│       └─ .env            # 追加
│       
├─ public
(以下省略)

vue.config.js

vue.config.js をルートディレクトリ下に追加します。

vue-cli-service 実行時に自動で読み込まれるファイルです。

vue.config.js
var dotenv = require('dotenv').config({ path: `./env/${process.env.VUE_APP_MODE}/.env` })
if (dotenv.error) {
  throw dotenv.error
}
require('dotenv-expand')(dotenv)

ポイント

  • 1行目: 環境変数 VUE_APP_MODE を用いて、上記で作成した env フォルダ下の .env ファイルをパスに指定
  • 5行目: dotenvdotenv-expand で拡張

これで、環境別フォルダ下(app/env/)に、環境別ファイル(.env)を配置することができました。

env/{環境名}/.env

ファイルの中身の書き方としては、dotenv や、dotenv-expand に習います。

env/staging/.env
# Can use $VUE_APP_MODE, $NODE_ENV

# .env local variables
CLIENT_ID='abcde'

# Vue environment variables
VUE_APP_API_URL='https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/${CLIENT_ID}/${VUE_APP_MODE}'

※ 環境変数を設定した場合は、サーバーを再起動してください。

ポイント

  • 4行目: CLIENT_ID はこの .env ファイル内でのみ使用可能です。
    埋め込み変数として使用したいけれど、Vue アプリケーション上に必要ないという場合に有用です
  • 7行目: 例として VUE_APP_API_URL というキーで、環境別のAPIのURLを設定してみました。
    ここでは、.env.staging 内で定義している環境変数も使用できるので、${VUE_APP_MODE} を埋め込んでいます

環境変数の確認

ローカルサーバーを再起動して環境変数を確認します。

VUE_APP_API_URL が出力されました。埋め込み文字列も変換されています。

image.png

注意点

  • 同じ js ファイルで混同しやすいですが、src フォルダ以下(main.js など)が Vue.js のモジュールです
    vue.config.js は Node.js のモジュールになります
  • Vue CLI のドキュメント通り、Vue.js の環境変数は、プレフィックスとして VUE_APP_ を付加してください
  • 埋め込み文字列が不要な方は、dotenv-expand のセットアップが不要となります

運用例

それでは「環境別の構成(Git管理向け)」にて基盤を整えたところで、Git の運用例や CI/CD の設定例を見ていきます。

ソースコードリポジトリ

Vue アプリケーションのソースコードを管理するリポジトリは、下記の通り環境別にブランチを切ります。

なお、ブランチ間(環境間)ではソースコードや、ファイル構成の差異は発生しません。

ソースコードリポジトリ構成
SourceCodeRepository           # ソースコード用のリポジトリ
├─ development               # 開発環境ブランチ
│   └─ (省略: 下記ファイル構成の通り)
│   
├─ production                # 本番環境ブランチ
│   └─ (省略: 下記ファイル構成の通り)
│   
└─ staging                   # 検証環境ブランチ
    └─ (省略: 下記ファイル構成の通り)

env フォルダ下の除外

ソースコードリポジトリから、env フォルダ下の .env ファイルをGit管理対象外とします。

.gitignore

app/.gitignore に追記します。

.gitignore
...(省略)

# 追加
env/*.env

...(省略)

ファイル構成

最終的なソースコードリポジトリのファイル構成は以下の通りです。

ソースコードリポジトリ・ファイル構成
    app
    ├─ env                     
    │   └─ .gitkeep            # フォルダ構成を保つために追加
    ├─ node_modules
    ├─ public
    │   ├─ favicon.ico
    │   └─ index.html
    │
    ├─ src
    │   ├─ assets
    │   │   └─ logo.png
    │   │ 
    │   ├─ components
    │   │   └─ HelloWorld.vue
    │   │
    │   ├─ App.vue
    │   └─ main.js
    │ 
    ├─ .env.development        # 全環境残したままです
    ├─ .env.production         # 全環境残したままです
    ├─ .env.staging            # 全環境残したままです
    ├─ .gitignore
    ├─ babel.config.js
    ├─ package.json
    └─ vue.config.js

環境ファイルリポジトリ

env フォルダ下の環境別ファイルは、ソースコードとは別のGitリポジトリで管理します。

構成は以下の通りです。

環境ファイルリポジトリ構成
    EnvironmentRepository   # 環境ファイル用のリポジトリ
    ├─ development          # developmentブランチ
    │   └─ .env             # 環境別ファイル
    │   
    ├─ production           # productionブランチ
    │   └─ .env             # 環境別ファイル
    │   
    └─ staging              # stagingブランチ
        └─ .env             # 環境別ファイル

Git運用例

ここまでの設定によって、環境別の情報を管理する際の気持ち悪さが解消できました。
ただ、リポジトリを2つ運用することになるので、その点はご注意ください。

ソースコードリポジトリ

ソースコードリポジトリは、プルリクエストを基本としたよくある運用です。
プルリク→マージ→リリースとステージングしていきます。

環境ファイルリポジトリ

環境間の .env ファイルは必ず差分があるので、マニュアルで比較しながら各ブランチにマージします。

  1. development ブランチの .env ファイル修正
  2. development ブランチと比較しながら、staging ブランチの .env ファイル修正
  3. staging ブランチと比較しながら、production ブランチの .env ファイル修正

CI/CD設定例

各環境のパイプラインでは、下記のような手順でビルドします。
development 環境を例示します

  1. ソースコードリポジトリの development ブランチを clone
  2. 1.の app/env/ 下にディレクトリ指定で、環境ファイルリポジトリを clone
  3. git clone -b development https://{host}/app.git development
  4. vue-cli-service build --mode development でソースコードをビルド

開発方法

最後に、開発方法についても記載します。

env フォルダ下に環境ファイルリポジトリを clone すれば良いようにも感じますが、Gitリポジトリの中に別のGitリポジトリがあるのは望ましくありません。

よって、ここではシンボリックリンクを使用します。

環境ファイルを集約

ローカルで開発しているソースコードリポジトリとは別のディレクトリに、各ブランチを clone します。

ここでは C:\Dev\environments を作成します。

コマンドプロンプト
cd c:\Dev\environments
git clone -b development https://{host}/app.git development
git clone -b staging https://{host}/app.git staging
git clone -b production https://{host}/app.git production

クローン結果

environments フォルダ内。

image.png

各ブランチフォルダ内は、.env ファイルのみ。

image.png

シンボリックリンク作成

ローカルで開発しているソースコードリポジトリの env フォルダ内でコマンドプロンプトを開き、以下のコマンドを実行します。

※ 例では development 環境でローカルサーバーを起動しています。

コマンドプロンプト
mklink /j development c:\Dev\environments\development
mklink /j staging c:\Dev\environments\staging
mklink /j production c:\Dev\environments\production

シンボリックリンク(ジャンクション)を作成することで、env フォルダ下を除外する前の構成に戻りました。

image.png

開発方法まとめ

env フォルダ下はGit管理対象外なので、もし他のブランチにチェックアウトしても、env フォルダ下は消えたりしません。

ソースコードのブランチを変えるたびに、環境別ファイルをコピーしてきたりする手間を省くことができます。

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
1
Help us understand the problem. What are the problem?