question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Accessing env variables from index.html

See original GitHub issue

Describe the bug

I try to insert html tag by environment variable condition and use vite-plugin-html for it. But Vite behaviour is weird

Reproduction

https://github.com/xSorc/test-vite-index-env

This code works only in build

<% if (import.meta.env.VITE_SHOW_TAG === '1') { %>
  works
<% } %>

During server i have this error

[vite] Internal server error: Cannot use 'import.meta' outside a module while compiling ejs
If the above error is not helpful, you may want to try EJS-Lint:
https://github.com/RyanZim/EJS-Lint
Or, if you meant to create an async function, pass `async: true` as an option.

This code works only in dev server

// vite.config.ts
require('dotenv').config();
// index.html
<% if (process.env.VITE_SHOW_TAG === '1') { %>
  works
<% } %>

But during build this doesn’t work, because Vite replace process.env with this:

<% if (({}).VITE_SHOW_TAG === '1') { %>
  works
<% } %>
  1. The only option that works in both server and build is this:
// vite.config.ts
require('dotenv').config();
// index.html
<% if (process.env['VITE_SHOW_TAG'] === '1') { %>
  works
<% } %>

I suppose that first or second variant should works

System Info

Output of npx envinfo --system --npmPackages vite,@vitejs/plugin-vue --binaries --browsers:

  System:
    OS: Windows 10 10.0.19042
    CPU: (6) x64 Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz
    Memory: 9.13 GB / 15.94 GB
  Binaries:
    Node: 14.15.3 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.10 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 6.14.9 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Spartan (44.19041.423.0), Chromium (90.0.818.42)
    Internet Explorer: 11.0.19041.1
  npmPackages:
    vite: 2.2.1 => 2.2.1

Used package manager:


Before submitting the issue, please make sure you do the following

  • Read the Contributing Guidelines.
  • Read the docs.
  • Check that there isn’t already an issue that reports the same bug to avoid creating a duplicate.
  • Provide a description in this issue that describes the bug.
  • Make sure this is a Vite issue and not a framework-specific issue. For example, if it’s a Vue SFC related bug, it should likely be reported to https://github.com/vuejs/vue-next instead.
  • Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:14
  • Comments:30 (6 by maintainers)

github_iconTop GitHub Comments

37reactions
piotr-czcommented, Dec 22, 2021

Update: using enfocre: 'pre' inside plugin worked. Full code:

// vite.config.ts
import { defineConfig, loadEnv } from 'vite'

export default defineConfig(({ mode }) => ({
  plugins: [
    htmlPlugin(loadEnv(mode, '.')),
  ]
}))

/**
 * Replace env variables in index.html
 * @see https://github.com/vitejs/vite/issues/3105#issuecomment-939703781
 * @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
        ),
    }
  }
}
27reactions
nightahcommented, Oct 11, 2021

Okay so I’ve got to the bottom of this, the consumption of the quotes isn’t a Vite issue, it’s a problem that manifests from vite-plugin-html.

If I don’t use that plugin Vite’s output of the index.html post-production build is identical with the input index.html.

For clarity here’s an output index.html with vite-plugin-html performing env replacements with EJS tags:

<!doctype html><html lang=en><head><base href={{.BaseURL}}><meta property=csp-nonce content={{.CSPNonce}} /><meta charset=utf-8 /><meta name=viewport content="width=device-width,initial-scale=1"/><meta name=theme-color content=#000000 /><meta name=description content="Authelia login portal for your apps"/><link rel=manifest href=./manifest.json /><link rel=icon href=./favicon.ico /><title>Login - Authelia</title><script type=module crossorigin src=./static/js/index.829172be.js></script><link rel=modulepreload href=./static/js/vendor.d0bc79df.js><link rel=stylesheet href=./static/css/index.393eb37d.css></head><body data-basepath={{.Base}} data-rememberme={{.RememberMe}} data-resetpassword={{.ResetPassword}} data-theme={{.Theme}}><noscript>You need to enable JavaScript to run this app.</noscript><div id=root></div></body></html>

You’ll notice in the above extract that almost all sets of double quotes "" have been consumed along with the transformation.

Output with Vite and the transformIndexHtml Vite hook performing env replacements per solution described further down:

<!DOCTYPE html>
<html lang="en">

<head>
  <base href="{{.BaseURL}}">
  <meta property="csp-nonce" content="{{.CSPNonce}}" />
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta name="theme-color" content="#000000" />
  <meta name="description" content="Authelia login portal for your apps" />
  <link rel="manifest" href="./manifest.json" />
  <link rel="icon" href="./favicon.ico" />
  <title>Login - Authelia</title>
  <script type="module" crossorigin src="./static/js/index.dd4afd07.js"></script>
  <link rel="modulepreload" href="./static/js/vendor.88e06a7b.js">
  <link rel="stylesheet" href="./static/css/index.6d03b4c9.css">
</head>

<body data-basepath="{{.Base}}" data-rememberme="{{.RememberMe}}" data-resetpassword="{{.ResetPassword}}" data-theme="{{.Theme}}">
  <noscript>You need to enable JavaScript to run this app.</noscript>
  <div id="root"></div>
  
</body>

</html>

For those that are looking at a solution similar to CRA or others where you can just template %VARNAME% in your index.html and have it replaced during the dev server and production builds you can use the following which leverages part of what @cosmith provided above along with Vite’s transformIndexHtml hook:

import {defineConfig, loadEnv} from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
import reactRefresh from "@vitejs/plugin-react-refresh";

export default defineConfig(({mode}) => {
    const env = loadEnv(mode, "env");

    const htmlPlugin = () => {
        return {
            name: "html-transform",
            transformIndexHtml(html: string) {
                return html.replace(/%(.*?)%/g, function (match, p1) {
                    return env[p1];
                });
            },
        };
    };

    return {
        plugins: [htmlPlugin(), reactRefresh(), tsconfigPaths()],
    };
});

Just remember that only variables that are prefixed with VITE_ are passed across as per the Vite documentation.

@idleberg feel free to give this a try and let me know if it resolves your problem.

Read more comments on GitHub >

github_iconTop Results From Across the Web

[Tips] How to Access Environment Variables Stored in .env ...
My current project required to embed Google Analytics tags in React project's index.html for two different environments, ...
Read more >
Create React App: using environment variables in index.html
I use .env variables for the meta title of a site with various language versions of the build: <title>%REACT_APP_SITE_TITLE%</title>.
Read more >
Replace Environment Variables In Your Index.html - Medium
Add Variable In Index.html. Before implementing the script to update the variable per se, let's first add a variable in our index.html ....
Read more >
How Can I Access Environment Variables in My Static Website?
Then in your html or js files you can access the variables using the process.env. prefix. Like this. <html> <body> hello </body> ...
Read more >
How to import environment variable in html and js files
And I have another JS file builder.js where I am setting env variable like this: // var envURL = "http://localhost:8080"; var envURL =...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found