storybook: Unable to set environment variables
Describe the bug
I’m setting up my project to use env-cmd to set environment variables using different .env.{environment} files (ex. .env.dev, .env.staging, etc). Unfortunately storybook isn’t loading my environment variables. I’ve also tried setting environment variables in the command when running start-storybook (ex. REACT_APP_TEST_VAR=testing start-storybook -p 9009 -s public), and storybook isn’t picking up that environment variable either.
To Reproduce
Steps to reproduce the behavior:
Setting env vars in the command:
- Add
console.log(process.env.REACT_APP_TEST_VAR)to a js story file - Run
REACT_APP_TEST_VAR=testing start-storybook -p 9009 -s public - In the console, you should see
undefined
Setting env vars with env-cmd:
- Install
env-cmd(ex.yarn add env-cmd) - Add
console.log(process.env.REACT_APP_TEST_VAR)to a js story file - Create a
.env.devfile in the same directory aspackage.jsonthat has the lineREACT_APP_TEST_VAR=testing - Run
env-cmd -f .env.dev start-storybook -p 9009 -s public - In the console, you should see
undefined
Expected behavior
I expect process.env.REACT_APP_TEST_VAR to be set to testing, and for testing to get logged out in the console.
System:
Environment Info:
System: OS: macOS 10.15.6 CPU: (12) x64 Intel® Core™ i7-9750H CPU @ 2.60GHz Binaries: Node: 13.12.0 - ~/.nvm/versions/node/v13.12.0/bin/node Yarn: 1.19.1 - /usr/local/bin/yarn npm: 6.14.4 - ~/.nvm/versions/node/v13.12.0/bin/npm Browsers: Chrome: 84.0.4147.135 Safari: 13.1.2 npmPackages: @storybook/preset-create-react-app: ^3.1.4 => 3.1.4 @storybook/react: ^6.0.6 => 6.0.7
Additional context
A similar issue was brought up in https://github.com/storybookjs/storybook/issues/5166, which is now closed.
About this issue
- Original URL
- State: open
- Created 4 years ago
- Reactions: 23
- Comments: 21 (4 by maintainers)
But my application components already expect a given set of environment variables to be present, and not prefixed with
STORYBOOK_, I shouldn’t need to change my application code to point to different variables depending on the environment. Is there any workaround for this?Why should Storybook deal with the security of my application? It my responsibility to provide a safe environment and not expose unwanted data, and I could still leak sensitive data in a millon ways, for example by prefixing every environment variable with
STORYBOOK_in a script / webpack config like many people are currently doing to bypass this. You could also turn this off by default but have a configuration flag to forward variables with a warning, but please don’t block my workflow because it may possibly be a security issueHad the same problem as federicom-scale and FrederickEngelhardt (Wanting to use the env variables my code already uses)
So the “problem” is https://github.com/storybookjs/storybook/blob/188e52c1dbc95bd19600a966a7fdd79c89511bae/lib/core/src/server/config/utils.ts#L53 filters everything that does not start with
STORYBOOK_. (I get shilmans point to wipe away all the env variables that are initially present, like$HOME,$PATHand about 100 others – but it would still be nice to have some control over the process / the result).Anyways, the iframe-webpack.config.ts overwrites
process.env, so my dirty solution to add vars afterwards is:.storybook/main.jsMaybe it helps someone.
I think this line:
https://github.com/storybookjs/storybook/blob/188e52c1dbc95bd19600a966a7fdd79c89511bae/lib/core/src/server/config/utils.ts#L53
should not be hardcoded. There should be a config prop that allows us to pass string or array of strings (or even custom regular expressions) that define what variables should be whitelisted. For instance, NextJS already does the same, whitelists all variables that start with
NEXT_PUBLIC_. CRA does it for variables that start withREACT_APP_.Seems a bit redundant to create a separate
.envfile or duplicate variables with different names inside same.envfile just to get over this hump. A workaround can be implemented, but that shouldn’t be considered a long term solution.This looks tedious to maintain on a project with a lot of env variables:
It’s a security issue to make all environment variables available in your frontend code. Since Storybook supports a wide variety of environments, should we support every possible prefix?
I’ve repurposed the above into what I feel is a cleaner solution.
In my
.storybookdirectory, I created a.env.storybookfile with my desired env vars. To parse this file, I used thedotenvpackage:npm i -D dotenvoryarn add --dev dotenv.Then, in my
main.jsfile:FYI comments and spacing etc is to keep things clear and separate as per my own config file, which has a lot of other stuff going on. Hope this helps someone! 😃
Just spent an hour or so fighting with a combination of this and https://github.com/storybookjs/storybook/issues/17336
This is a combination that appears to work with
core.builder = 'webpack5'. As a bonus it fixes the empty env issue from 17336Note: Set up to inject NEXT_PUBLIC_ currently
Something here seems fundamentally wrong.
With storybook 6.3.12, all of the environment vars with the REACT_PREFIX in my various .env.* files are available inside my components. In 6.4.13, they are all undefined.
If we have to prefix stuff with REACT_APP so that a CRA build can make them available to the code that we’re trying to test, it really doesn’t help to have storybook filter them all out.
For me I wanted to have an env to know that I’m building for Storybook. I ended up setting in it
.storybook/main.js. docs for env varsand accessing it with
process.env.STORYBOOK_ENVSmall tweak to @maxbeier’s script above. Important thing is to remember to return the config.
Hussshhhh! Finally I’m able to inject environment variables from my
.env-cmdrcfile (I’m using env-cmdrc, storybook 7.4).If anyone is still struggling & want to inject the original environment vars (WITHOUT ADDING STORYBOOK_), this post may help you.
Please follow below steps -
"storybook": "env-cmd -e local storybook dev -p 6006",.env-cmdrcinsideenvprop in main.ts (document ref). We just need to append them intoenvthe following way -env: config => ({ ...config, ...injectVars }),WhereinjectVarsis the function where I collected my specific environment variables which containREACT_APP_prefix -const injectVars = Object.keys(process.env).reduce((c, key) => { if (/^REACT_APP_/.test(key)) { c[key] = process.env[key]; } return c; }, {});That’s it. Now I get access my environment variables using
process.env.<variable_name>.Thanks @joeswann & everyone for the references
If you want separate
developmentvsproductionenv var files (as I’ve just realised I need), here’s how I did that:Similar to the above, using the
dotenvpackage - but instead of the one.env.storybookfile, I’ve got two separate env files in my.storybookdir now: the standard.env.developmentand.env.production.Code: