【问题标题】:How to use different .env files with nextjs?如何在 nextjs 中使用不同的 .env 文件?
【发布时间】:2020-04-15 04:08:59
【问题描述】:

我希望有不同的环境变量配置文件,并能够在我的下一个项目中使用它们。我看到了dotenv 的例子。

但我不喜欢在 .env 文件中定义变量,也在 config.next.js 文件中定义它们。如果由于某种原因我将变量放在 .env 文件中但忘记将它们放在 config.next.js 文件中,则代码开始出现问题。 有没有更高效的方法?

我在 package.json 中的脚本:

"scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start",
    "lint": "eslint pages --ext .ts,.tsx,.js",
    "test": "jest",
    "commit": "git-cz",
    "dev:production": "dotenv next"
},

我的 .env 变量

TITULO=react, typescript, material ui App

组件

import { NextPage }          from 'next';
import { FunctionComponent } from 'react';

interface HelloWorldProps {
  nombre: string,
  saludo?: string
}


const HelloWorld: FunctionComponent<HelloWorldProps> = ({ nombre, saludo = 'noches' }: HelloWorldProps) => (
  <>
    <h1>Hola {nombre} buenas {saludo}</h1>
    {/* eslint-disable-next-line multiline-ternary */}
    <h2>{process.env.TITULO ? 'hola' : 'adios'}</h2>
  </>
);

const Home: NextPage = () => <HelloWorld nombre="cristian" />;

export default Home;

