I'm trying to provide access to certain environment variables in the front end code package by webpack, but process is always undefined. The application I'm working on is doing a bunch of extra stuff in the webpack configuration that I thought might be creating issues, so I wanted to see how it worked with a default create react app instance, and then compare the two. However I'm seeing the same behavior with the create react app instance (process is always undefined in the client side code).
These are the steps I performed:
// We will provide `paths.publicUrlOrPath` to our app
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
// Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
// Get environment variables to inject into our app.
const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1));
(then further down in webpack.config.js...)
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
// It is absolutely essential that NODE_ENV is set to production
// during a production build.
// Otherwise React will be compiled in the very slow development mode.
new webpack.DefinePlugin(env.stringified),
This section from config/env.js show that at the very least process.env.NODE_ENV=development, regardless of what it picks up from the underlying environment:
const raw = Object.keys(process.env)
.filter(key => REACT_APP.test(key))
.reduce(
(env, key) => {
env[key] = process.env[key];
return env;
},
{
// Useful for determining whether we’re running in production mode.
// Most importantly, it switches React into the correct mode.
NODE_ENV: process.env.NODE_ENV || 'development',
// Useful for resolving the correct path to static assets in `public`.
// For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
// This should only be used as an escape hatch. Normally you would put
// images into the `src` and `import` them in code to get their paths.
PUBLIC_URL: publicUrl,
// We support configuring the sockjs pathname during development.
// These settings let a developer run multiple simultaneous projects.
// They are used as the connection `hostname`, `pathname` and `port`
// in webpackHotDevClient. They are used as the `sockHost`, `sockPath`
// and `sockPort` options in webpack-dev-server.
WDS_SOCKET_HOST: process.env.WDS_SOCKET_HOST,
WDS_SOCKET_PATH: process.env.WDS_SOCKET_PATH,
WDS_SOCKET_PORT: process.env.WDS_SOCKET_PORT,
// Whether or not react-refresh is enabled.
// It is defined here so it is available in the webpackHotDevClient.
FAST_REFRESH: process.env.FAST_REFRESH !== 'false',
}
);
// Stringify all values so we can feed into webpack DefinePlugin
const stringified = {
'process.env': Object.keys(raw).reduce((env, key) => {
env[key] = JSON.stringify(raw[key]);
return env;
}, {}),
};
return { raw, stringified };
}
function App() {
console.log(process);
return (
<div className="App">
<header className="App-header">
ReferenceError: process is not defined
at App (App.js:7:1)
at renderWithHooks (react-dom.development.js:15486:1)
at mountIndeterminateComponent (react-dom.development.js:20103:1)
at beginWork (react-dom.development.js:21626:1)
at beginWork$1 (react-dom.development.js:27465:1)
at performUnitOfWork (react-dom.development.js:26596:1)
at workLoopSync (react-dom.development.js:26505:1)
at renderRootSync (react-dom.development.js:26473:1)
at recoverFromConcurrentError (react-dom.development.js:25889:1)
at performConcurrentWorkOnRoot (react-dom.development.js:25789:1)
UPDATE: This question has been marked as a duplicate of Uncaught ReferenceError: process is not defined however I believe that there is a key difference between the two. The other question focuses entirely on the details of how to set up the configuration, whereas this question deals with the mechanics of how the data is being injected into the client side app. The configuration I had was in fact correct (since I was relying on Create React App to do the configuration for me). It was when I tried to troubleshoot the behavior by adding
console.log(process);
it was then demonstrated that I had a misunderstanding of how the data was being made available (as an object vs straight text substitution).
TL;DR; I feel there's knowledge that is highlighted in this question & answer that isn't nearly as apparent in the other thread.
DefinePlugin doesn't create a variable named process
. It does direct text replacement, so just substitutes strings with other stings during build. For example, if you use process.env.NODE_ENV
, this will be replaced with string "development"
or "production"
or whatever your actuall process.env.NODE_ENV
was set to. Using process.env
for such stuff is more of a convention that some libraries rely on. So, you write process.env.NODE_ENV === "development"
, and after DefinePlugin it will be "development" === "development"
and then this will be replaced with true
or removed altogether during minification and dead code elimination step.