Module not found: Error: Can't resolve 'fs' in dotenv/lib - node.js

All of a sudden, when creating a react production build, I get this error.
> safe-courier#0.1.0 build
> react-scripts build
Creating an optimized production build...
Failed to compile.
Module not found: Error: Can't resolve 'fs' in '/workspace/safe-courier/client/node_modules/dotenv/lib'
I have searched on the web, found similar cases but different frameworks of which all were not of help in regards to this issue.
I have tried to uninstall dotenv and reinstall it again but i get the same error. I'm not sure what could be the problem understanding that fs module is part of nodejs and comes bundled with it

To solve this:
Create the .env file at the root level of you app
Name your variables beginning with REACT_APP_ // that's the key !!
Restart your server with npm start each time you change an env variable
Use your variable with process.env.NAMEOFYOURVARIABLE
No need of dotenv for your React app.

I solved the same problem;
npm install dotenv-webpack --save-dev
Create .env file under root folder
create env variable as
REACT_APP_YOURVARIABLE=itsvalue
Create webpack.config.js file under the root folder with following content
const Dotenv = require('dotenv-webpack');
module.exports = {
plugins: [
new Dotenv()
]
}
Then wherever you want to use variable in .env write
process.env.REACT_APP_YOURVARIABLE
There is no need to import dotenv. It is already done in webpack.config.js

1- As already mentioned by Stéphane Sulikowski, No need to use dot-env in react projects
Why?
"dot-env" uses some modules that are only supported by nodejs but not supported by "browser engines" like fs, os etc. React-code-bundle runs in the browser and the browser doesn't support module "fs", so if any modules reference the "fs" module will get the same error.
There is some inbuilt support by reactjs to use environment variables stored in a .env file and begins with REACT_APP_
2- If you have to use it for some reason use "env-cmd"
npm install env-cmd
3- create environment specific .env files like .env.local OR .env
4- In your "environment specific" OR .env file, add variables beginning with REACT_APP_
REACT_APP_API_BASE_URL="http://localhost:4000"
5- Use these environment variables in your code files
like console.warn (process.env.REACT_APP_API_BASE_URL)
6- OPTIONALLY...... configure package.json something like this
...
"scripts": {
"start": "env-cmd -f .env.local react-scripts start",
"build:staging": "env-cmd -f .env.staging react-scripts build",
"build:production": "env-cmd -f .env.production react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
}
Note - When you add a new variable in .env .... files, you have to run npm start OR related...

Just like Reno mentioned just create your .env at the root with the name prepended with REACT_APP and it will work out of the box
Example .env file
REACT_APP_GITHUB_API_URL=https://api.github.com/graphql
Usage:
process.env.REACT_APP_GITHUB_API_URL

If you are using create-react-app this article describes the behavior of environment variables: https://create-react-app.dev/docs/adding-custom-environment-variables/
Note that the document frequently reminds you of this warning:
WARNING: Do not store any secrets (such as private API keys) in your React app!
Environment variables are embedded into the build, meaning anyone can view them by inspecting your app's files.
To securely use secrets such as passwords and tokens, consider setting up a server that can deliver this data to the frontend via HTTP. For example, once users authenticate into your app you send their credentials to a microservice that can validate their identity and return an API key or session to be used for subsequent REST API calls.

Related

process.env.NODE_ENV suddenly UNDEFINED in current SvelteKit project

