Why React not accept environment variable set in Heroku? - reactjs

I am following docs here: https://create-react-app.dev/docs/adding-custom-environment-variables/
did set up in heroku the variable:
REACT_APP_ENVIRONMENT = prod
and checking in code:
export const fbAppId =
process.env.REACT_APP_ENVIRONMENT === "prod"
? "316459592894290"
: "1162568760820386";
But somehow always the NOT "prod" version is assinged. Do you have any idea why?
I have react-script 3.4.3.

Related

Use multiple web.config files for qa, dev and prod in a REACTJs project

I need to set some headers to my application based on the environment (dev,qa and prod). Is there a way to have multiple web.config files? Or maybe can we access ENV variables within the web.config?
PD: My app is hosted in azure
There are multiple ways to do this
Option 1 :
make use of the Process Env :
in the package.json , update your script to have a script for each of the builds
like
"build:dev": "cross-env ENVIRONMENT=development node parseEnv --exec:\"react-scripts build\"",
"build:prod": "cross-env ENVIRONMENT=production node parseEnv --exec:\"react-scripts build\"",
"build:qa": "cross-env ENVIRONMENT=qa node parseEnv --exec:\"react-scripts build\"",
you can see we are passing ENVIRONMENT= in the scripts
Now create a parseEnv.js file at the same level of the root
parseEnv.js:
const dotenv = require('dotenv');
const fs = require('fs'); // to check if the file exists
const path = require('path'); // to get the current path
const { execSync } = require("child_process");
const currentPath = path.join(__dirname);
// Create the fallback path (the production .env)
const basePath = currentPath + '/env/.env';
// We're concatenating the environment name to our filename to specify the correct env file!
envPath = basePath + '.' + process.env.ENVIRONMENT;
// console.log("the env path is", envPath);
// Check if the file exists, otherwise fall back to the production .env
const finalPath = fs.existsSync(envPath) ? envPath : basePath;
console.log("Selected env:", finalPath);
// Set the path parameter in the dotenv config
const fileEnv = dotenv.config({ path: finalPath }).parsed;
// reduce it to a nice object, the same as before (but with the variables from the file)
const envKeys = Object.keys(fileEnv).reduce((prev, next) => {
prev[`REACT_APP_${next}`] = JSON.stringify(fileEnv[next]);
return prev;
}, {});
let envs = ``
for (const k in envKeys) {
envs += `${k}=${envKeys[k]}\n`
}
fs.writeFileSync(`${currentPath}/.env`, envs)
console.log('Environment variables copied to .env file.')
if (execString.indexOf('--exec:') >= 0) {
execString = execString.replace('--exec:', '')
console.log('Exec:', execString)
execSync(execString, { stdio: 'inherit' })
}
Lets build the env files
create a folder env at the same level of parseEnv.js and create your env files
.env ---> production file
.env.development --> development environment
.env.qa --> Qa environment
example :
.env.development
TITLE=This is development
API_URL=https://dev.example.com/api/v1.6
SECRET_KEY=xxxxxxxxxxxxxxxxxxxxxxxxx
.env
TITLE=This is Production
API_URL=https://prod.example.com/api/v1.6
SECRET_KEY=xxxxxxxxxxxxxxxxxxxxxxxxx
in your index.js , now you can make use of these by calling
const TITLE = process.env.REACT_APP_TITLE;
const URL = process.env.REACT_APP_API_URL;
Option2: make use of a config API .
You can have all your configurations in a JSON and put in a Database against the domain names . For example , consider your development will always happen from localhost:3000 , and qa will happen from https://qa.example.com and so on
you can construct a DB like this
domain | Configs
http://localhost:3000/ { "TITLE": " This is development"}
http://qa.example.com/ { "TITLE": " This is QA" }
and upon init , call this API and connect to a config server which can then serve you back these configs depends on your domain . Advantage here is like you do not need to build seperate , you can still run your Qa at localhost:6000 if you want , you just need to add a db entry alone . NO need to keep env files in the source .

