Parcel: [feature] Use environment variables inside the HTML

Created on 17 Apr 2018  Â·  10Comments  Â·  Source: parcel-bundler/parcel

🙋 feature request!

First thing first: Thanks for the nice work ! :+1:

I have a use case where an anchor tag redirects to an external URL based on the environment (localhost:3333 if in DEV for instance and https://whatever.com in PROD).

Therefore, it would be really convenient to be able to use the environment variables directly inside the index.html without going through any javascript code.

Just like this : <a href=%MY_ENV_VARIABLE%>Ok</a>

The % are used randomly just to show some kind of formatting to handle ENV variables at build time.

Maybe I have missed something but I was not able to find any kind of documentation or issues (open or close) dealing with this kind of things. Maybe I'm totally missing something but with this type of use cases, this feature would be very convenient.

Help Wanted Feature

Most helpful comment

If you’re using something that runs JS (like react) as mentioned you can just reference process.env in your code. However, I was able to get environment variables within my regular HTML files using PostHTML with the following steps:

  1. Set some environment variables, e.g., I created .env.development in the root of my project as such:

    HOME_URL=/index.html
    
  2. Add the posthtml-expressions library:

    yarn add -D posthtml-expressions
    
  3. Add a posthtml config file—important that it’s a JS file and not just JSON—posthtml.config.js (the reason for using these as JS files is not really documented currently, but the ability to access process.env here is why I’m using it):

    module.exports = {
      plugins: {
        "posthtml-expressions": {
          locals: {
            HOME_URL: process.env.HOME_URL
          }
        }
      }
    };
    
  4. Update my HTML to use the posthtml-expressions syntax:

    <a href="{{ HOME_URL || '/' }}">home</a>
    
  5. In order to try it out in dev yarn start and to build it for production yarn build taking into account different environments, I have the following in my package.json:

    {
      "scripts": {
        "start": "yarn parcel src/*.html",
        "build": "NODE_ENV=prod parcel build --public-url ./ src/index.html",
      }
    }
    

And voila, you have environment variables reflected in your HTML.

Also, one gotcha: I’m not seeing changes to .env triggering a re-build. You’ll have to edit something to trigger a re-build or stop parcel, rm -r .cache, and then start parcel.


@breier in your example, are you using some extra asset-type handler to handle that ruby syntax <%= … %>?

All 10 comments

+1

We would like to use different favicons to signify our dev environment versus our production environment so that when we have many tabs open, it's easy to pick out where you're looking. Having access to an env variable in the HTML would allow us to do this easily.

Would also be useful for additional script tags (service worker, Google analytics, etc) that you don't need when developing/designing your app; but obviously need when deployed.

I _think_ this could be resolved by allowing the entry point to be a template file like Handlebars, EJS, or Pug. Parcel automatically sets the NODE_ENV to production which could be passed to the template at build time.

Those of us coming from Webpack got used to html-webpack-plugin, so it would be great to see Parcel incorporate similar functionality, while still maintaining the exceptional developer experience it offers over Webpack.

UPDATE:

This is actually already supported. I created a simple example using Pug. You do have to npm add -D pug.

index.pug

doctype html
html(lang='en')
  head
    meta(charset='utf-8')
    meta(name='viewport', content='width=device-width, initial-scale=1, shrink-to-fit=no')
    title Parcel
  body
    if process.env.NODE_ENV === 'production'
      h1 PRODUCTION
    else
      h1 DEVELOPMENT

Running parcel build index.pug will generate the following index.html:

dist/index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Parcel</title>
  </head>
  <body>
    <h1>PRODUCTION</h1>
  </body>
</html>

Therefor, to resolve @GaelS 's issue, you could do something like this:

body
  a(href=process.env.LINK_HREF) Ok
LINK_HREF='http://example.com' parcel build index.pug
<body>
  <a href="http://example.com">Ok</a>
<body>

Pretty cool and still zero config :+1:

You can use <%= MY_ENV_VAR %> syntax.

The example bellow uses VUE_APP_TITLE variable that I set in my .env files and BASE_URL that's a system environment variable.

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= VUE_APP_TITLE %></title>
</head>

If you’re using something that runs JS (like react) as mentioned you can just reference process.env in your code. However, I was able to get environment variables within my regular HTML files using PostHTML with the following steps:

  1. Set some environment variables, e.g., I created .env.development in the root of my project as such:

    HOME_URL=/index.html
    
  2. Add the posthtml-expressions library:

    yarn add -D posthtml-expressions
    
  3. Add a posthtml config file—important that it’s a JS file and not just JSON—posthtml.config.js (the reason for using these as JS files is not really documented currently, but the ability to access process.env here is why I’m using it):

    module.exports = {
      plugins: {
        "posthtml-expressions": {
          locals: {
            HOME_URL: process.env.HOME_URL
          }
        }
      }
    };
    
  4. Update my HTML to use the posthtml-expressions syntax:

    <a href="{{ HOME_URL || '/' }}">home</a>
    
  5. In order to try it out in dev yarn start and to build it for production yarn build taking into account different environments, I have the following in my package.json:

    {
      "scripts": {
        "start": "yarn parcel src/*.html",
        "build": "NODE_ENV=prod parcel build --public-url ./ src/index.html",
      }
    }
    

And voila, you have environment variables reflected in your HTML.

Also, one gotcha: I’m not seeing changes to .env triggering a re-build. You’ll have to edit something to trigger a re-build or stop parcel, rm -r .cache, and then start parcel.


@breier in your example, are you using some extra asset-type handler to handle that ruby syntax <%= … %>?

@mrcoles I've used vue-cli to start a project using webpack template. No additions.

This isn't something we'll support out of the box since it isn't standard HTML syntax. But you could easily use a PostHTML plugin for this, or another template language like Pug.

@mrcoles I've used vue-cli to start a project using webpack template. No additions.

@breier Are you using the vue cli to have process.env available? If so, how? Thanks

is it HOME_URL or HOME_PATH?

@dandv, sorry that was a typo, I updated my comment so all HOME_PATH references are HOME_URL. Of course, feel free to use any variable names you want in your code :shipit:

@mrcoles I've used vue-cli to start a project using webpack template. No additions.

@breier Are you using the vue cli to have process.env available? If so, how? Thanks

Sorry for the really late reply, but for the record, here it is...
https://cli.vuejs.org/guide/mode-and-env.html#environment-variables

Note that only NODE_ENV, BASE_URL, and variables that start with VUE_APP_ will be statically embedded into the client bundle with webpack.DefinePlugin. It is to avoid accidentally exposing a private key on the machine that could have the same name.

Basically, any custom env var just have to start with VUE_APP_ in order to be auto loaded and assimilated.

I hope it helps someone ;)

@mrcoles, were you able to use NODE_ENV though?
It seems to be set to production regardless of what's used.

posthtml.config.js

console.log(process.env.NODE_ENV)
module.expors = {};
$ npx parcel --version
2.0.0-nightly.462
$ NODE_ENV=test npx parcel build --no-cache index.html
console: production
â ¸ Building index.html...

If you’re using something that runs JS (like react) as mentioned you can just reference process.env in your code. However, I was able to get environment variables within my regular HTML files using PostHTML with the following steps:
3. Add a posthtml config file—important that it’s a JS file and not just JSON—posthtml.config.js (the reason for using these as JS files is not really documented currently, but the ability to access process.env here is why I’m using it):
js module.exports = { plugins: { "posthtml-expressions": { locals: { HOME_URL: process.env.HOME_URL } } } };

Was this page helpful?
0 / 5 - 0 ratings