Nuxt.jsでmicroCMSのAPIキーを隠蔽する
Nuxt.js+microCMSでJamstac構成の静的サイトを作成する際に、APIキーを隠蔽する方法の覚書です。以下のような内容です(インストールや導入部分も簡単に触れていますが適宜読み飛ばしてください)。
- Nuxt.jsのインストール
- microCMSの導入とコンテンツの作成
- コンテンツの表示
- APIキーの隠蔽
Nuxt.jsのインストール
create-nuxt-appでNuxt.jsをインストールします。今回は以下の設定にしています。
$ npx create-nuxt-app microcms-test
create-nuxt-app v3.6.0
✨ Generating Nuxt.js project in microcms-test
? Project name: microcms-test
? Programming language: JavaScript
? Package manager: Npm
? UI framework: Tailwind CSS
? Nuxt.js modules: Axios - Promise based HTTP client
? Linting tools: ESLint, Prettier
? Testing framework: None
? Rendering mode: Universal (SSR / SSG)
? Deployment target: Static (Static/Jamstack hosting)
? Development tools: jsconfig.json (Recommended for VS Code if you're not using typescript)
? Continuous integration: None
? Version control system: Git
- モジュールは非同期通信でAPIを利用するため
Axiosを選択 - レンダリングモードは
Universal (SSR / SSG)を選択 - デプロイのターゲットは
Static (Static/Jamstack hosting)を選択
それ以外は適宜必要なものを選択します。
生成されたpackage.jsonは以下のようになっています。今回Nuxt.jsのバージョンは"2.15.3"を使用しました。
{
"name": "microcms-test",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate",
"lint:js": "eslint --ext \".js,.vue\" --ignore-path .gitignore .",
"lint": "npm run lint:js"
},
"dependencies": {
"@nuxtjs/axios": "^5.13.1",
"core-js": "^3.9.1",
"nuxt": "^2.15.3"
},
"devDependencies": {
// ...
}
}
インストールが完了したら、ディレクトリに移動してNuxt.jsを起動します。
cd microcms-test
npm run dev
http://localhost:3000/ でアクセスして、以下のように表示されれば完了です。

microCMSの導入
公式ドキュメントの操作マニュアルの手順にそってmicroCMSを導入します。 アカウント登録 → ログイン → サービスの作成まで行うと、管理画面へのURLが発行されるのでこれにアクセスします。
APIの作成
管理画面にアクセスするとAPIの作成画面に移るので、API名とエンドポイントを設定します。今回はAPIの型にリスト形式を選択して、APIスキーマを以下のように定義しました。

コンテンツの作成
コンテンツはサンプル用に以下のように登録しました。

コンテンツの表示
ここまでできたらNuxt.js側からコンテンツを取得して表示してみます。pages/index.vueを以下のように書き換えます。your-service-idとyour-api-keyはそれぞれ作成したサービスのものにします。
<template>
<div>
<div
v-for="item in items"
:key="item.id"
class="m-4 border-2 border-blue-300"
>
<h1 class="p-2 text-xl text-blue-700 bg-blue-300">{{ item.title }}</h1>
<p class="p-2 text-gray-800">{{ item.body }}</p>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
async asyncData() {
const { data } = await axios.get('https://your-service-id.microcms.io/api/v1/test', {
headers: { 'X-API-KEY': 'your-api-key' },
})
return {
items: data.contents,
}
},
}
</script>
axiosを利用してasyncData()の戻り値itemsにデータを取得して、それをv-forでリストレンダリングしています。(クラスは適当につけていますが無視してください)
asyncData()はサーバーから非同期データを直接取得しています。
これでmicroCMSから取得したデータがブラウザに表示されました!

APIキーの隠蔽
ここから本題のAPIキーの隠蔽についてです。
Nuxt.jsの2.12以前では、環境変数としてAPIキーを定義してprocess.env経由で参照する方法や、nuxt.config.js内でenvを利用して設定する方法がありました。process.env経由で利用する方法ではビルド時に定数に変換されてバンドル後のファイルにはAPIキーの値が含まれてしまっている、nuxt.config.js内でenvの設定値はクライアント側から参照できてしまう、などそれぞれ問題がありました。Nuxt.jsの2.13以降からはnuxt.config.jsのpublicRuntimeConfigとprivateRuntimeConfigプロパティを利用してAPIキーをクライアント側から完全に隠蔽できるようになりました。
環境変数を定義して読み込む
まず、ルート階層に.envファイルを作成し、以下のように記述します。
your-service-idとyour-api-keyはそれぞれ作成したサービスのものに置き換えます。
BASE_URL=http://localhost:3000
API_KEY=your-api-key
API_URL=https://your-service-id.microcms.io/api/v1
次にNuxt.jsからこれを参照するためにnuxt.config.jsに以下のように定義します。
const { API_KEY, API_URL } = process.env;
export default: {
// ...
publicRuntimeConfig: {
apiUrl: API_URL,
apiKey: process.env.NODE_ENV !== 'production' ? API_KEY : undefined
},
privateRuntimeConfig: {
apiKey: API_KEY,
},
}
publicRuntimeConfigにはクライアント側で利用するための環境変数を定義し、privateRuntimeConfigにはサーバー側で利用するための環境変数を定義します。
publicRuntimeConfig内ではprocess.env.NODE_ENVがproductionでない場合(開発中npm run dev時)にAPI_KEYの値を参照できるようにして、本番環境では参照しないようにしています。
publicRuntimeConfigの値はprivateRuntimeConfigによって上書きされるので、本番環境ではクライアント側からは隠蔽されます。
APIキーの記述を書き換える
これで$configから情報を取得できるようになったので、asyncData()の引数に$configを渡して$config.apiKeyでAPIキーを参照するようにpages/index.vueを書き換えます。
(urlも$config.apiUrlで参照するように書き換えています)
<template>
<div>
<div
v-for="item in items"
:key="item.id"
class="m-4 border-2 border-blue-300"
>
<h1 class="p-2 text-xl text-blue-700 bg-blue-300">{{ item.title }}</h1>
<p class="p-2 text-gray-800">{{ item.body }}</p>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
async asyncData({ $config }) {
const { data } = await axios.get(`${$config.apiUrl}/test`, {
headers: { 'X-API-KEY': $config.apiKey },
})
return {
items: data.contents,
}
},
}
</script>
これでAPIキーを隠蔽しつつmicroCMSから取得したデータをブラウザに表示できるようになりました。
参考
-
https://blog.microcms.io/nuxt-secure-api-key
microCMS公式のブログ記事です。とても丁寧に説明されていてありがたいです。 -
https://books.mdn.co.jp/books/3220303021/
書籍の後半部で、Nuxt.js+microCMSでJamstack開発が学べます。初心者でも理解しやすかったです。おすすめです。
Discussion