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