如何从前端访问环境变量

Posted

技术标签:

【中文标题】如何从前端访问环境变量【英文标题】:How to access environment variables from the front-end 【发布时间】:2019-12-30 23:28:58 【问题描述】:

我在编译脚本中定义了几个环境变量。但是,我只能从 webpack.config.babel.js 文件中访问这些变量,并且我需要在反应代码(前端)中访问这些变量。

我在这里找到了一种方法:https://blog.container-solutions.com/deploying-configurable-frontend-web-application-containers,但我认为放入元标记数据(例如数据库密码)并不是一个好主意。尽管如此,尝试只为 .env 文件做的方式对我不起作用:(

那么,我的问题是?

编辑我:

我已经应用了@robi932 的明智建议,但它对我不起作用:(

webpack.config.babel.js

plugins: [
    new htmlWebpackPlugin(
        template: "./src/client/index.html",    //where is our template
        filename: "../index.html",              //where we are going to put our index.html inside the output directory
        minify: 
            collapseWhitespace: true,
            removeComments: true,
            removeRedundantAttributes: true,
            removeScriptTypeAttributes: true,
            removeStyleLinkTypeAttributes: true,
            useShortDoctype: true
                    
    ),
    new MiniCssExtractPlugin(
        filename: "css/bundle.css",
        minify: 
            collapseWhitespace: true,
            removeComments: true,
            removeRedundantAttributes: true,
            removeScriptTypeAttributes: true,
            removeStyleLinkTypeAttributes: true,
            useShortDoctype: true
                     
    ),
    new webpack.DefinePlugin(
        URL_FEB_API: JSON.stringify(process.env.URL_FEB_API)
    )

我定义了 const URL_FEB_API 以便稍后在我的 react-js 代码中使用它,但是当我尝试访问它时,它不起作用:(

console.log("HomeLF1Content process.env.URL_FEB_API: " + URL_FEB_API);

console.log("HomeLF1Content process.env.URL_FEB_API: " + process.env.URL_FEB_API);

这是我在 package.json 中的编译脚本:

    "clean": "rm -rf ./dist",
    "compile-dev": "NODE_ENV=development URL_FEB_API=http://localhost:4000/api/feb/graphiql webpack -d --config ./webpack.config.babel.js --progress",
    "dev": "npm run clean && npm run compile-dev && cross-env NODE_ENV=development nodemon --exec babel-node src/server/server.js --ignore ./src/client"

我做错了什么?

解决方案:

感谢https://medium.com/@trekinbami/using-environment-variables-in-react-6b0a99d83cf5@Shubham Jain 提供的这个链接,我终于找到了一个很好的解决方案来为前端定义环境变量。

然后,我将解释我为解决问题所采取的步骤。

首先,我们需要为每个环境提供两个 .env 文件。现在,我们有两个环境:开发和生产。因此,.env.development 将是我们要配置所有开发变量的文件,而 .env 将是我们要配置所有生产变量的文件。

第二,要选择之前创建的文件之一,我们需要告诉节点要编译哪个文件,所以在我们的编译脚本中,我们必须定义一个我们正在调用的变量NODE_ENV,我们将使用“开发”或“生产”进行初始化。

开发脚本:

"clean": "rm -rf ./dist",
"compile-dev": "NODE_ENV=development webpack -d --config ./webpack.config.babel.js --progress",
"dev": "npm run clean && npm run compile-dev && cross-env NODE_ENV=development nodemon --exec babel-node src/server/server.js --ignore ./src/client",

生产脚本:

"clean": "rm -rf ./dist",
"compile": "NODE_ENV=production webpack -p --config ./webpack.config.babel.js --progress",
"start": "npm run clean && npm run compile && cross-env NODE_ENV=production babel-node src/server/server.js --ignore ./node_modules",

第三,现在,我们将在 webpack.config.babel.js 文件中添加一些代码,以根据 NODE_ENV 变量的值选择环境变量。

import webpack from "webpack";
import path from "path";
import dotenv from "dotenv";
import fs from "fs";
/**
 * Code to get the values of environment variables during compilation time for the front-end
 */
//Get the root path. Our .env files and webpack.config.babel.js files are in the root path
const currentPath = path.join(__dirname);
const basePath = currentPath + "/.env";
// We're concatenating the environment name to our filename to specify the correct env file!
const envPath = basePath + "." + process.env.NODE_ENV;
// Check if the file exists, otherwise fall back to the production .env
const finalPath = fs.existsSync(envPath) ? envPath : basePath;
// Set the path parameter in the dotenv config
const fileEnv = dotenv.config( path: finalPath ).parsed;
// reduce it to a nice object, the same as before
const envKeys = Object.keys(fileEnv).reduce((prev, next) => 
  prev[`process.env.$next`] = JSON.stringify(fileEnv[next]);
  return prev;
, );

第四,在 webpack.config.babel.js 文件中,在 plugin 部分,我们必须在编译项目时添加对这个变量的访问:

plugins: [
    //With this entry we can get access to the environment variable for front-end
    new webpack.DefinePlugin(envKeys),
],

最后,要在前端访问这些变量,我们可以使用process.env.VARIABLE_NAME 轻松访问它们,其中 VARIABLE_NAME 是文件 .env 或 . env.development.

请投票给@Shubham Jain 给出的答案,因为他的链接对我非常有用。

【问题讨论】:

你说的是服务器的 .env 还是客户端的 .env? 我正在讨论客户的 .env。使用服务器环境变量我没有问题。谢谢。 看看有没有帮助medium.com/@trekinbami/… 【参考方案1】:

有一个非常简单的方法:

第一步:转到应用程序的根文件夹并创建一个名为 .env 的文本文件。

第二步:在新文件中创建您的自定义变量。 Create React App(CRA) 在每个自定义变量上强制使用前缀 REACT_APP。请注意,不带前缀的变量在打包时会被忽略。

REACT_APP_CLIENT_ID=jfjffffaddfeettgydgdffv
REACT_APP_KEY=aaddddawrfffvvvvssaa

第三步:将它们分配给变量,将它们打印到屏幕等,但它们在您的 javascript 文件中是只读的。

console.log(process.env.REACT_APP_CLIENT_ID); 
console.log(process.env.REACT_APP_KEY);

第四步:有一个名为 NODE_ENV 的内置环境变量。您可以从 process.env.NODE_ENV 访问它。这个变量会根据你当前所处的模式而改变。当你运行 npm start 时,它等于'development',当你运行 npm test 时,它等于'test',当你运行 npm run build 时,它等于'生产'。此变量很特殊,因为它可用于根据您的模式访问不同的环境配置。例如,如果您有不同的数据库用于生产和开发(通常是为了防止干扰),您可以使用它有条件地访问某些变量。您无法手动覆盖 NODE_ENV 的事实可防止开发人员意外将开发版本部署到生产环境。

第五步:打开 .gitignore 文件。我喜欢将 .env 和其他环境变量放在#misc 下。

为什么即使在执行了这些过程之后它仍然无法正常工作?

确保您在每个变量上都使用了前缀 REACT_APP

确认 .env 文件中的变量名与您的 js 文件中的变量名匹配。例如,.env 中的 REACT_APP_KEY 与 process.env.REACT_APP_KY

如果开发服务器正在运行,请停止它,然后使用 npm start 它重新运行。我真的很挣扎(变量是未定义的错误)。每次更新 .env 文件时,都需要停止服务器并重新运行它,因为环境变量仅在构建期间更新(变量未定义错误)。

从变量的值中删除引号。

错误

REACT_APP_KEY=”AHEHEHR”

REACT_APP_KEY=AHEHEHR

注意:将敏感内容放入环境变量并不能使它们安全。它们在构建过程中被注入到捆绑文件中,因此任何人都可以通过检查您的文件来查看它们。我发现它们的最大用途是在将我的代码推送到远程存储库之前隐藏信息。

【讨论】:

这假设 OP 正在使用 create-react-app,但似乎不是,或者至少不能保证。【参考方案2】:

我想你想要直截了当的解决方案。有一个名为dotenv-webpack 的第三方库。更多信息here

const Dotenv = require('dotenv-webpack');

module.exports = 
  ...
  plugins: [
    new Dotenv()
  ]
  ...
;

【讨论】:

【参考方案3】:

Webpack 可以帮助您将变量从配置发送到您的反应应用程序,即定义插件。 看这里https://webpack.js.org/plugins/define-plugin/

【讨论】:

嗨@robi932!!!我已经应用了您的解决方案,但是我做错了,因为它对我不起作用:( 你重启了webpack服务器吗?【参考方案4】:

如何在 React 项目中配置 .evn 文件

    只需创建 .env 文件。 需要把你的配置放到 .env 文件中,比如
REACT_APP_FIREBASE_REALTIME_DB=https://sample.firebaseio.com/
REACT_APP_FIREBASE_API=FFYTYt67567yhhhmnbdfgjd7erehfjdhfjd

注意:您必须提及REACT_APP,然后您才能提及您的标识符

例如: REACT_APP_FIREBASE_REALTIME_DB

    将代码放入您的首选文件
process.env.REACT_APP_FIREBASE_REALTIME_DB
process.env.REACT_APP_FIREBASE_API

【讨论】:

【参考方案5】:
- Create .env file in root folder

 - Open to .env file

     --> REACT_APP_API_KEY= API KEY
    **NOTE** starting with the prefix REACT_APP_ (IMPORTANT)

 - Access it use process.env
  eg  const  REACT_APP_API_KEY,REACT_APP_TEMPLATE_ID,REACT_APP_SERVICE_ID = process.env

 - And use with template string
 eg emailjs.send(`$REACT_APP_SERVICE_ID`,`$REACT_APP_TEMPLATE_ID`, values, `$REACT_APP_API_KEY` )
      .then((response) => 
         console.log('SUCCESS!', response.status, response.text);
      , (err) => 
         console.log('FAILED...', err);
      );

    

When you do any changes or need to create at .env file don't forget to restart  
appliction "npm start"

【讨论】:

【参考方案6】:

以上方法在我的 Windows 设备上对我不起作用,所以我想分享一下。

npm install dotenv

.env 文件

URL_FEB_API = https://example.com

example.js

const dotenv = require("dotenv");

dotenv.config( path: ".env" );

const url = process.env.URL_FEB_API;
console.log(url);

【讨论】:

如果这对您不起作用,请随时联系我

以上是关于如何从前端访问环境变量的主要内容,如果未能解决你的问题,请参考以下文章

如何从公用文件夹中访问环境变量?

如何从 Node 应用程序客户端访问环境变量

如何使用python 2.7从特定文件中读取环境变量

如何从 phpunit.xml 而不是应用程序配置文件访问环境变量

如何将环境变量传递给前端 Web 应用程序?

如何使用 mod_wsgi 从 django 访问 mod_ssl 环境变量?