|
| 1 | +--- |
| 2 | +title: 環境変数を使う |
| 3 | +sidebar: |
| 4 | + label: 環境変数 |
| 5 | +description: Astroプロジェクトで環境変数を使う方法を学びます。 |
| 6 | +i18nReady: true |
| 7 | +--- |
| 8 | +import PackageManagerTabs from '~/components/tabs/PackageManagerTabs.astro' |
| 9 | +import ReadMore from '~/components/ReadMore.astro'; |
| 10 | + |
| 11 | +Astroでは、[Viteに組み込まれた環境変数のサポート](#viteの組み込みサポート)を利用できます。また、いくつかの[デフォルト環境変数](#デフォルト環境変数)が用意されており、現在のプロジェクトの設定値(`site`や`base`など)や、プロジェクトが開発・本番のどちらで実行されているかなどにアクセスできます。 |
| 12 | + |
| 13 | +さらにAstroは、[型安全に環境変数を使い、整理する方法](#型安全な環境変数)も提供しています。これはAstroのコンテキスト内(Astroコンポーネント、ルートやエンドポイント、UIフレームワークコンポーネント、ミドルウェアなど)で利用でき、[Astro設定内のスキーマ](/ja/reference/configuration-reference/#env)で管理します。 |
| 14 | + |
| 15 | +## Viteの組み込みサポート |
| 16 | + |
| 17 | +Astroは、Viteに組み込まれた環境変数のサポートを利用します。これらの環境変数はビルド時に静的に置き換えられ、[Viteが提供する環境変数を扱うためのさまざまな機能](https://vite.dev/guide/env-and-mode.html)を利用できます。 |
| 18 | + |
| 19 | +なお、すべての環境変数はサーバーサイドのコードから利用できますが、セキュリティ上の理由から、クライアントサイドのコードで利用できるのは`PUBLIC_`で始まる環境変数のみです。 |
| 20 | + |
| 21 | +```ini title=".env" |
| 22 | +SECRET_PASSWORD=password123 |
| 23 | +PUBLIC_ANYBODY=there |
| 24 | +``` |
| 25 | + |
| 26 | +この例では、`PUBLIC_ANYBODY`(`import.meta.env.PUBLIC_ANYBODY`でアクセス可能)はサーバーコードでもクライアントコードでも利用できますが、`SECRET_PASSWORD`(`import.meta.env.SECRET_PASSWORD`でアクセス可能)はサーバーサイドでのみ利用できます。 |
| 27 | + |
| 28 | +:::caution |
| 29 | +`.env`ファイルは[設定ファイル](#astro設定ファイル内)の中では読み込まれません。 |
| 30 | +::: |
| 31 | + |
| 32 | +### TypeScriptのIntelliSense |
| 33 | + |
| 34 | +デフォルトでは、Astroは`astro/client.d.ts`内に`import.meta.env`の型定義をあらかじめ用意しています。 |
| 35 | + |
| 36 | +`.env.[mode]`ファイルでその他のカスタム環境変数を定義できますが、`PUBLIC_`で始まるユーザー定義の環境変数についてTypeScriptのIntelliSenseを効かせたい場合があります。 |
| 37 | + |
| 38 | +そのためには、`src/`に`env.d.ts`を作成して[グローバルな型を拡張](/ja/guides/typescript/#extending-global-types)し、次のように`ImportMetaEnv`を設定します。 |
| 39 | + |
| 40 | +```ts title="src/env.d.ts" |
| 41 | +interface ImportMetaEnv { |
| 42 | + readonly DB_PASSWORD: string; |
| 43 | + readonly PUBLIC_POKEAPI: string; |
| 44 | + // その他の環境変数... |
| 45 | +} |
| 46 | + |
| 47 | +interface ImportMeta { |
| 48 | + readonly env: ImportMetaEnv; |
| 49 | +} |
| 50 | +``` |
| 51 | + |
| 52 | +## デフォルト環境変数 |
| 53 | + |
| 54 | +Astroには、いくつかの環境変数が標準で組み込まれています。 |
| 55 | + |
| 56 | +- `import.meta.env.MODE`: サイトが実行されているモードです。`astro dev`の実行時は`development`、`astro build`の実行時は`production`になります。 |
| 57 | +- `import.meta.env.PROD`: サイトが本番環境で実行されている場合は`true`、それ以外は`false`になります。 |
| 58 | +- `import.meta.env.DEV`: サイトが開発環境で実行されている場合は`true`、それ以外は`false`になります。常に`import.meta.env.PROD`の逆の値です。 |
| 59 | +- `import.meta.env.BASE_URL`: サイトが配信されるベースURLです。[`base`設定オプション](/ja/reference/configuration-reference/#base)によって決まります。 |
| 60 | +- `import.meta.env.SITE`: プロジェクトの`astro.config`で指定された[`site`オプション](/ja/reference/configuration-reference/#site)が設定されます。 |
| 61 | + |
| 62 | +これらは、他の環境変数と同じように使えます。 |
| 63 | + |
| 64 | +```ts utils.ts |
| 65 | +const isProd = import.meta.env.PROD; |
| 66 | +const isDev = import.meta.env.DEV; |
| 67 | +``` |
| 68 | + |
| 69 | +## 環境変数を設定する |
| 70 | + |
| 71 | +### `.env`ファイル |
| 72 | + |
| 73 | +環境変数は、プロジェクトディレクトリにある`.env`ファイルから読み込まれます。 |
| 74 | + |
| 75 | +プロジェクトディレクトリに`.env`ファイルを作成し、変数をいくつか追加してみましょう。 |
| 76 | + |
| 77 | +```ini title=".env" |
| 78 | +# これはサーバー上で実行されるときのみ利用できます! |
| 79 | +DB_PASSWORD="foobar" |
| 80 | + |
| 81 | +# これはどこでも利用できます! |
| 82 | +PUBLIC_POKEAPI="https://pokeapi.co/api/v2" |
| 83 | +``` |
| 84 | + |
| 85 | +ファイル名に`.production`や`.development`、あるいはカスタムモード名(例: `.env.testing`、`.env.staging`)を加えることもできます。これにより、状況に応じて異なる環境変数のセットを使い分けられます。 |
| 86 | + |
| 87 | +`astro dev`と`astro build`コマンドは、それぞれデフォルトで`"development"`モードと`"production"`モードになります。これらのコマンドを[`--mode`フラグ](/ja/reference/cli-reference/#--mode-string)付きで実行すると、`mode`に別の値を渡し、対応する`.env`ファイルを読み込めます。 |
| 88 | + |
| 89 | +これにより、APIの接続先を変えて開発サーバーを起動したり、サイトをビルドしたりできます。 |
| 90 | + |
| 91 | +<PackageManagerTabs> |
| 92 | + <Fragment slot="npm"> |
| 93 | + ```shell |
| 94 | + # 「staging」APIに接続した状態で開発サーバーを起動する |
| 95 | + npm run astro dev -- --mode staging |
| 96 | + |
| 97 | + # 「production」APIに接続し、追加のデバッグ情報を含めてサイトをビルドする |
| 98 | + npm run astro build -- --devOutput |
| 99 | + |
| 100 | + # 「testing」APIに接続した状態でサイトをビルドする |
| 101 | + npm run astro build -- --mode testing |
| 102 | + ``` |
| 103 | + </Fragment> |
| 104 | + <Fragment slot="pnpm"> |
| 105 | + ```shell |
| 106 | + # 「staging」APIに接続した状態で開発サーバーを起動する |
| 107 | + pnpm astro dev --mode staging |
| 108 | + |
| 109 | + # 「production」APIに接続し、追加のデバッグ情報を含めてサイトをビルドする |
| 110 | + pnpm astro build --devOutput |
| 111 | + |
| 112 | + # 「testing」APIに接続した状態でサイトをビルドする |
| 113 | + pnpm astro build --mode testing |
| 114 | + ``` |
| 115 | + </Fragment> |
| 116 | + <Fragment slot="yarn"> |
| 117 | + ```shell |
| 118 | + # 「staging」APIに接続した状態で開発サーバーを起動する |
| 119 | + yarn astro dev --mode staging |
| 120 | + |
| 121 | + # 「production」APIに接続し、追加のデバッグ情報を含めてサイトをビルドする |
| 122 | + yarn astro build --devOutput |
| 123 | + |
| 124 | + # 「testing」APIに接続した状態でサイトをビルドする |
| 125 | + yarn astro build --mode testing |
| 126 | + ``` |
| 127 | + </Fragment> |
| 128 | +</PackageManagerTabs> |
| 129 | + |
| 130 | +`.env`ファイルの詳細については、[Viteのドキュメント](https://vite.dev/guide/env-and-mode.html#env-files)を参照してください。 |
| 131 | + |
| 132 | +### Astro設定ファイル内 |
| 133 | + |
| 134 | +Astroは、他のファイルを読み込む前に設定ファイルを評価します。そのため、`astro.config.mjs`内で`import.meta.env`を使って、`.env`ファイルに設定された環境変数にアクセスすることはできません。 |
| 135 | + |
| 136 | +設定ファイル内では、[CLIで設定した値](#cliを使う)など、その他の環境変数に`process.env`でアクセスできます。 |
| 137 | + |
| 138 | +また、[Viteの`loadEnv`ヘルパー](https://main.vite.dev/config/#using-environment-variables-in-config)を使って、`.env`ファイルを手動で読み込むことも可能です。 |
| 139 | + |
| 140 | +```js title="astro.config.mjs" |
| 141 | +import { loadEnv } from "vite"; |
| 142 | + |
| 143 | +const { SECRET_PASSWORD } = loadEnv(process.env.NODE_ENV, process.cwd(), ""); |
| 144 | +``` |
| 145 | + |
| 146 | +:::note |
| 147 | +`pnpm`では、プロジェクトに直接インストールされていないモジュールをインポートできません。`pnpm`を使っている場合は、`loadEnv`ヘルパーを使うために`vite`をインストールする必要があります。 |
| 148 | + |
| 149 | +```sh |
| 150 | +pnpm add -D vite |
| 151 | +``` |
| 152 | +::: |
| 153 | + |
| 154 | +### CLIを使う |
| 155 | + |
| 156 | +プロジェクトの実行時に環境変数を追加することもできます。 |
| 157 | + |
| 158 | +<PackageManagerTabs> |
| 159 | + <Fragment slot="yarn"> |
| 160 | + ```shell |
| 161 | + PUBLIC_POKEAPI=https://pokeapi.co/api/v2 yarn run dev |
| 162 | + ``` |
| 163 | + </Fragment> |
| 164 | + <Fragment slot="npm"> |
| 165 | + ```shell |
| 166 | + PUBLIC_POKEAPI=https://pokeapi.co/api/v2 npm run dev |
| 167 | + ``` |
| 168 | + </Fragment> |
| 169 | + <Fragment slot="pnpm"> |
| 170 | + ```shell |
| 171 | + PUBLIC_POKEAPI=https://pokeapi.co/api/v2 pnpm run dev |
| 172 | + ``` |
| 173 | + </Fragment> |
| 174 | +</PackageManagerTabs> |
| 175 | + |
| 176 | +## 環境変数を取得する |
| 177 | + |
| 178 | +Astroでは、環境変数へのアクセスに`process.env`ではなく、[ES2020で追加された`import.meta`機能](https://tc39.es/ecma262/2020/#prod-ImportMeta)を利用した`import.meta.env`を使います。 |
| 179 | + |
| 180 | +たとえば、`PUBLIC_POKEAPI`環境変数を取得するには`import.meta.env.PUBLIC_POKEAPI`を使います。 |
| 181 | + |
| 182 | +```js /(?<!//.*)import.meta.env.[A-Z_]+/ |
| 183 | +// import.meta.env.SSR === true のとき |
| 184 | +const data = await db(import.meta.env.DB_PASSWORD); |
| 185 | + |
| 186 | +// import.meta.env.SSR === false のとき |
| 187 | +const data = fetch(`${import.meta.env.PUBLIC_POKEAPI}/pokemon/squirtle`); |
| 188 | +``` |
| 189 | +
|
| 190 | +SSRを使う場合、環境変数は使用しているSSRアダプターに応じて実行時にアクセスできます。ほとんどのアダプターでは`process.env`で環境変数にアクセスできますが、一部のアダプターは動作が異なります。たとえばDenoアダプターでは`Deno.env.get()`を使います。Cloudflareアダプターを使う場合に環境変数を扱う方法については、[Cloudflareランタイムへのアクセス方法](/ja/guides/integrations-guide/cloudflare/#cloudflare-runtime)を参照してください。Astroはまずサーバー環境に変数があるか確認し、存在しない場合は`.env`ファイル内を探します。 |
| 191 | +
|
| 192 | +## 型安全な環境変数 |
| 193 | +
|
| 194 | +`astro:env` APIを使うと、[設定した環境変数](#環境変数を設定する)に対して型安全なスキーマを定義できます。これにより、各変数をサーバーとクライアントのどちらで利用できるようにするかを指定したり、データ型や追加のプロパティを定義したりできます。 |
| 195 | +
|
| 196 | +<ReadMore>アダプターを開発していますか?[アダプターを`astro:env`に対応させる方法](/ja/reference/adapter-reference/#envgetsecret)を参照してください。</ReadMore> |
| 197 | +
|
| 198 | +### 基本的な使い方 |
| 199 | +
|
| 200 | +#### スキーマを定義する |
| 201 | +
|
| 202 | +スキーマを設定するには、Astroの設定に`env.schema`オプションを追加します。 |
| 203 | +
|
| 204 | +```js title="astro.config.mjs" ins={4-8} |
| 205 | +import { defineConfig } from "astro/config"; |
| 206 | +
|
| 207 | +export default defineConfig({ |
| 208 | + env: { |
| 209 | + schema: { |
| 210 | + // ... |
| 211 | + } |
| 212 | + } |
| 213 | +}) |
| 214 | +``` |
| 215 | +
|
| 216 | +続いて、`envField`ヘルパーを使って[変数を文字列、数値、列挙型、真偽値として登録](#データ型)できます。各変数に`context`(`"client"`または`"server"`)と`access`(`"secret"`または`"public"`)を指定して[環境変数の種類](#変数の種類)を定義し、`optional`や`default`といった追加のプロパティをオブジェクトで渡します。 |
| 217 | +
|
| 218 | +```js title="astro.config.mjs" ins="envField" |
| 219 | +import { defineConfig, envField } from "astro/config"; |
| 220 | +
|
| 221 | +export default defineConfig({ |
| 222 | + env: { |
| 223 | + schema: { |
| 224 | + API_URL: envField.string({ context: "client", access: "public", optional: true }), |
| 225 | + PORT: envField.number({ context: "server", access: "public", default: 4321 }), |
| 226 | + API_SECRET: envField.string({ context: "server", access: "secret" }), |
| 227 | + } |
| 228 | + } |
| 229 | +}) |
| 230 | +``` |
| 231 | +
|
| 232 | +型は`astro dev`や`astro build`の実行時に自動生成されますが、`astro sync`を実行して型のみを生成することもできます。 |
| 233 | +
|
| 234 | +#### スキーマで定義した変数を使う |
| 235 | +
|
| 236 | +定義した変数を、`/client`または`/server`モジュールからインポートして使います。 |
| 237 | +
|
| 238 | +```astro |
| 239 | +--- |
| 240 | +import { API_URL } from "astro:env/client"; |
| 241 | +import { API_SECRET_TOKEN } from "astro:env/server"; |
| 242 | +
|
| 243 | +const data = await fetch(`${API_URL}/users`, { |
| 244 | + method: "GET", |
| 245 | + headers: { |
| 246 | + "Content-Type": "application/json", |
| 247 | + "Authorization": `Bearer ${API_SECRET_TOKEN}` |
| 248 | + }, |
| 249 | +}) |
| 250 | +--- |
| 251 | +
|
| 252 | +<script> |
| 253 | + import { API_URL } from "astro:env/client"; |
| 254 | + |
| 255 | + fetch(`${API_URL}/ping`) |
| 256 | +</script> |
| 257 | +``` |
| 258 | +
|
| 259 | +### 変数の種類 |
| 260 | +
|
| 261 | +環境変数には、スキーマで定義する`context`(`"client"`または`"server"`)と`access`(`"secret"`または`"public"`)の設定の組み合わせによって決まる、3つの種類があります: |
| 262 | +
|
| 263 | +- **パブリックなクライアント変数**: この変数は最終的なクライアントバンドルとサーバーバンドルの両方に含まれ、`astro:env/client`モジュールを通じてクライアントとサーバーの両方からアクセスできます。 |
| 264 | +
|
| 265 | + ```js |
| 266 | + import { API_URL } from "astro:env/client"; |
| 267 | + ``` |
| 268 | +
|
| 269 | +- **パブリックなサーバー変数**: この変数は最終的なサーバーバンドルに含まれ、`astro:env/server`モジュールを通じてサーバー上でアクセスできます。 |
| 270 | +
|
| 271 | + ```js |
| 272 | + import { PORT } from "astro:env/server"; |
| 273 | + ``` |
| 274 | +
|
| 275 | +- **シークレットサーバー変数**: この変数は最終的なバンドルには含まれず、`astro:env/server`モジュールを通じてサーバー上でアクセスできます。 |
| 276 | +
|
| 277 | + ```js |
| 278 | + import { API_SECRET } from "astro:env/server"; |
| 279 | + ``` |
| 280 | +
|
| 281 | + デフォルトでは、`astro:env/server`モジュールから何かがインポートされるたびに、すべてのシークレットが検証されます。つまり、インポートされていないシークレットも検証される場合があります。ビルド時にこの検証を満たすために、[ダミーの環境変数を渡す](#環境変数を設定する)必要があるかもしれません。 |
| 282 | +
|
| 283 | + また、[`validateSecrets: true`を設定](/ja/reference/configuration-reference/#envvalidatesecrets)することで、起動時にシークレットを検証するようにもできます。 |
| 284 | +
|
| 285 | +:::note |
| 286 | +**シークレットクライアント変数**は、データを安全にクライアントへ送信する方法がないためサポートされていません。したがって、スキーマで`context: "client"`と`access: "secret"`の両方を設定することはできません。 |
| 287 | +::: |
| 288 | +
|
| 289 | +### データ型 |
| 290 | +
|
| 291 | +現在、文字列、数値、列挙型、真偽値の4つのデータ型がサポートされています。 |
| 292 | +
|
| 293 | +```js |
| 294 | +import { envField } from "astro/config"; |
| 295 | +
|
| 296 | +envField.string({ |
| 297 | + // context と access |
| 298 | + optional: true, |
| 299 | + default: "foo", |
| 300 | +}) |
| 301 | +
|
| 302 | +envField.number({ |
| 303 | + // context と access |
| 304 | + optional: true, |
| 305 | + default: 15, |
| 306 | +}) |
| 307 | +
|
| 308 | +envField.boolean({ |
| 309 | + // context と access |
| 310 | + optional: true, |
| 311 | + default: true, |
| 312 | +}) |
| 313 | +
|
| 314 | +envField.enum({ |
| 315 | + // context と access |
| 316 | + values: ["foo", "bar", "baz"], |
| 317 | + optional: true, |
| 318 | + default: "baz", |
| 319 | +}) |
| 320 | +``` |
| 321 | +
|
| 322 | +<ReadMore>`envField`で指定できる検証用フィールドの完全な一覧については、[`envField` APIリファレンス](/ja/reference/modules/astro-config/#envfield)を参照してください。</ReadMore> |
| 323 | +
|
| 324 | +### シークレットを動的に取得する |
| 325 | +
|
| 326 | +スキーマを定義していても、特定のシークレットの生の値を取得したい場合や、スキーマで定義されていないシークレットを取得したい場合があります。そのような場合は、`astro:env/server`からエクスポートされている`getSecret()`を使えます。 |
| 327 | +
|
| 328 | +```js |
| 329 | +import { |
| 330 | + FOO, // boolean |
| 331 | + getSecret |
| 332 | +} from "astro:env/server"; |
| 333 | +
|
| 334 | +getSecret("FOO"); // string | undefined |
| 335 | +``` |
| 336 | +
|
| 337 | +<ReadMore>詳しくは[APIリファレンス](/ja/reference/modules/astro-env/#getsecret)を参照してください。</ReadMore> |
| 338 | +
|
| 339 | +### 制限事項 |
| 340 | +
|
| 341 | +`astro:env`は仮想モジュールであり、Astroコンテキスト内でのみ使えます。たとえば、以下の場所で使えます。 |
| 342 | +
|
| 343 | +- ミドルウェア |
| 344 | +- Astroのルートとエンドポイント |
| 345 | +- Astroコンポーネント |
| 346 | +- フレームワークコンポーネント |
| 347 | +- モジュール |
| 348 | +
|
| 349 | +以下の場所では利用できないため、`process.env`を使う必要があります。 |
| 350 | +
|
| 351 | +- `astro.config.mjs` |
| 352 | +- スクリプト |
0 commit comments