Can I change the process.env.NODE_ENV in dev? - react-native

I'm using a node package API client in my react-native project that uses the process.env.NODE_ENV to determine whether to return development or production data. I'd like to test it in my dev environment (simulator) against the production database (it's read-only and the data greatly differs between dev and prod).
From what I can tell from this:
https://github.com/reactjs/react-redux/issues/39#issuecomment-131415769
process.env.NODE_ENV is set to development by default when the dev flag is true.
I've tried setting the NODE_ENV to production in my environment but it isn't picked up in the actual simulator (it still says development).
Is there some way to specify this when starting up or using run-*?

In your AppDelegate.m startup (before calling jsBundleForBundleRoot), add this:
[RCTBundleURLProvider sharedSettings].enableDev = false;
Or for Android, it should be something like this (untested):
PreferenceManager.getDefaultSharedPreferences(this).edit().putBoolean("js_dev_mode_debug", false);
Note that these change the defaults, which I believe exist beyond the execution of your app. So you'll probably need to run them again with true to reset them back to the default values.

Related

How to change environment when logging with sentry

I'm using sentry with react native. I can set the environment when I init:
const env = 'staging'
Sentry.init({
environment: env,
dsn: 'blah',
enableInExpoDevelopment: true
});
But if I want to change the environment later? Do I need to call init again? Or is this something that can be passed up per event?
For capturing events I use something like:
Sentry.Native.captureMessage(eventName, context)
You only need to initialize Sentry one time.
When pushing your changes to main branch, don't forget to also change Sentry's environment to "production" and also your app's version, that will help you debug which version is having issues.

Expo application doesn't get changes in .env file

I have an Expo managed react native application. I created my .env file in the root of my project, installed react-native-dotenv and set up babel to use it. After a while I managed to get it to work.
I have my environment variable
ENDPOINT=http://127.0.0.1:8000/api
and i use it with
process.env.ENDPOINT
After a while I decided to test the android version of the app, so i changed the endpoint url to my LAN ip and restarted the server. The problem is that even after restarting the server, the cache and the computer, when I call process.env.ENDPOINT it keeps the first url I set.
Here's a list of the things i tried:
restarting the server
restarting the server and the cache
restarting the whole computer
change the variable name to REACT_APP_ENDPOINT as many suggested (I get undefined, it's still stuck to ENDPOINT)
empty expo cache
The strange thing is that I already changed that same variable twice (from 127.0.0.1:8000 to 127.0.0.1:8080 and back for a problem with backend) and had the same problem, but it went away by itself after a couple of minutes (and server restarts).
This time I've been trying to get it to work for 7 hours and nothing has changed.
Any idea?
I had the same issue and managed to run the app with .env changes after using the following command.
expo r -c
reference: https://github.com/goatandsheep/react-native-dotenv/issues/75#issuecomment-728055969
After a couple hundred more tests I gave up and implemented a "custom" solution, without any external library:
Switched .env files to TypeScript files (E.g. .env.development -> env.development.ts)
Set up an object named env that has all environmental variables as properties
export const env = {
VAR1: 'foo',
...
}
Imported this constant inside the application entry point (in my case App.tsx)
Inside the main constructor assign env to global.env
Use global.env instead of process.env
Not sure if this is the best practice, but solved my problem for now, works like a charm and doesn't require me to reload my application at every change. I'm a bit concerned by the security aspect of having the environment in a global variable inside a js project, so any suggestion is still welcome

How to Manage Staging and Production Environments in a React Native App

I got a react-native app already ready and works but the app points on a prod api so to avoid problems I wanted that she points on a rest api, so how can I reconfigure it, I have only an environment file.js that contains the URL api, and this file is called in the API service
I tried react-native config but didn't know how to make it work,
All I want is to duplicate that env file because he contains all necessary URLs, so I want to have file named envProd and another named envStaging they should be similar the only different part is the URL of my api , so when I want to run the app i precise which file I want to choose to run with
If the API URL's are the only difference, you don't need to create two separate config files. Instead, you can make use of the inbuild __DEV__ global variable in JavaScript to determine if you're using React Native packager (dev mode) or not (production).
Ref: https://facebook.github.io/react-native/docs/javascript-environment.html
So, something like below.
var apiURL = __DEV__ == true ? 'development.api.com' : 'prod.api.com';
I am finding switching environments quite hard to manage.
__DEV__ is awesome for local disabling stuff when in development. Won't work for any of the builds though.
For staging vs production seems that configuring react-native-config is the best. Unfortunately, next to being somewhat hard to configure binaries need to get recompiled separately for each environment. This means - one update - two build with uploads to whatever provider you use. It can get more complex if you use something like codepush too.
possible solution
Create a hidden feature in your app that allows to toggle the environment from the within the app. This way you can have one build, give it to testers. They switch env to staging and later you only need to promote it as a production build.
This could be something like tap 10 times on an empty space somewhere - the more creative you get the better :)
Good luck
const _Environments = {
production: {
API_BASE: 'https://api.test.com/',
USERNAME: 'admin',
PASSWORD: '1234',
},
development: {
API_BASE: 'https://dev.api.test.com/',
USERNAME: 'admin',
PASSWORD: '1234',
},
};
function getEnvironment() {
// Insert logic here to get the current platform (e.g. staging, production, etc)
var platform = __DEV__ ? 'development' : 'production';
// ...now return the correct environment
return _Environments[platform];
}
export const Environment = getEnvironment();
Try this. using yargs you can replace static import content with dynamic scripts.

How can I test electron-builder auto-update flow?

I built an Electron app and I am now looking at how to distribute it.
I went with electron-builder to handle packaging etc.
For a bit of context, as a web developer, I am used to continuously deploy web apps on a web server but I have a hard time figuring out how to distribute a packaged one in Electron.
In electron-builder docs there is a brief mention about testing auto-update:
"Note that in order to develop/test UI/UX of updating without packaging the application you need to have a file named dev-app-update.yml in the root of your project, which matches your publish setting from electron-builder config (but in YAML format)"
But, it's rather vague...
So I actually have two questions:
1. How do I actually test the auto-update flow?
Do I need to actually publish a new version to trigger an update locally? Seems pretty unclear, it would be like developing against the production server.
2. Is it possible to have a fallback for unsigned code?
I don't have yet any certificate for code signing. So the OS/app will block the auto-update. But, I'd still want to tell the user that an update is available so they can go and download the app manually. Can I do that? (going back to point 1, I'd like to be able to test this flow)
I've just finished dealing with this. I also wanted to test against a non-production server and avoid having to package my app each time I iterated. To test downloads I had to sign my app, which slowed things down. But it sounds like you just need to check for updates. Which I think you can do as follows...
I created a dummy github repo, then created a a file dev-app-update.yml containing:
owner: <user or organization name>
repo: dev-auto-update-testing
provider: github
The path where this file is expected to be defaults to a place you can't access. Thankfully, you can override it like so:
if (isDev) {
// Useful for some dev/debugging tasks, but download can
// not be validated becuase dev app is not signed
autoUpdater.updateConfigPath = path.join(__dirname, 'dev-app-update.yml');
}
...that should be enough for your case -- since you don't need downloads.
If not, here are some other tips:
you can change the repo setting in your electron-builder config to point at your dummy repo then package your app. This will give you a packed, production build that points at your dummy repo -- this is how I did my download testing (though I have a cert, and signed my app)
you should be calling autoUpdate's checkForUpdates(), but if checkForUpdatesAndNotify() gives you a useful OS Notification then you should be able to set autoUpdater.autoDownload to false and end up with what you need.
Lastly, it sounds you could skip autoUpdater, since you won't be using the download feature anyway. Instead you could use github's releases api, assuming you use github to host your release. If not then your host should have something similar. Use that to check for updates then tell the user from within your App (could present them with a clickable URL too). If you want OS Notifications electron has a module for that.
We're using electron-updater with GitHub as a provider for auto-updates. Unfortunately, it breaks a lot and the electron-builder team doesn't support these issues well (1, 2, 3) (from my own experience, but you can find more examples on GitHub).
One way to test updates in dev mode:
Create a build of your app with an arbitrarily high version number
Create a public repo and publish the above build
Create a dev-app-update.yml next to your main entry point and configure it for the repo above (see)
In your main entry point:
import { autoUpdater } from "electron-updater";
...
if (process.env.NODE_ENV === "development") {
// Customize the test by toggling these lines
// autoUpdater.autoDownload = false
// autoUpdater.autoInstallOnAppQuit = false;
autoUpdater.checkForUpdates();
}
Then when running yarn dev you should see something like:
Checking for update
...
Found version 100.0.0 (url: <>.exe)
Downloading update from <>.exe
updaterCacheDirName is not specified in app-update.yml Was app build using at least electron-builder 20.34.0?
updater cache dir: C:\Users\<>\AppData\Local\Electron
New version 100.0.0 has been downloaded to C:\Users\<>\AppData\Local\Electron\pending\<>.exe
And it should install when you close the dev app.
This should give you some certainty but we still ran into issues in production. If you want to be sure, play through the full update flow with a test repo but packaged production apps just as you would do with the live one.

Vue.js: Passing environment variables to a vue.js application

I'm running a vue.js application in a Docker container. I have some configuration set via environment variables (e.g. API base url). I want to be able to use these variables in my application in browser. How can I pass them?
I tried to add these variables to one of the config/*.env.js files like that (config/dev.env.js):
module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
backendBase: process.env.BACKEND_BASE
})
Then I run application using npm run dev but process.env object is always empty (NODE_ENV is also not available)
I came across the exact same problem recently. If you are running the dev server using a watcher I think it doesn't pick the config change up correctly. I stopped my dev server, rebuilt production as well (no idea if that helps but just in case) and then started the dev server up again and all was ok.
To access the above settings you should be able to use process.env in your code
console.log(process.env.NODE_ENV)
I think only variables prefixed with VUE_APP get packaged up by Vue.
From: https://cli.vuejs.org/guide/mode-and-env.html#environment-variables
Note that only variables that start with VUE_APP_ will be statically
embedded into the client bundle with webpack.DefinePlugin.
I tested locally.
.env in root:
APP_TEST=foo
VUE_APP_TEST=bar
In main.js:
// imports and other stuff
new Vue({
render: h => h(App),
}).$mount('#app');
console.log(process.env.APP_TEST, 'APP_TEST');
console.log(process.env.VUE_APP_TEST, 'VUE_APP_TEST');
Output:
undefined APP_TEST
bar VUE_APP_TEST
You'll need to run another build if you make changes to your envvars.