Azure environment variables only available inside server.js - reactjs

Trying to setup React app deployed by Azure Devops to use environment variables from Azure.
The command run to start the application is
pm2 start server.js
Within server.js I have added some logging...
console.log(process.env);
This dumps out all the env variables as you would expect (including those set in Azure).
When I attempt to use the same environment variables elsewhere, they are undefined. The files I'm attempting to access the environment variables are in typescript files, and I'm attempting to access them using process.env.MY_VAR.

If you run a process in the context of a build or release, it has access to the environment variables that are defined in the build/release. If you run it elsewhere, it doesn't. Because it's a different environment, and nothing is setting those environment variables. If you want those environment variables set, you need to set them.
In an Azure app service, the correct place is in the App Settings section of your app service. You can use an ARM template to deploy your app service and configure the app settings, or you can set the app settings directly while deploying with the App Service Deploy task.

Related

How to access the environment variables in Amazon S3 for the react application as I have stored the Firebase and Google Api Key in env variables?

REACT_APP_API_KEY=**
REACT_APP_FIREBASE_API_KEY=**
Using in the below style in react js for local environment :
process.env.REACT_APP_FIREBASE_API_KEY
Note : I am using aws code pipeline and code build for ci /cd.
In Code Build you can edit the Environment and add environmental variables. Click Additional configuration in the console to see it. You can export REACT_APP_FIREBASE_API_KEY there and you it should be picked up by npm run build.
You could also use an .env.production file and commit it to source code. These aren't secrets, are added to the deployed code, so there shouldn't be a security issue.

Consume Cloud Run environment variables inside Nextjs app

I've recently built a Nextjs app, which I am hosting on Google Cloud Run.
My app makes some requests to external APIs from the getStaticProps() method.
I would like to be able to point to a different API host depending on the environment (e.g prod or dev) using environment variables which would be set differently for each environment.
I know I can store these variables in environment specific files like .env.development and .env.production however I would like to be able to store these environment variables in the environment variables field in the Google Cloud console for the cloud run service and skip storing them in the files altogether.
I have tried adding in the variables to Cloud Run, but it does not work. I have also tried prefixing the variables with NEXT_PUBLIC_... With no luck.
Did anyone have any tips on how to accomplish this?
Ok... I think I have figured it out now.
I was using Cloud Builds to build my container, and the container runs npm run build before it runs npm run start.
I assume that my Cloud Run variables aren't available at the point in time when Cloud Build is building the project.
So, I think my solution is prob to try and inject the variables at the point when it is building, using substitution variables.
EDIT: Confirmed. If I start Nextjs in dev mode, such that the page is rendered on the server for each request, then the Cloud Run environment variables are used.
To build the Nextjs app for production, I include the environment variables in the Dockerfile that is built by Cloud Build
EDIT: as request, an example of a dockerfile setting the environment variable:
FROM node:16.13-alpine
RUN mkdir -p /usr/src
WORKDIR /usr/src
COPY . /usr/src
ENV NEXT_PUBLIC_MY_API_HOST='https://some.host.com'
RUN npm install -only=production
RUN npm run build
EXPOSE 3000
CMD npm run start
Then you can just reference the environment variable from within your code using process.env.NEXT_PUBLIC_MY_API_HOST

Using create-react-app hosted on S3 to hit a Heroku API

Backgroud
The backend is a Rails API-only app running on Heroku (on port 5000 during local development).
The frontend is made with create-react-app and is hosted in an S3 bucket behind AWS CloudFront (on port 3000 during local development).
Development Setup
Locally, the frontend's package.json includes:
"proxy": "http://localhost:5000",
This lets me run a Javascript command like…
await fetch(`/someEndpoint`)
…and the development server running on localhost:3000 forwards the response from http://localhost:5000/someEndpoint. This works great and my frontend processes the responses successfully 👍.
Production Issues
Now I'm running on production.
If I change nothing, the same line will try to load from https://asdfasdfasdf.cloudfront.net/someEndpoint which will 404.
Instead I want to configure the app so that in production it will hit the Heroku app https://my-awesome-rails-app.herokuapp.com/someEndpoint where the Rails API is running.
Questions
(1) Is what I want possible without changing the code
await fetch(`/someEndpoint`)
either by configuring the frontend to use my-awesome-rails-app.herokuapp.com, or by configuring CloudFront to forward some requests to S3 and others to Heroku?
(2) If neither are possible, how should I write the fetch() command to let me hit Heroku in production but still keep the local proxying behavior during local development? Some use of environment variables maybe?
In my opinion, It's better to follow the same process (to get the API hostname) in all the environments. Also setting up CloudFront only for this purpose is not convincing unless you have other reasons to do so.
I think you could use an environment variable and here is how you can do it.
using environment variables in react project
react-scripts supports environment variables using dotenv library.
we build the react app using:
REACT_APP_API_DOMAIN=REACT_APP_API_DOMAIN npm run build
or you can define a .env.production where the NODE_ENV environment variable is set to production.
REACT_APP_API_DOMAIN=http://localhost:5000
Then in your code file, you can access it from process.env
await fetch(`${process.env.REACT_APP_API_DOMAIN}/someEndpoint`)
Please read the reference, there is a pattern using which you should define the environment variables for it to work. for e.g each environment variable you define should start with REACT_APP_
Reference:
https://create-react-app.dev/docs/adding-custom-environment-variables/
hope this helps.

