noszone
noszone

Reputation: 328

Is it possible to use a React server enviroment variables into frontend at client side?

I am using PKG, to make a executable .exe file for my Appolo GraphQL Server + React client bundled all into one exe file. It's working, and now there is requirement: app should read from somewhere an IP address and use it as constants for host, port, etc.

From server side I am using fs.readFileSync - which is okay. I can read any text file as it's nodejs server side. And now the requirement is to pass that IP to the client files -> into the static folder (marked *), where I have constant.js with IP of client to connect inside (compiled static/js..). Server side files (NodeJs+React):

├───build
│   └───static
│       ├───css
│       ├───*js*
│       └───media
├───config
├───src
│   ├───core
│   ├───graphql
│   ├───guardServer
│   └───pg
└───SSL

Client React files tree:

├───.idea
├───.vs
│   └───React
│       └───v16
├───build
│   └───static
│       ├───css
│       ├───js
│       └───media
├───public
└───src
    ├───components
    │   ├───core
    │   │   ├───functions
    │   │   └───modal
    │   └───modules
    │       ├───account
    │       ├───adminPanel
    │       │   └───pages
    │       ├───archive
    │       ├───hr-department
    │       │   └───pages
    │       ├───logs
    │       ├───monitor
    │       └───reports
    ├───config
    └───images

So my actions are: npm run build a clent. Then I taking the folder build and replacing a server side files: server/build folder. Then I'm doing on the server side - npm run build and receiving an exe file. WHERE a server part (/server/index.js) of this exe can read a settings.txt, but not that part (client) which is inside /server/build/static/js...

My question is: is it possible by modifying webpacker somehow, and server environment variable will be accessible (and will be dynamic) from client side with command process.env.myvar?

If not, if there are any tricks I can utilize in this case? Please note that PKG's fs.writeFileSync is now allowed due to the filesystem shapshot restriction.

Code of server side:

let fileContent = fs.readFileSync("D:\\settings.txt", "utf8");
let getIp=JSON.parse(fileContent); //fine working, got IP

Client using Apollo Client and exactly for him I need to pass that IP from server side, any ideas please?

Update for Ajeet Shah. What I did:

On my server.js - var __SERVER_DATA__ = "192.168.0.111";

in index.html of client - <script>
      window.SERVER_DATA = __SERVER_DATA__;
    </script>

in index.js of client - console.log(window.SERVER_DATA);

Update:

I think I will end up for a while with the tiny http server, which will run on localhost:port. And from there I can freely read any settings. Thank you All for usefull answers.

I've chosen the answer with more options and there was advise about localStorage. Thank you all much for heads up. Still trying to implement offered methods.

Update.

I've finishied doing this. I've used an html variable window.SERVER_DATA = __SERVER_DATA__ as described here - https://create-react-app.dev/docs/title-and-meta-tags/#injecting-data-from-the-server-into-the-page. I will decide later on what to do with best answer, if nobody will post extra ones.

Upvotes: 2

Views: 3391

Answers (2)

JRichardsz
JRichardsz

Reputation: 16524

In backend technologies, everything is solved with environment variables which is a good practice when you have to move your app through stages( dev, staging, prod).

In client side technologies( react, vue, angular or simple js) the obtainment of these values dynamically is complicated.

Check this answer to understand how variables work in js client side or how to inject dynamic values

https://stackoverflow.com/a/54271114/3957754

REACT_APP

One strategy is use the REACT_APP variables

https://create-react-app.dev/docs/adding-custom-environment-variables/

So if you create this variable in your server side

export REACT_APP_remote_ip

React library will create a variable for you. You can use thia var in any react file

process.env.remote_ip

Webpack

Similar to REACT_APP webpack offer an option to expose server side variables as global javascript variables ready to use in any .js file

new webpack.DefinePlugin({
  API_BASE_URL: JSON.stringify(process.env.API_BASE_URL)
})

/settings

Another option is to create an endpoint in your nodejs server side. This endpoint has access to the environment values, so you can return anything you want:

res.json({
  "ip1": process.env.remote_ip_1
});

After this, you just need to call or invoke this endpoint /settings in the most early js or entrypoint of your react or javascript files.

Finally, the return of /settings could be exposed as global javascript values or stored in localstore of browser

Upvotes: 1

Ajeet Shah
Ajeet Shah

Reputation: 19823

As described in docs, you can create server side variables that can be injected in your front end code.

Here is what you need to do:

  1. Create a JS script, say myConfig.js, and place it on the server at a public location so that frontend can load it.
  2. Define config data in this file, e.g:
const myConfig1 = "foo bar"
const myConfig2 = "anythng else"
  1. Add below lines in the <head> section of index.html file in your frontend app. It will read load/data from the server and set those in global window object.
<script src="http://path/to/file/on/server/myConfig.js" type="text/javascript"></script>
<script>
  window.myConfig1 = myConfig1
  window.myConfig2 = myConfig2
</script>
  1. Now you can access those config vars (which came from server) in your ReactJS app using global window object as window['myConfig1'] and window['myConfig2'].

Using this method, you don't need to rebuild the frontend app using npm run build when you change your config vars as these are defined, separately from frontend, on the server. To change these config vars, you just need to change those on the server and do a refresh in browser.

Upvotes: 1

Related Questions