Search code examples
reactjswebpackcreate-react-appdotenv

How to inject dotenv variables without REACT_APP prefix in create-react-app?


I have a project to migrate from legacy React app to standard create-react-app one (not ejected).

In legacy project, it manually loads .env files with dotenv and dotenv-expand and injects through webpack DefinePlugin.

create-react-app intuitively supports dotenv but can only recognize variables with REACT_APP_ prefix.

There are so many places in legacy code also along with imported packages in other repositories that are using process.env.xxx variables, so it is impossible for now to rename them with prefix before migration.

In this case, how can I make create-react-app recognize dotenv variables without REACT_APP_ prefix?

BTW, I tried to rewire build script before with some simple customizations over webpack, like bundling js and css:

const path = require('path');
const rewire = require('rewire');
const defaults = rewire('react-scripts/scripts/build.js');

let webpackConfig = defaults.__get__('config');

webpackConfig.output.filename = 'static/js/[name].js';
webpackConfig.optimization.splitChunks = { cacheGroups: { default: false } };
webpackConfig.optimization.runtimeChunk = false;
webpackConfig.plugins.find(plugin => plugin.__proto__.constructor.name === 'MiniCssExtractPlugin').options.filename = 'static/css/[name].css';
webpackConfig.plugins.find(plugin => plugin.__proto__.constructor.name === 'MiniCssExtractPlugin').options.moduleFilename = () => 'static/css/[name].css';

But it seems dotenv and DefinePlugin are more complicated. Not sure if it can be achieved in the same way.


Solution

  • Also use rewire

    // "start": "node start.js"
    const rewire = require('rewire');
    
    process.env.NODE_ENV = 'development';
    
    let getClientEnvironment = rewire('react-scripts/config/env.js');
    getClientEnvironment.__set__(
      'REACT_APP',
      /(^REACT_APP_|API|DEPLOY|SECRET|TOKEN|URL)/,
    );
    
    let configFactory = rewire('react-scripts/config/webpack.config.js');
    configFactory.__set__('getClientEnvironment', getClientEnvironment);
    
    let start = rewire('react-scripts/scripts/start.js');
    start.__set__('configFactory', configFactory);
    

    build is a little bit different

    // "build": "node build.js"
    const rewire = require('rewire');
    
    process.env.NODE_ENV = 'production';
    
    let getClientEnvironment = rewire('react-scripts/config/env.js');
    getClientEnvironment.__set__(
      'REACT_APP',
      /(^REACT_APP_|API|DEPLOY|SECRET|TOKEN|URL)/,
    );
    
    let configFactory = rewire('react-scripts/config/webpack.config.js');
    configFactory.__set__('getClientEnvironment', getClientEnvironment);
    
    let webpackConfig = configFactory('production');
    
    let build = rewire('react-scripts/scripts/build.js');
    build.__set__('config', webpackConfig);