Webpack:使用 DefinePlugin 和 DotEnv 未定义 process.env

IT技术 reactjs webpack webpack-dev-server
2021-04-29 18:51:05

我想从我的 .env 文件中获取我的变量,但我总是得到 undefined

这是我的 js 代码:

require('dotenv').config();
class Header extends React.Component{
    constructor(props){...}
    render(){
        console.log("NODE ENV", process.env.NODE_ENV);
        console.log("REACT_APP_MYAPP", process.env.REACT_APP_MYAPP);
        ...
   }
}

这打印:

NODE_ENV 开发

REACT_APP_MYAPP undefined

在我的 package.json 中有:

"scripts":{
      "start" : "webpack-dev-server --config webpack.dev.js",
      "build" : "webpack --config webpack.prod.js"
 }

在我的 webpack.dev.js 中:

const webpack = require("webpack");
const merge = require("webpack-merge");
const path = require("path");
const common = require("./webpack.common.js");

module.exports = merge.smart(common, {
    devServer: {
        contentBase: path.resolve(__dirname, "dist"),
        hot: true,
        overlay: {
            warnings: true,
            errors: true
        },
        inline :true,
        historyApiFallback: true,
        port: 8085
    },
    devtool: "inline-sourcemap",
    optimization: {
        namedModules: true
    },
    plugins: [
        new webpack.HotModulReplacementPlugin(),
        new webpack.DefinePlugin({
            "process.env.NODE_ENV": JSON.stringify("development"),
            "process.env.REACT_APP_MYAPP": JSON.stringify(process.env.REACT_APP_MYAPP)
        })
    ],
    mode: "development"
});

我把我的 .env 文件放在我项目的根目录下,在 webpack.dev.js 和 package.json 旁边:

REACT_APP_MYAPP= http://localhost:8080/

所以我认为,在文件中获取变量并不成功。

请问如何获取代码中REACT_APP_MYAPP值?

4个回答

穿过又深又黑的兔子洞,您将了解到以下事实:

  • Webpack 5 不再提供process其他 Node.js 变量
  • 的角色DefinePlugin需要重新定义。
  • 传递给的值DefinePlugin必须是字符串化的,即使它们是字符串。
  • EnvironmentPlugin 考虑到 Webpack 5,这让事情变得更加混乱。
  • process.env 不是你应该在前端使用的东西。
  • 您可以使用polyfills重新添加process重新添加其他人,但它不再可用有原因的
  • dotenv-wepack既不是必需的,也不是要走的路。
  • 使用的原因process.env是全局访问变量。但它是乘坐错误航班的乘客。我们可以删除它,而是直接访问预期的变量:
plugins: [
    new DefinePlugin({
        // With dotenv (values must be stringified)
        ...Object.entries(dotenv.config().parsed).reduce((acc, curr) => ({...acc, [`${curr[0]}`]: JSON.stringify(curr[1]) }), {}),
        
        // Without dotenv 
        'myString': JSON.stringify('IAmAString')
    })
  ]

在前端:

declare var myString: string;
console.log(myString); // 'IAmAString'

如果您有多个带有变量的对象,那么抽象字符串化是有意义的:

// Create a function to stringify values
function stringifyValues(object: {[key: string]: any;}){
    return Object.entries(object).reduce((acc, curr) => ({...acc, [`${curr[0]}`]: JSON.stringify(curr[1]) }), {} as { [key: string]: string; });
}

// use with DefinePlugin
plugins: [
    new DefinePlugin({
      ...stringifyValues(dotenv.config().parsed),
      ...stringifyValues(dotenv.config({ path: '/.env.special' }).parsed),
      'myObject': stringifyValues({ 
            name: 'Object', 
            description: 'to be an object' 
      })
    })
  ]

如果你真的想访问process.env

plugins: [
    new DefinePlugin({
        // this might expose confidential data about your environment
        'process.env': JSON.stringify(process.env),

        // the correct way
        'process.env.USERNAME': JSON.stringify('Donald Hump')
    })
  ]

在前端:

declare var process: any;
console.log(process) // will NOT work, because process hasn't been injected
console.log(process.env); // will work but risky
console.log(process.env.USERNAME); // correct: 'Donald Hump'

在 start 中添加 REACT_APP_MYAPP 的第一个解决方案不起作用。但第二种解决方案奏效了。

解决方案:

require('dotenv').config()在 my 中添加文件webpack.dev.js并替换:

   new webpack.DefinePlugin({
        "process.env.NODE_ENV": JSON.stringify("development"),
        "process.env.REACT_APP_MYAPP": JSON.stringify(process.env.REACT_APP_MYAPP)
    })

    new webpack.EnvironmentPlugin(['NODE_ENV', 'REACT_APP_MYAPP']);

谢谢!

有几种方法可以使这项工作发挥作用。

最简单的测试是将您的更改"start" : "webpack-dev-server --config webpack.dev.js","start" : "REACT_APP_MYAPP=http://localhost:8080/ node webpack-dev-server --config webpack.dev.js",

这将注入环境变量,它将在 webpack 构建过程中可用。无论何时使用npmnode运行命令,您都可以使用此技术例如,NODE_ENV='development REACT_MY_APP=http://localhost:8080/ node myapp.js两者都将在process.env.

你也可以require('dotenv').config()在你的webpack.dev.js. 然后它将在您使用 DefinePlugin 期间设置。

通常,您不使用该npm start命令来运行您的开发服务器。

随着应用程序的增长,您应该查看Webpack Environment Plugin然后您可以将 .env 用于“生产”构建设置,在生产 webpack.prod.js 中需要它,同时使用插件设置您的默认/回退环境变量。

它适用于我的自定义 React 应用程序模型,仅当我不在变量名称中包含“REACT_APP_”时:

在 webpack.config.js 中:

// Node import
const path = require('path');

const webpack = require('webpack');

require('dotenv').config();

module.exports = [
   plugins: [
    new webpack.EnvironmentPlugin(['NODE_ENV', 'API'])
  ],
]

在 .env 中:

NODE_ENV=development
API=http://localhost:5000

当我部署应用程序时(例如在 Netlify 上),我从生产环境变量中排除了 NODE_ENV。