Vite 環境で index.html から環境変数を参照する

2022.08.23

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

.env の変数(例:環境別のタグなど)を index.html から参照したい場合、Webpack を利用した環境だと何もしなくても読み込めるのですが、Vite を利用している場合だと少し頑張る必要があります。

参考 Issue:Accessing env variables from index.html #3105

検証環境

  • React v18.2.0
  • Vite v3.0.7

雛形を作成

以下の内容で新規プロジェクトを作成します。

npm create vite@latest

✔ Project name: … my-vite-project
✔ Select a framework: › react
✔ Select a variant: › react-ts

.env ファイルを作成

次にルートディレクトリに.env ファイルを作成します。

VITE_MY_TITLE='環境変数だよ'

Vite のお作法に則ってVITE_で始まる変数を定義します。

環境変数が誤ってクライアントに漏れてしまうことを防ぐために、VITE_ から始まる変数のみが Vite で処理されたコードに公開されます。

このままアプリのコンポーネント、index.html から参照してみましょう。 App.tsxindex.html をそれぞれ以下のように変更します。

App.tsx

import {useState} from "react";
import "./App.css";

function App() {
  const [count, setCount] = useState(0);

  return (
    <div className="App">
      <h1>{import.meta.env.VITE_MY_TITLE}</h1>
    </div>
  );
}

export default App;

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script>
      const title = import.meta.env.VITE_MY_TITLE
    </script>
    <title>${title}</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

App.tsx からは問題なく読み込めますが、index.html からは読み込まれずに以下のエラーが起こります

Uncaught SyntaxError: Cannot use 'import.meta' outside a module

関数を定義して Vite のプラグインとして読み込ませる

Issueのコメントにあった解決方法を参考に vite.config.tsを以下のように更新します。

import {defineConfig, loadEnv} from "vite";
import react from "@vitejs/plugin-react";

// https://vitejs.dev/config/
export default defineConfig(({mode}) => {
  return {
    plugins: [react(), htmlPlugin(loadEnv(mode, "."))],
  };
});

/**
 * Replace env variables in index.html
 * @see https://github.com/vitejs/vite/issues/3105#issuecomment-939703781
 * @example `%VITE_MY_ENV%`
 * @see https://vitejs.dev/guide/api-plugin.html#transformindexhtml
 */
function htmlPlugin(env: ReturnType<typeof loadEnv>) {
  return {
    name: "html-transform",
    transformIndexHtml: {
      enforce: "pre" as const,
      transform: (html: string): string =>
        html.replace(/%(.*?)%/g, (match, p1) => env[p1] ?? match),
    },
  };
}

結果

index.html から%<VITE_YOUR_VARIABLE>%の形式で環境変数を読み込みます。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <title>%VITE_MY_TITLE%</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

コンソールのエラーが消えて index.html から環境変数が参照できたことが確認できれば OK です。

参考