Inside svelte.config.js I was using this
const dev = process.env.NODE_ENV === 'development';
to conditionally set a base path which was working fine in projects with #sveltejs/kit#1.0.0-next.350 and *.357
After installing now the most recent SvelteKit version #sveltejs/kit#1.0.0-next.386 it only results to undefined
Differences I notice is that the new project lists "vite": "^3.0.0" as devDependency and the script changed from "dev": "svelte-kit dev", to "dev": "vite dev"
Update: It's also the case for a project with #sveltejs/kit#1.0.0-next.366, vite#2.9.14, "dev": "vite dev" - so the switch was before vite 3.0
Going through the vite docs I find import.meta.env, but that's also undefined inside svelte.config.js
Switching from Node v16 to 17 didn't make a difference as well
What changed and how can I now distinguish between dev and build mode?
The behavior you describe was introduced in 100-next384
[breaking] remove mode, prod and server from $app/env (#5602)
and here is the relevant discussion
respect --mode, and remove server, prod and mode from $app/env
I think you should use Vite capabilities to configure dev VS production/build modes.
Update
Considering better your case, a way to solve the issue is to set a value for the NODE_DEV environment variable, like (Linux/Mac):
export NODE_ENV=development && npm run dev
There are other ways to do this but at least for development it should do the trick.
This might help someone in the future. I encountered this error when I created an express server in a react application. I created the server directory in the root folder of the react application and I was running both react app and express server at the same time.

How Do I Build For A UAT Environment Using React?

According to the React docs you can have development, test and production envs.
The value of NODE_ENV is set automatically to development (when using npm start), test (when using npm test) or production (when using npm build). Thus, from the point of view of create-react-app, there are only three environments.
I need to change root rest api urls based on how I am deployed.
e.g.
development: baseURL = 'http://localhost:3004';
test: baseURL = 'http://localhost:8080';
uat: baseURL = 'http://uat.api.azure.com:8080';
production: baseURL = 'http://my.cool.api.com';
How do I configure a UAT environment for react if it only caters for dev, test and prod?
What would my javascript, package.json and build commands look like to switch these values automatically?
Like John Ruddell wrote in the comments, we should still use NODE_ENV=production in a staging environment to keep it as close as prod as possible. But that doesn't help with our problem here.
The reason why NODE_ENV can't be used reliably is that most Node modules use NODE_ENV to adjust and optimize with sane defaults, like Express, React, Next, etc. Next even completely changes its features depending on the commonly used values development, test and production.
So the solution is to create our own variable, and how to do that depends on the project we're working on.
Additional environments with Create React App (CRA)
The documentation says:
Note: You must create custom environment variables beginning with REACT_APP_. Any other variables except NODE_ENV will be ignored to avoid accidentally exposing a private key on the machine that could have the same name.
It was discussed in an issue where Ian Schmitz says:
Instead you can create your own variable like REACT_APP_SERVER_URL which can have default values in dev and prod through the .env file if you'd like, then simply set that environment variable when building your app for staging like REACT_APP_SERVER_URL=... npm run build.
A common package that I use is cross-env so that anyone can run our npm scripts on any platform.
"scripts": {
"build:uat": "cross-env REACT_APP_SERVER_URL='http://uat.api.azure.com:8080' npm run build"
Any other JS project
If we're not bound to CRA, or have ejected, we can easily configure any number of environment configurations we'd like in a similar fashion.
Personally, I like dotenv-extended which offers validation for required variables and default values.
Similarly, in the package.json file:
"scripts": {
"build:uat": "cross-env APP_ENV=UAT npm run build"
Then, in an entry point node script (one of the first script loaded, e.g. required in a babel config):
const dotEnv = require('dotenv-extended');
// Import environment values from a .env.* file
const envFile = dotEnv.load({
path: `.env.${process.env.APP_ENV || 'local'}`,
defaults: 'build/env/.env.defaults',
schema: 'build/env/.env.schema',
errorOnMissing: true,
silent: false,
});
Then, as an example, a babel configuration file could use these like this:
const env = require('./build/env');
module.exports = {
plugins: [
['transform-define', env],
],
};
Runtime configuration
John Ruddell also mentioned that one can detect at runtime the domain the app is running off of.
function getApiUrl() {
const { href } = window.location;
// UAT
if (href.indexOf('https://my-uat-env.example.com') !== -1) {
return 'http://uat.api.azure.com:8080';
}
// PROD
if (href.indexOf('https://example.com') !== -1) {
return 'http://my.cool.api.com';
}
// Defaults to local
return 'http://localhost:3004';
}
This is quick and simple, works without changing the build/CI/CD pipeline at all. Though it has some downsides:
All the configuration is "leaked" in the final build,
It won't benefit from dead-code removal at minification time when using something like babel-plugin-transform-define or Webpack's DefinePlugin resulting in a slightly bigger file size.
Won't be available at compile time.
Trickier if using Server-Side Rendering (though not impossible)
To have multiple environments in a React.js application you can use this plugin
env-cmd from NPM
And after that Create the three files as per your need.
For example if you want to setup dev, stag and prod environments you can write your commands like this.
"start:dev": "env-cmd -f dev.env npm start", // dev env
"build:beta": "env-cmd -f stag.env npm run build", // beta env
"build": "react-scripts build", // prod env using .env file

Run create-react-app in a certain browser

Is it possible to launch create-react-app App in a certain browser of my choice? Currently, it always runs in the Chrome while I want it to do that in the Chrome Canary. Does anybody know?
You can use BROWSER environment variable to set which browser you wanna open the app in. For example,
BROWSER=firefox yarn start
or
BROWSER=firefox npm start
will open the app in firefox.
So, you can put something like this in your package.json
"scripts": {
"start": "BROWSER=firefox react-scripts start",
"build": "react-scripts build && sw-precache --config=sw-precache-config.js",
"test": "react-scripts test --env=jsdom",
You can read more about it in this pull request thread
With current iterations of create-react-app this can be accomplished by adding a .env file to the project with a "BROWSER" key. It's described in the Advanced Configuration section of the documentation.
If you want to use Google Chrome Canary for your development browser (as I do) then you'll need to create that .env file in the root of the project with the following contents:
# Override default browser for npm start in react-script
BROWSER=Google Chrome Canary
Be sure you don't get overzealous and quote it or add a semi-colon at the end. I did both and scratched my head at first why it didn't work.
You can use .env file with BROWSER=firefox
https://create-react-app.dev/docs/advanced-configuration/
This worked for me:
Set Chrome Canary as default browser in PowerShell (choose the right path first)
$chromePath = "${Env:ProgramFiles(x86)}\Google\Chrome\Application\"
$chromeApp = "chrome.exe"
$chromeCommandArgs = "--make-default-browser"
& "$chromePath$chromeApp" $chromeCommandArgs
(answer from)
https://stackoverflow.com/a/17536704/11878186
Set variable BROWSER=Chrome in .env file in root directory

Target certain environments based on console input

To preface the question I am using an ejected create-react-app for the layout of my project.
I have 5 environments that my application is going to be deployed to. Each environment has the same set of services (mostly), for example one might look like:
//environment 1
https://environment1.service1.foo.bar
https://environment1.service2.foo.bar
//environment 2
https://environment2.service1.foo.bar
https://environment2.service2.foo.bar
To achieve this on past projects (Angular/Gulp) I had a gulp task that essentially would look for a variable being passed in
gulp build --environment environment1
The code to do so looks like this:
gulp.task('environment', ['clean-environment'], function() {
log('Copying environment');
var environmentFile = config.environmentSrcDir + 'env2.js';
if (args.environment !== 'env2' ||
args.environment === 'env3' ||
args.environment === 'env4' ||
args.environment === 'evn5') {
environmentFile = config.environmentSrcDir + args.environment + '.js';
}
return gulp
.src(environmentFile)
.pipe(rename(config.environmentService))
.pipe(gulp.dest(config.root));
});
And basically point to the correct file with the correct endpoints inside of it as well as other pertinent variables associated with that environment.
My question is, where given the fact that I am using create-react-app as a starting point, so webpack, and node scripts, how would I accomplish something like this. Basically I want to be able to say yarn build env1 and then the project to set a constant or file of constants as the 'active` constants so to speak.
If you are using "Create-react-app" then you have the ability to define development environment variable through different .env files.
Link: https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#adding-development-environment-variables-in-env
.env:
REACT_APP_GOOGLE_CLIENT_ID = XXX-YYY-ZZZ.apps.googleusercontent.com
REACT_APP_API_PROTOCOL = http:
REACT_APP_API_HOST = localhost:3000
NODE_PATH = src/scripts
PORT = 9001
.env.production:
REACT_APP_GOOGLE_CLIENT_ID = ZZZ-YYY-XXX.apps.googleusercontent.com
REACT_APP_API_PROTOCOL = https:
REACT_APP_API_HOST = api.my-applicaton.com
NODE_PATH = src/scripts
Read different .env configs according to current command (start / test / build). dev.env for start and test. prod.env for build. If custom config does not exist — read env variables from .env file.
Blockquote
You will tell which .env file will be used with your start project command.
You should have something like this in your package.json file under scripts object:
"start-js": "react-scripts start",
"start": "npm-run-all -p watch-css start-js",
"build": "npm run build-css && react-scripts build",
Then you can start your project using specified commands. From the documentation, files on the left have more priority than files on the right:
npm start: .env.development.local, .env.development, .env.local, .env
npm run build: .env.production.local, .env.production, .env.local, .env
npm test: .env.test.local, .env.test, .env (note .env.local is missing)
For example, if you start with npm run build, you will be able to access variables defined in .env.production file.
In JavaScript code, you can use process.env.REACT_APP_API_HOST.
Also, see this link on medium.com: https://medium.com/#tuchk4/why-i-love-create-react-app-e63b1be689a3

How to set NODE_PATH=. for node.js app hosted in openshift

I use custom node.js cartridge on openshift
icflorescu/openshift-cartridge-nodejs .
How can i set NODE_PATH=. for app start in package.json ? Should i provide it in package.json like that : "start": "NODE_PATH=. NODE_ENV=production node app.js" ,
either i should use something like here
Dindaleon/hapi-react-starter-kit - some npm package like cross-env
I have line in main app.js file. There is folder named 'config', in the same directory with app.js, in folder config placed file index.js, file index.js have code with 'module.exports = Object.assign({ ...some conifg object... });' . When i delete NODE_PATH=. , node throws "Error: Cannot find module 'config' " .
var config = require('config');
I'm the author of openshift-cartridge-nodejs :-)
Having "start": "node app.js" in your package.json should be just enough.
If you take a look at bin/install, you'll see that NODE_ENV is already set to production by default in the cartridge setup script.
Also, I'm not sure what you're trying to achieve by setting NODE_PATH to .. There's a single Node.js version installed.
If you're generally interested in how you can set custom environment variables in an OpenShift-deployed application, have a look at the docs here. Basically you'll have to use the rhc command-line utility like this:
$ rhc env set <Variable>=<Value> <Variable2>=<Value2> -a App_Name

Resources