bit
bit copied to clipboard
Environment variables
Description
Environment variables are not loading into process during run app or preview.
Specifications
- Bit version: 0.0.792
- Node version: v16.16.0
- npm / yarn version: yarn -v 1.22.19
- Platform: OSx Monterey
- Bit compiler (include version): ?
- Bit tester (include version): ?
Context and additional information
Using an existing mono-repo, trying to convert it into small bits. But I can not load env vars from the host app (that contains all the other bit components). All of my components are teambit/react.
which env-vars you refer? variables defined in the node process and your app can't access?
Yap.
environment variables ( like: REACT_APP_SOME_API_KEY=a12m3234fjdp-xx#5) aren't being loaded from .env, but is not avilable also if i run export REACT_APP_SOME_API_KEY=a12m3234fjdp-xx#5 && bit run app_compnenet_path (or bit start).
Is there a best practice of loading environment variables into apps so this code could will load the correct value instead of undfined?
process.env.REACT_APP_SOME_API_KEY
@itaymendel Here is a git repo that helps to understand the problem: https://github.com/amitrahav/bit-load-env-reproduce
Same issue here. Any updates?
Hello, same issue here, any updates pls ? Cannot access .env variables through process.env !
The best way to go is probably to create a build task that will inject these vars. If it's something you configure for production then it should be set on Netlify or wherever you deploy. If you need it for the devserver, you shouldn't be using the process.env because it doesn't run on node.
@NitsanCohen770 can you suggest an alternative to env vars that works in Bit? I tried setting up a custom env with a webpack config transformation to inject the variables into the process.env object but this does not seem to work.
function commonTransformation(config: WebpackConfigMutator, _context: WebpackConfigTransformContext) {
config.addPlugin(
new webpack.EnvironmentPlugin( { REACT_ENV_HELLO: "HELLO FROM WEBPACK" } )
)
return config;
}
Edit:
After a few restarts and changing webpack.EnvironmentPlugin to webpack.DefinePlugin I got the above to work.
Hello, same issue here. I have checked the documentation and nothing about environment variables.
I managed to hack together a solution that I think may be using an old version of a custom React bit env but it's working for me.
The solution below uses a namespace id to filter only required environment variables.
The env file looks like this
PROJECT_NAMESPACE=MY_PROJECT
MY_PROJECT_api_port=1234
MY_PROJECT_api_host=4567
OTHER_VAR=foo
In this file only variables with MY_PROJECT prefix will be injected with Webpack.
I have this inside of react-env-custom.main.runtime.ts
import { ReactEnvCustomAspect } from './react-env-custom.aspect';
import { EnvsAspect, EnvsMain } from '@teambit/envs';
import { ReactAspect, ReactMain } from '@teambit/react';
import { MainRuntime } from '@teambit/cli';
import {
WebpackConfigTransformer,
WebpackConfigMutator,
WebpackConfigTransformContext,
} from '@teambit/webpack';
/**
* Transformation to apply for both preview and dev server
* @param config
* @param _context
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function commonTransformation(
config: WebpackConfigMutator,
_context: WebpackConfigTransformContext
) {
const webpack = require('webpack');
if (process.env.NODE_ENV !== 'production') {
const filteredEnv = Object.keys(process.env).reduce((acc, key) => {
if (
process.env.PROJECT_NAMESPACE?.split(',').some((prefix) => {
return key.startsWith(prefix);
})
) {
acc[key] = process.env[key];
}
return acc;
}, {});
config.addPlugin(
new webpack.DefinePlugin({
'process.env': JSON.stringify(filteredEnv),
})
);
} else {
// TODO: Find safe way of injecting env vars into production build
}
return config;
}
/**
* Transformation for the preview only
* @param config
* @param context
* @returns
*/
export const previewConfigTransformer: WebpackConfigTransformer = (
config: WebpackConfigMutator,
context: WebpackConfigTransformContext
) => {
const newConfig = commonTransformation(config, context);
return newConfig;
};
export class ReactEnvCustomMain {
static slots = [];
static dependencies = [ReactAspect, EnvsAspect];
static runtime = MainRuntime;
static async provider([react, envs]: [ReactMain, EnvsMain]) {
const webpackModifiers = {
previewConfig: [previewConfigTransformer],
devServerConfig: [devServerConfigTransformer],
};
const ReactEnvCustomEnv = react.compose([
react.useWebpack(webpackModifiers),
]);
envs.registerEnv(ReactEnvCustomEnv);
return new ReactEnvCustomMain();
}
}
ReactEnvCustomAspect.addRuntime(ReactEnvCustomMain);
Thanks for sharing @sbland! That code looks very useful. I noticed it doesn't define the devServerConfigTransformer function - is there any additional special logic we'd need to be aware of in that function beyond what's visible in the commonTransformation function? Thanks again!
@coreyaus my devServerConfigTransformer looks exactly the same as previewConfigTransformer
export const devServerConfigTransformer: WebpackConfigTransformer = (
config: WebpackConfigMutator,
context: WebpackConfigTransformContext
) => {
const newConfig = commonTransformation(config, context);
return newConfig;
};
I want to add a environment variable can someone help me by providing a simple step by step procedure.
@Jagadishvg create a react environment by following the steps here: https://bit.dev/docs/react-env/set-up-your-env/ making sure to assign the env to your component.
Then in my-custom-env/config/webpack.config.ts add the following...
import type {
WebpackConfigMutator,
WebpackConfigTransformContext,
} from '@teambit/webpack';
/**
* modifies the webpack config for the components preview bundle.
* @see https://bit.dev/reference/webpack/webpack-config
*/
export const webpackTransformer = (
config: WebpackConfigMutator,
_context: WebpackConfigTransformContext
): WebpackConfigMutator => {
const webpack = require('webpack');
if (process.env.NODE_ENV !== 'production') {
const filteredEnv = Object.keys(process.env).reduce((acc: any, key: string) => {
if (
process.env.PROJECT_NAMESPACE?.split(',').some((prefix) => {
return key.startsWith(prefix);
})
) {
acc[key] = process.env[key];
}
return acc;
}, {});
config.addPlugin(
new webpack.DefinePlugin({
'process.env': JSON.stringify(filteredEnv),
})
);
} else {
// TODO: Find safe way of injecting env vars into production build
}
return config;
};
Then create an .env file in the root dir like below...
PROJECT_NAMESPACE=MY_PROJECT
MY_PROJECT_api_port=1234
MY_PROJECT_api_host=4567
If your using ReactEnv instead of ReactMain (I think this must have been a doc change at some point?) you can implement as below.
import { ReactEnv } from '@teambit/react.react-env';
import { webpackTransformer } from './config/webpack.config.js';
import { EnvHandler } from '@teambit/envs';
import { ReactPreview } from '@teambit/preview.react-preview';
import { Preview } from '@teambit/preview';
import hostDependencies from './preview/host-dependencies.js';
export class ReactEnvCustom extends ReactEnv {
protected previewMounter = require.resolve('./preview/mounter');
/**
* create an instance for Bit Preview.
*/
preview(): EnvHandler<Preview> {
return ReactPreview.from({
// TODO: Add webpack here
transformers: [
webpackTransformer,
],
mounter: this.previewMounter,
hostDependencies,
});
}
}