I want to deploy a React app (made with Create React App) + a Node server with Heroku,
I did it, but my app can't fetch data from the server,
In production, my process.env.NODE_ENV is equal to "development" which causes a lot of wrong stuff in my code,
Do you know what can put process.env.NODE_ENV always at "development"? At the build, this environment variable is supposed to switch to "production", no?
Your package.json add this.
"scripts": {
"start": "export NODE_ENV=development; {your start code}",
Your env variables can be set per environment, in this case in Heroku: https://devcenter.heroku.com/articles/config-vars#using-the-heroku-dashboard
If you want to make sure build always runs with the same NODE_ENV, you can follow #seunggabi 's answer. I'd also use cross-env to make it work cross-platform in such case. Per-process variable can be forced on heroku-postbuild task (after &&).
You can take control of your Environment with env-cmd. They make easy to switch between your local development, testing, staging, UAT or production.
You can refer to this article. This is was very helpful for me
Related
I deployed a regular React app to Vercel and would like to have a API_BASE_URL environment setting with different values for development, preview and production environments.
Typically, I'd use dotenv npm package with my webpack config setting up the variables for local or production depending on the build by looking into env.local and env.production respectively.
The env.production would look like this:
API_BASE_URL=#{API_BASE_URL}
Then, I'd have my deployment pipeline replace all instances of #{___} with the respective values available in the pipeline.
However, the regular way in Vercel seems to be to make a Next.js app and the environment variables in the project will be automatically available in the process.env variable in the backend code.
Is there anyway for us to have environment variables in a non-Next.js in Vercel?
I'm thinking I have 2 ways forward:
There is actually an easy way 🍀
Create my own build and deployment pipeline to replace the #{___} placeholders and deploy using vercel deploy command.
Had a similar issue on my SPA (React + Webpack) app on deployed on Vercel. This is what worked for me.
https://github.com/mrsteele/dotenv-webpack#properties
webpack.config.js
const Dotenv = require('dotenv-webpack');
module.exports = {
// OTHER CONFIGS
plugins: [
new Dotenv({
systemvars: true
})
]
};
Doing it like this I was able to read env vars from:
Vercel build runtime (ex: VERCEL_ENV)
.env file in my src folder
Env variables defined in Vercel console
Initially, I was overlooking an important fact. Vercel deploys builds and deploys changes in the same step.
2 commits in preview branch which are merge them both to main in 1 single commit: that's a totally new thing (a new build is created for every single commit in every environment).
This goes against the build once, deploy to multiple environments principle but I suppose Vercel's team considered that in their quest to make the development process as simple as possible.
Anyway, I worked out 2 solutions:
In the build command, insert the environment variables e.g. in the package.json:
scripts: {
"build": "webpack --env production --env VERCEL_ENV=$VERCEL_ENV"
}
Create my own build and deployment pipeline and then deploy to vercel using vercel deploy command. It also works but I think I'm going to stick to the option for simplicity, at least in the meantime.
I've just deployed my first Next.js app in production through Nginx and pm2. Everything seems okay but the app frequently reloads after some interval on browser. I'm seeing the webpack-hmr is also running in my production server. (Which I think isn't necessary in production)
I am using a custom server.js and I run my app on production using next build then NODE_ENV=production node server.js command, and restarting my server using pm2.
I've added below a screenshot of my dev-tool's network tab which is showing the HMR running on production. If HMR is the possible cause of browser reload, then what should I do to disable it on production?
And also if the "frequent reload" isn't happening because of HMR then what will be the cause of it?
Have you guys experienced the same issue on production? If so, please share your knowledge and experience. Thanks.
Edit: I am also using next-pwa and a warning keeps showing on my console for it -
GenerateSW has been called multiple times, perhaps due to running webpack in --watch mode. The precache manifest generated after the first call may be inaccurate! Please see https://github.com/GoogleChrome/workbox/issues/1790 for more information.
Fixed it by disabling pwa when in development
const prod = process.env.NODE_ENV === 'production'
module.exports = withPWA({
pwa: {
dest: 'public',
disable: prod ? false : true
}
})
Finally found a solution. I had to tell my env mode when starting pm2 as pm2 start server --env production. And it works perfectly on my browser.
After running yarn eject in my react project,I get the 'process' is not defined error when calling registerServiceWorker() in index.js. files in scripts and config directories are not modified.
I get the same error for module variable.
This happens because React uses process.env to determine whether you're in a development or production environment. From getting-started.md:
Note: by default, React will be in development mode, which is slower, and not advised for production. To use React in production mode, set the environment variable NODE_ENV to production (using envify or webpack's DefinePlugin).
For example:
new webpack.DefinePlugin({
"process.env": {
NODE_ENV: JSON.stringify("production")
}
});
So to build it with Rollup, you need to replace process.env.NODE_ENV with either "development" or "production" – you can use rollup-plugin-replace for this:
rollup({
entry: 'main.js',
plugins: [
replace({
'process.env.NODE_ENV': JSON.stringify( 'production' )
})
]
}).then(...)
Since there is not a lot of details regarding your setup, my answer is going to assume you are using create-react-app which is the most common tool with the concept of an eject command.
You are using a version of CRA that got released before this change, renaming the registerServiceWorker file to serviceWorker and disabling SW by default, so a version <=1.1.5 based on release tags.
The Service Worker of CRA is there to cache your assets so that your application still works offline. If you don't need this feature, one straightforward thing to fix the error would be to disable the registerServiceWorker call, since that's what they did in the template too.
A more painful one would be to actually upgrade your project to CRA 2.x but probably worth it in the long run to keep your ejected project as close as possible to the origin. There is an upgrade guide you could take a look at here.
I myself created a new CRA project using the latest version and ejected it while enabling the service worker and didn't encounter any issue of the sort you are experiencing, so definitely something to consider too.
I've built my Angular 2 project using the Angular 2 CLI and was able to deploy the application to Heroku using this tutorial.
Now, I'd like to create a pipeline for the different environments of the applications (dev, staging, production, etc...).
In my package.json I have "postinstall": "ng build -prod" which creates a production build of my code, which my application runs off of. Is there a way that I could have -prod change based on CONFIG_VARS that I would have in my Heroku setup? For example it would say "postinstall": "ng build -dev" for a dev environment or "postinstall": "ng build -staging" for a staging environment. Or would I need to set up my project differently?
The short answer is: No, you will need to do something different.
Explanation:
The npm postinstall script runs when the Heroku slug is built, when you do a git push to the first Heroku app in your pipeline. Subsequently, when you "promote" releases through your Heroku pipeline (e.g. from "development" to "staging" to "production"), the pre-built Heroku slug is promoted "as is", and is NOT rebuilt.
Hence, let's say you have a config var set up in your "development" app that would set the argument that you pass to "ng build" to "dev". That means that when you git push to your "development" app, the slug will get built with the "dev" options. That is fine for the "development" app. HOWEVER, when you subsequently promote to "staging" and "production", you will be promoting the pre-built slug that was built with the "dev" options, which is NOT what you want.
So, to get the functionality you want you will need to consider a different approach.
One way to do it would be to run your "ng build" script in the "npm prestart" phase. That should work, and enable you to use Heroku config vars to modify your Angular2 app depending on the Heroku pipeline phase they are deployed on. However, I typically would NOT recommend this approach. This will cause your "ng build" to run every time "npm start" is run, which is quite often on Heroku (i.e. at least once every 24 hours or so, plus every time your Heroku dynos restart for whatever reason). This would cause your app to experience longer downtime than necessary EVERY time your dynos restart. Not a good idea, typically.
Instead, a better option may be to have your Angular2 app query your server when it initializes, and have the server return whatever pipeline-phase specific values your Angular2 app needs, based on regular Heroku config vars.
If you are running your application in a Heroku node environment you can try to take a look at this solution to avoid having your environments variables and security keys hardcoded in the repositories: https://medium.com/#natchiketa/angular-cli-and-os-environment-variables-4cfa3b849659
I strongly suggest also to take a look at its first response that introduce a dynamic solution to create the environment file at building time: https://medium.com/#h_martos/amazing-job-sara-you-save-me-a-lot-of-time-thank-you-8703b628e3eb
Maybe they are not the best solutions, but a trick to avoid setting up projects differently each time.
i found your question when i was researching the same issue.. how to use environment vars from heroku inside of angular..
after not finding any satisfying answer i came with this (cookie) approach for using different API endpoints for my pipeline.
set a cookie in your server response (server.js) with the content of your var:
app.use(function(req, res, next) {
res.cookie('API_URL', process.env.API_URL || 'http://127.0.0.1:8500/api/');
next();
});
read the value inside of your module:
this.apiUrl = cookieService.get('API_URL');
it's a workaround that will of course only work when user accepts cookies...
I am attempting to figure out the best way to load environment variables into my AngularJS app. I am currently using constants, which take their valuues from those defined in the Webpack definePlugin. However, this causes an issue with Heroku as the code is built when pushed to staging, and when it is promoted to production, it is not rebuild, therefore the webpack definePlugin constants are the staging environment variables.
I have looked at requesting the environment variables from my API at run time and then setting them as constants to be used in my front-end, but I can't figure out how to set constants programatically outside of the initial .constant(..) opportunity.
If anyone knows any other better practices around loading environment variables into a front-end when using Webpack (and not Grunt) please do let me know.
If you are using node.js (and npm) in your server, you could consider running webpack in the "npm prestart" script, instead of in "npm postinstall".
That way webpack would run every time your heroku dynos start or recycle, and so would pick up your env var definitions from the appropriate Heroku pipeline phase. So, when your staging dynos start, webpack would pick up your staging env var definitions, and when your production dynos start, webpack would pick up your production env var definitions.
The disadvantage of this approach, however, is that increases the time your dynos are out of service while recycling, since they now need to run webpack before starting.