firebase cloud functions: cannot read property 'environment' of undefined

am getting this error while I'm trying to deploy to a new firebase project using
firebase deploy --only functions command. I have two projects in use, one dev and one prod, I was working on prod and deploy worked well now too but when I added this project dev the deploying keeps working well in prod but in this new project dev no. I instead get this error:
Error: Error occurred while parsing your function triggers.
TypeError: Cannot read property 'environment' of undefined
at Object. (/home/projectId/Bitbucket/project-backend/functions/lib/db.js:6:35)
I added the key and eveything in cert/dev/firebase-dev.json in order to work.
The file db.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.db = void 0;
const admin = require("firebase-admin");
const functions = require("firebase-functions");
const dir = functions.config().app.environment;
const certFile = `firebase-${dir}.json`;
//using admin SDK
const serviceAccount = require(__dirname + `/../cert/${dir}/${certFile}`);
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
.....
Any Idea? Thanks.
Since the error is cannot read property 'environment' of undefined and in your code we see
const dir = functions.config().app.environment;
the error seems to come from the environment configuration.
You should double check that the environment configuration is correctly set in the dev environment/project.
For that, you should use the firebase functions:config:get CLI command, as explained in the doc.

workerize-loader failed to work after compiling (react typescript)

I created a rust-wasm module and use workerize-loader to load it:
export const getQRCode = async (
arg: string,
width: number,
height: number
) => {
const { qrcode } = await import('uranus-qrcode');
return qrcode(arg, width, height);
};
and then I use the worker as such:
// #ts-ignore
// eslint-disable-next-line import/no-webpack-loader-syntax
import qrCodeWorker from 'workerize-loader!workers/qrCodeWorker';
...
const workerizeQRLoader = async () => {
try {
const instance = qrCodeWorker();
const qr = await instance.getQRCode(href, 150, 150);
setQRCode({
__html: qr
});
} catch (e) {
console.warn(e);
}
};
...
useEffect(() => {
workerizeQRLoader();
// qrLoader();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
...
The above works in dev mode, but after compiling it says:
TypeError: a.getQRCode is not a function
at 8.a2ac9b2e.chunk.js:1
at l (0.69608c56.chunk.js:2)
at Generator._invoke (0.69608c56.chunk.js:2)
at Generator.forEach.e.<computed> [as next] (0.69608c56.chunk.js:2)
at r (0.69608c56.chunk.js:2)
at s (0.69608c56.chunk.js:2)
at 0.69608c56.chunk.js:2
at new Promise (<anonymous>)
at 0.69608c56.chunk.js:2
at 8.a2ac9b2e.chunk.js:1
If I import the rust-wasm module directly into the main thread it works:
...
const qrLoader = async () => {
const { qrcode: render } = await import('uranus-qrcode');
const qr = await render(href, 150, 150);
setQRCode({
__html: qr
});
};
useEffect(() => {
// workerizeQRLoader();
qrLoader();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
...
Basically I try to get React (Webpack & TypeScript flavor) to load WebAssembly modules (aka wasm, created via Rust-Wasmbindgen) through web workers. I've tried workerize-loader + wasm-loader, and it works pretty well in the dev mode but once it is compiled, the prototype will not be added to the worker (suspecting it's a bug in workerize-loader because all workerized modules behave the same). I also tried to work with worker-loader + comlink, but the worker-loader doesn't seem to work with wasm-loader (would not be able to import wasm into the worker). The only way to get this to work is to load wasm into the main thread via wasm-loader and just give up the multi-threads setup which is basically a shame...so does anyone have successfully use a WebAssembly module loaded through a web worker in a React TypeScript project? What's your setup?
I also created a starter project: https://github.com/aeroxy/react-typescript-webassembly-starter.git
You can checkout the "workerize" branch and see how it works in dev mode but after compiling, it throws "not a function" error.
This is a bit much for a comment but I got some bad and good news. Executed the following commands using node v12.16.1 and yarn 1.22.4:
git clone https://github.com/aeroxy/react-typescript-webassembly-starter.git
cd react-typescript-webassembly-starter
yarn # some warnings that packages need to be updated to later version
yarn start # dev version works
yarn build
cd build
npx serve
When opening the build version in Google Chrome 81.0.4044.113 (Official Build) (64-bit) on my Fedora 31 I can see the qr code, no errors in console.
That means that there is no fault in the project (good news) but something maybe wrong in settings on your machine (bad news), the os you are using or some other machine specific difference.
You could try a to clone the project again and run the commands exactly like I did to see if that's working. Older npm could have some problems with cached packages but that's been fixed for a while now. A while ago you needed to change the repository for npm or use vpn because it was blocked, this could also be causing you trouble.
This is a duplicate of my original answer but got deleted for some odd reason by a moderator without leaving a reason.
Now the workerize method works!
I've originally tried workerize-loader + wasm-loader, and it works pretty well in the dev mode but once it is compiled, the prototype will not be added to the worker (suspecting it's a bug in workerize-loader because all workerized modules behave the same). This indeed turns out to be a bug in workerize-loader (see workerize-loader failed to work after compiling and Version 1.2.0 does not export function on worker instance in production mode). After upgrading to the workerize-loader 1.2.1, it works in both dev and prod code.
I have updated the Master repo: https://github.com/aeroxy/react-typescript-webassembly-starter.git

react is missing from redux-devtools

I am relatively new to react and webpack, and I just picked up a new project to work on. To configure DevTool, we have:
export function renderDevTools(store) {
if (__DEV__) {
let {DevTools, DebugPanel, LogMonitor} = require('redux-devtools/lib/react');
return (
<DebugPanel top right bottom>
<DevTools store={store} monitor={LogMonitor} />
</DebugPanel>
);
}
return null;
}
From the node_module, I can see:
\node_modules\redux-devtools\lib\
has
createDevTools.js
index.js
persistState.js
but there is no react.js in this folder, so running the code will give:
ERROR in ./app/utils/devTools.js
Module not found: Error: Cannot resolve module 'redux-devtools/lib/react'
I have tried
npm install redux-devtools
but there is still missing react from the file. This is a legacy code, and when I tried running it, it isn't working. I am wondering what went wrong?
This code is for redux-devtools#2. In redux-devtools#3 monitors are decoupled into redux-devtools-log-monitor and redux-devtools-dock-monitor, which you have also to install and add to you project as indicated in the docs.
Also you have to set __DEV__ as true in webpack.config (which should be different for development and production):
plugins: [
new webpack.DefinePlugin({
'__DEV__': true
})
],
A easier way is not to include it directly into your app, but to use Chrome / Firefox extension. Then you can add it to your Redux store with just one line of code:
const store = createStore(reducer, /* preloadedState, */
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
Make sure to remove everything else related to Redux DevTools in this case.
If you're using the extension you can use it also in production without any edge cases, otherwise make sure to remove it from production bundle.

Setting NODE_ENV via envify not working

I have the following gulp task in my gulpfile.js:
gulp.task('build-scripts', function () {
var b = browserify({ debug: false });
b.transform(reactify);
b.transform(envify({
_: 'purge',
NODE_ENV: 'production'
}));
b.add('./src/scripts/index.js');
return b.bundle()
.pipe(source('./www/scripts/dist/bundle.js'))
.pipe(buffer())
.pipe(uglify())
.pipe(gulp.dest('.'))
});
The task completes with status 0 and the React transform happens, but in bundle.js I still see:
if (process.env.NODE_ENV !== 'production') {
Wasn't this supposed to go away with the envify transform?
Am I doing something wrong here?
I have done some digging, but all the solutions I can find are os x / linux specific (I'm on a windows machine).
EDIT: I am running the gulp build from within visual studio's Task Runner Explorer.
The doc says:
By default, environment variables that are not defined will be left untouched.
https://github.com/hughsk/envify#purging-processenv
Have you tried defining it before running that? i.e.
process.env.NODE_ENV = 'production';

Resources