【问题标题】:How to inject dotenv variables without REACT_APP prefix in create-react-app?如何在 create-react-app 中注入没有 REACT_APP 前缀的 dotenv 变量?
【发布时间】:2020-08-07 05:46:33
【问题描述】:

我有一个项目要从旧版 React 应用迁移到标准 create-react-app 一个(未弹出)。

在遗留项目中,它手动加载带有dotenvdotenv-expand.env文件,并通过webpack注入DefinePlugin

create-react-app直观地支持dotenv,但只能识别带有REACT_APP_前缀的变量。

遗留代码中有很多地方以及其他存储库中使用 process.env.xxx 变量的导入包,因此现在无法在迁移之前使用前缀重命名它们。

在这种情况下,如何让create-react-app 识别没有REACT_APP_ 前缀的dotenv 变量?

顺便说一句,我之前尝试过rewire 构建脚本,对 webpack 进行了一些简单的自定义,比如捆绑 js 和 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';

但似乎dotenvDefinePlugin 更复杂。不确定是否可以以相同的方式实现。

【问题讨论】:

  • 不确定这是否适合您的情况,但如果您使用两种命名样式定义所有变量怎么办? (例如FOO=barREACT_APP_FOO=bar
  • 我看过cra的源码,REACT_APP_的前缀是不能改的。

标签: reactjs webpack create-react-app dotenv


【解决方案1】:

也可以使用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 有点不同

// "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);

【讨论】:

    【解决方案2】:

    Years agoDan Abramov(CRA 的共同创建者)建议重新定义变量以适应 REACT_APP_ 的入口点脚本,然后调用 package.json 中的 react-scripts。

    如果您有更简单的需求来支持这些变量,例如 Netlify 的 COMMIT_REF 或 Gitlab 的 CI_COMMIT_SHA 等 CI 平台变量,您可以在不添加其他脚本的情况下内联设置这些变量。

      "scripts": {
        "start": "react-scripts start",
        "build": "REACT_APP_COMMIT_SHA=$COMMIT_REF$CI_COMMIT_SHA react-scripts build",
        "test": "react-scripts test",
        "eject": "react-scripts eject"
      },
    

    这会将REACT_APP_COMMIT_SHA 设置为它所内置的任何服务的哈希值(因为其他变量将为空)。

    【讨论】:

      【解决方案3】:

      我的解决方案是在构建时创建 config-overrides.js 并修改 process.env。 您仍然在 env 文件中定义了 REACT_APP_[VARIABLE NAME],并在构建时删除了前缀。

      // config-overrides.js
      const {
          override,
      } = require('customize-cra');
      const ENV_PREFIX = /^REACT_APP_/i;
      
      const findWebpackPlugin = (plugins, pluginName) =>
          plugins.find((plugin) => plugin.constructor.name === pluginName);
      
      const overrideProcessEnv = () => (config) => {
          const plugin = findWebpackPlugin(config.plugins, 'DefinePlugin');
          const processEnv = plugin.definitions['process.env'] || {};
      
          const transformedEnv = Object.keys(processEnv)
              .filter((key) => ENV_PREFIX.test(key))
              .reduce((env, key) => {
                  const craKey = key.replace('REACT_APP_', '');
                  env[craKey] = processEnv[key];
                  return env;
              }, {});
      
          plugin.definitions['process.env'] = {
              ...processEnv,
              ...transformedEnv,
          };
      
          return config;
      };
      module.exports = override(
        overrideProcessEnv()
      )

      【讨论】:

        猜你喜欢
        • 2020-08-18
        • 2019-04-06
        • 2020-04-02
        • 1970-01-01
        • 1970-01-01
        • 2019-06-08
        • 2019-10-14
        • 1970-01-01
        • 2019-01-19
        相关资源
        最近更新 更多