【问题讨论】:

    标签: reactjs environment-variables next.js


    【解决方案1】:

    您可以使用dotenv-cli,然后在您的package.json 中为不同的环境设置不同的.env 文件。比如:

    {
      ...
      "scripts": {
        "dev:production": "dotenv next", // Uses .env file
        "dev:staging": "dotenv -e .env.staging next" // Uses .env.staging file
      }
      ...
    }
    

    【讨论】:

    • 它给了我一个dotenv not found 的错误。虽然我已经安装了它并且可以正常使用本地文件
    • dotenv -e .env.development next build 仍在加载生产配置
    【解决方案2】:

    npm i dotenv

    然后将以下代码添加到next.config.js,重新启动应用程序即可!

    // next.config.js
    
    require('dotenv').config()
    const webpack = require('webpack')
    
    module.exports = {
      webpack: (config) => {
        config.plugins.push(
          new webpack.EnvironmentPlugin(process.env)
        )
        return config
      }
    }
    

    如果您的 .env 文件与 next.config.js 不在同一文件夹中,请添加路径到您的配置,如下所示,

    require('dotenv').config({ path: 'path/to/.env' })
    

    【讨论】:

    • 添加 config.plugins.push 行对我来说适用于 Next 9.4.0;谢谢!
    【解决方案3】:

    Next 9.4 内置了对 .env 文件的支持:https://nextjs.org/docs/basic-features/environment-variables

    但是,如果您想拥有多个 .env 文件,例如:

    • .env.development
    • .env.staging
    • .env.prestaging
    • .env.production

    使用内置的环境变量支持是不可能的。目前官方支持的环境只有 3 个,分别是:“开发”、“测试”、“生产”。 next dev 使用“开发”环境,next build &amp;&amp; next start 使用“生产”环境。

    如果你需要为生产环境构建,但使用“.env.staging”,那么你需要添加env-cmd包,并将这一行添加到你的package.json:

    "build:staging": "env-cmd -f .env.staging yarn build && yarn start"
    

    接下来将使用“.env.staging”变量进行生产构建。

    【讨论】:

    • 下一个开发者使用“开发”,下一个构建和下一个启动使用“生产”环境,那么如何在“测试”环境中运行?
    • 这很适合在本地启动应用程序。但是,当您在我的情况下进行部署时,它不会加载环境变量。我有一个默认的 .env 并且在构建时我添加了 .env.staging 例如。在已部署的版本上,仅显示来自 .env 的变量?你能帮我解决这个问题吗?
    • 这没问题,但是一旦在任何地方运行,它就无法与 Docker 构建一起使用,因为您需要使用不同的命令进行构建。这是解决方案:github.com/andrewmclagan/react-env
    • 关于cmd-env 的好消息。顺便说一句,看起来它应该是 nextJs 的一个选项 =)
    • @WendellPereira 确实如此,我们需要安装外部库来处理环境,这太荒谬了——'
    【解决方案4】:

    Next 9.4 support out of the box environment variablesincluded support for multiple environments

    新环境变量支持

    • 环境变量默认仅在 Node.js 环境中可用
    • NEXT_PUBLIC_ 为前缀的环境变量会暴露给浏览器

    暴露环境变量

    Next.js 允许您使用环境变量文件 (.env) 公开变量,其中包括对多种环境的支持。它的工作原理是这样的:

    • .env - 包含所有环境的环境变量
    • .env.local - 所有环境的局部变量覆盖
    • .env.[environment] - 一个环境的环境变量。例如:.env.development
    • .env.[environment].local - 一种环境的局部变量覆盖。例如:.env.development.local

    【讨论】:

    • 但是如何启动使用.env.staging的应用程序?
    【解决方案5】:

    你可以通过以下两种方式在 nextjs 中拥有不同的 .env 文件:

    1.使用 env-cmd 包

    在脚本中提供环境文件的路径,例如:

    "scripts": {
        "start": "env-cmd path/to/prod/env/file next start",
        "start:dev": "env-cmd path/to/prod/env/file next dev",   
        "build:dev": "env-cmd path/to/dev/env/file next build",
        "build:test": "env-cmd path/to/test/env/file next build",
        "build:stage": "env-cmd path/to/stage/env/file next build",
        "build": "env-cmd path/to/stage/prod/file next build",        
    },
    

    2。使用 dotenv 包

    在你的 next.config.js 文件中添加以下内容:

    require("dotenv").config({ path: `${process.env.ENVIRONMENT}` });
    
    module.exports = {
          // your configs
    }
    

    并在您的脚本中,提供 ENVIRONMENT 变量,例如:

    "scripts": {
        "start": "ENVIRONMENT=path/to/prod/env/file next start",
        "start:dev": "ENVIRONMENT=path/to/dev/env/file next dev",
        "build:dev": "ENVIRONMENT=path/to/dev/env/file next build",
        "build:test": "ENVIRONMENT=path/to/test/env/file next build",
        "build:stage": "ENVIRONMENT=path/to/stage/env/file next build",
        "build": "ENVIRONMENT=path/to/stage/prod/file next build",        
    },
    

    注意:不要把你的 .env* 文件放在根目录下,否则 NEXT 会自动从你的 .evn* 文件中挑选,它只支持生产和开发阶段。所以它会忽略其他 .env.my-stage 文件。

    【讨论】:

    • 嗨。 next start 命令是否需要 env-cmd?我认为变量是在构建期间内联的,next start 只是运行该构建,对吗?
    • @RichardTrembecký,是的,没错。如果没有生产构建,next start 将无法工作,env-cmd 在构建期间注入变量。
    • 未找到模块:错误:无法解析 'C:\admin\node_modules\dotenv\lib' 中的 'fs'
    【解决方案6】:

    大多数这些答案的问题是它们违背了“构建一次运行无处不在”的原则,实际上我们大多数人都使用这种技术构建和运行 Docker 容器。像这样有多个构建命令是不可能的,这是不好的做法。

    最好让您的环境在运行时可用。我们通过window.__ENV创建了一个允许下一个静态优化并且仍然具有运行时环境变量的包

    https://github.com/andrewmclagan/react-env

    这通过在运行时从白名单环境变量生成环境配置对象来工作:

    {
      ...
      "scripts": {
        "dev": "react-env -- next dev", // where .env.${APP_ENV}
        "start": "react-env --env APP_ENV -- next start" // where .env.${APP_ENV}
      }
      ...
    }
    

    【讨论】:

    • 来自其他环境,对 NextJS 这样做完全傻眼,感谢您成为理性的声音。
    • 也搜索了一段时间,只是对接下来处理 env 的“默认”方式感到困惑 - 谢谢
    • 构建后如何从流程环境中选择API基础URL?如果在构建过程中实际 URL 未知,并且将在启动时传递给 Docker 容器?
    • 查看这个包的文档。你可以这样做。
    【解决方案7】:

    如果您想在没有任何 3rd 方库的情况下使用它,您可以直接在脚本开头使用 NEXT_PUBLIC_ 从脚本中公开它,例如:

    "scripts": {
      "start": "NEXT_PUBLIC_APP_ENV=development next dev"
    }
    

    比使用它

    console.log(process.env.NEXT_PUBLIC_APP_ENV); // >>> development
    

    【讨论】:

    • 我猜有人没有正确,或者可能是版本问题,但我在很多项目中都使用它
    【解决方案8】:

    对于任何有兴趣使用.yml 文件来轻松管理环境变量的人,我是这样做的。

    devDependencies中安装插件yenv

    next.config.js 中添加以下配置:

    const path = require("path");
    const yenv = require("yenv");
    const { PHASE_DEVELOPMENT_SERVER } = require("next/constants");
    
    module.exports = (phase) => {
      const isDev = phase === PHASE_DEVELOPMENT_SERVER;
      const NEXT_ENV = isDev ? "development" : process.env.APP_ENV;
      const rawEnv = yenv(path.resolve(".env.yml"), { raw: true, env: NEXT_ENV });
      
      return {
        ...some other config,
        env: getEnvVars(rawEnv, isDev).raw,
        compress: true,
      };
    };
    
    function getEnvVars(rawEnv, dev) {
      const NEXT_PUBLIC = /^NEXT_PUBLIC_/i;
      const raw = Object.keys(rawEnv)
        .filter((key) => NEXT_PUBLIC.test(key))
        .reduce((env, key) => {
          env[key] = rawEnv[key];
          return env;
        }, {});
      // 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 };
    }
    

    现在只需在 package.json 脚本中根据环境添加不同的构建命令。

    "scripts": {
        "dev": "node server.js",
        "build:production": "APP_ENV=production next build",
        "build:staging": "APP_ENV=staging next build",
        "start": "NODE_ENV=production node server.js"
      },
    

    现在您可以通过单个文件 .env.yml 使用您的环境变量,如下所示:

    base:
      NEXT_PUBLIC_SECRET_KEY : ""
      NEXT_PUBLIC_ANOTHER_SECRET: ""
    
    development:
      ~compose: base
      NEXT_PUBLIC_SECRET_KEY: "bnbnfjf"
    
    staging:
      ~compose: base
      NEXT_PUBLIC_SECRET_KEY: "absadsad"
    
    production:
      ~compose: base
      NEXT_PUBLIC_SECRET_KEY: "lasjdasodsdsad"
    
    

    现在您可以调用npm run build:production 来加载生产环境变量,调用npm run build:staging 来暂存环境变量。

    这为您的用例提供了任意数量的环境的好处。您只需添加一个构建命令,并更新 .env.yml 中的环境变量,一切顺利。

    【讨论】:

      猜你喜欢
      • 2021-12-17
      • 1970-01-01
      • 2020-04-20
      • 1970-01-01
      • 1970-01-01
      • 2017-05-03
      • 2021-07-03
      • 2021-10-25
      • 1970-01-01
      相关资源
      最近更新 更多