How to send ENV variables from backend server to javascript in the browser

This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the javascript category.

Last Updated: 2024-03-05

Sometimes some variables in I need in JavaScript are only known when the backend is serving pages. Therefore I need a way to sync environment variables between my backend and JavaScript running in the browser. I did this via a window.env object:

<script>
  window.env = {
    enviroment: '{{ env('APP_ENV') }}',
    stripePublicKey: '{{ env('STRIPE_KEY') }}',
    debug: '{{ env('APP_DEBUG') }}',
    baseUrl: '{{ env('APP_URL') }}',
    apiUrl: '{{ env('APP_URL') }}/api/v1'
  }
</script>

Note some drawbacks: This environment won't be available immediately (compared to placing variables in an ES6 import). Therefore you need to wait until page load then take certain actions. For example imagine you wrote the following JavaScript:

function loadStripe() {
  doSomethingWith(window.env.stripePublicKey)
}

// Imagine then this was called at top-level in some ES6 file:
loadStripe()

The issue is that the window.env is not available at import, therefore window.env.debug wasn't available either. This would not have happened with "true" environment variables, since they are ready from the time the process began.

The fix, given the current system would be a nil check - i.e. something like this:

function loadStripe(locale) {
  window.env && doSomethingWith(window.env.stripePublicKey)
}