Firebase + Next.js serverless, on GCP - How to manage staging, production + local

I'm using React with next.js and Google Cloud functions to serve the app. I also use firebase. I'm looking for the best way to automatically configure the staging and production configuration for the 3 environments.
Production: Uses production credentials
Staging: Uses staging credentials
Local: Also uses staging credentials
I have two Firebase projects and currently switch between the configuration using the firebase.js file in my app. I swap out the config object, then deploy. I want to be able to run the app locally, and both on staging and production without changing anything on deploy as it leads to errors.
The issue for me is setting different environment variables for the two cloud projects...I can read cloud environment variables I set up there, but only in the cloud functions environment, not in the client-facing app, which is where I am currently swapping the configuration.
I can see this being solved by:
Google Cloud Platform environment variables (but I have tried and failed to read them from the client). Maybe I change the next.js config to read something up in the cloud when running, instead of doing the config change at deploy?
Local nextjs environment configuration but this doesn't know anything about the two different servers (only dev vs prod which don't match up exactly with local and cloud)
React dotenv configuration (same as the point above)
webpack / npm configuration that swaps the config when compiling
Swapping env based on firebase use [environment] on the command line at deploy time
Points #1 and #5 seem the most likely candidates for automatic and seamless deployment but I can't figure out how to read the GCP config variables in React and for #5 I don't know how to run a custom script that could swap variables based on the firebase project currently being used on the command line.
Most info I have seen on this doesn't tackle this issue exactly - all the env variables are either only in the cloud functions or distinguish local vs cloud or dev vs prod, but cannot distinguish between two clouds and a local that uses the same config as one of the clouds.
Someone must have had experience with this?
I've finally tracked down an answer to this.
The best way I've found to handle this in React/nextjs is to use a combination of my ideas #4 and #5 from my original question.
As seen here, firebase has a firebase apps:sdkconfig command on the cli that:
Prints the Google services configuration of a Firebase App.
So knowing that, you can add a script to npm that creates a firebase config file each time the site gets built. Since it knows which firebase project you are currently using on the command line, it knows the version of the config to output when you're deploying.
Then, in your package.json, you can set it to run.
"scripts": {
...
"build": "npm run getconfig && next build",
"getconfig": "firebase apps:sdkconfig web --json > ./firebase-config.json",
...
},
Then, in your firebase.js or wherever you're configuring firebase in your app:
// Get the Firebase config from the auto generated file.
const firebaseConfig = require('./firebase-config.json').result.sdkConfig;
// Instantiate a Firebase app.
const firebaseApp = firebase.initializeApp(firebaseConfig);
This works both locally and in the cloud with no manual changes needed other than what you'd already be doing to switch the environment you're using (i.e. firebase use)
You might need to tweak which npm script it runs on or other small things to suit your needs, but this general setup is working great for me with production, staging and development environments.

create-react-app build/serve environment variables

Relatively new to working with react. I have an application that is working fine in local docker. I populate a bunch of REACT_APP_ environment variables by exporting them to the environment before starting the docker container.
Now, I'm trying to deploy this to a kubernetes pod by running a yarn build and then serving up the build. I see that the environment variables are available on the pod itself by looking at printenv but the application doesn't appear to be picking them up.
Is there something special with serving a production build of a react-app to get it to see the exported environment variables that I'm missing?
I don't want to embed an .env file into the built docker image for security reasons, so I'm hoping that running a react build via serve can still pick up exported REACT_APP_ environment variables that are set via kubernetes secrets.
So apparently, whenever you build a react application with npm, static files are produced that don't know anything about any environment variables you may try to inject at runtime with Kubernetes.
The article below does a good job of explaining this and why they choose to attach the environment variables to the JavaScript window object since it has application-scope available to it.
Making a React application container environment-aware at Kubernetes deployment

Resources