Next.js 将 NODE_ENV 传递给客户端

Posted

技术标签:

【中文标题】Next.js 将 NODE_ENV 传递给客户端【英文标题】:Next.js pass NODE_ENV to client 【发布时间】:2019-04-15 10:45:59 【问题描述】:

我正在使用 Next.js 构建一个 React s-s-r 应用程序。

我希望能够在客户端访问 NODE_ENV,因为这将告诉我的应用使用哪些 API 端点。

我正在努力为此寻找合适的方法。当我第一次在服务器上呈现页面时,我想将 NODE_ENV 定义为窗口变量,然后在我进行 API 调用的辅助函数中,我会检查代码是在服务器上还是在客户端上被调用,并根据需要使用windowprocess.env 对象。

对于这样的问题,有人有好的解决方案吗?这一定是一个普遍的问题,但我找不到任何好的解决方案。

【问题讨论】:

Have you tried using the DefinePlugin? 您可以将其包含到 window.__INITIAL_STATE__ = $JSON.stringify(initialState || ); 【参考方案1】:

从 Next.js 9.4 开始,NextJs 现在内置了对环境变量的支持,允许您使用 .env 文件执行以下操作:

.env.local 示例:

DB_HOST=localhost
DB_USER=myuser
DB_PASS=mypassword

如果你想向客户端公开环境变量,你必须在变量前面加上NEXT_PUBLIC_,例如:

NEXT_PUBLIC_API_PORT=4000

如果要使用变量,可以这样使用:process.env.NEXT_PUBLIC_API_PORT

有关文档,请参阅here

【讨论】:

【参考方案2】:

另一个简单的解决方案:

在根文件夹创建 2 个文件:

.env.development
.env.production

根据需要在里面添加变量,例如在 .env.development 文件中:

NEXT_PUBLIC_ENV="development"

在 .env.production 文件中:

NEXT_PUBLIC_ENV="production"

然后用它举例:

console.log('Version: ', process.env.NEXT_PUBLIC_ENV);

【讨论】:

【参考方案3】:

使用 Next 的构建时配置

@DarrylR 已经使用next.config.js 和 接下来是runtime configuration, 不过你也可以使用Next的build-time configuration。

这使您可以将process.env.XXXX 直接放入代码中(如下面的第 3 步所示),您无需导入任何内容。但是,如果您在使用Next.js 本地构建和部署到ZEIT Now 时都应设置环境变量,我不知道您是否可以使用此方法将它们保存在一个文件中(请参阅下面的步骤2) .

运行时配置文档建议您通常要使用构建时配置:

警告:通常您希望使用构建时配置来提供您的配置。原因是运行时配置增加了渲染/初始化开销并且与automatic prerendering不兼容。


步骤:

1。为构建过程设置NODE_ENV

1.1 使用ZEIT Now

如果您使用 ZEIT Now 进行部署,您可以在now.json 中设置env variables used at build time:


  "version": 2,
  "build": 
    "env": 
      "NODE_ENV": "production"
    
  

1.2 本地运行时(可选)

如果您希望在本地运行时也设置NODE_ENV,则now.json 不会设置。 但是您可以通过其他方式设置它,例如:

$ NODE_ENV=production npm run build

或者将package.json中的构建脚本改成

"build": "NODE_ENV=production next build"

如果您愿意,当然也可以为其他脚本设置NODE_ENV,而不是构建。

2。使process.env.NODE_ENV 的下一个内联值

将其添加到next.config.js,如here 所述:

module.exports = 
  env: 
    NODE_ENV: process.env.NODE_ENV
  
;

3。在代码中使用

if (process.env.NODE_ENV === "production") 
  console.log("In production")
 else 
  console.log("Not in production")

【讨论】:

我尝试了这个解决方案,但在我的情况下,next.config.js 中不允许使用 NODE_ENV:github.com/zeit/next.js/blob/master/errors/… 您忘记了实际答案。你只说如何使用变量,而不是如何设置它.... 在第 1 步和第 2 步中,我尝试解释如何设置它。你能解释一下它的哪一部分缺失或令人困惑吗? (实际上,不确定您是指我还是第一条评论。)【参考方案4】:

1。您可以将其包含在 webpack 配置中(使用 dotenv-webpack 依赖项):

require('dotenv').config()

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

module.exports = 
  webpack: (config) => 
    config.plugins = config.plugins || []

    config.plugins = [
      ...config.plugins,

      // Read the .env file
      new Dotenv(
        path: path.join(__dirname, '.env'),
        systemvars: true
      )
    ]

    return config
  

参考:here


2。使用 babel 插件将变量导入整个应用程序:

env-config.js

const prod = process.env.NODE_ENV === 'production'

module.exports = 
  'process.env.BACKEND_URL': prod ? 'https://api.example.com' : 'https://localhost:8080'

.babelrc.js

const env = require('./env-config.js')

module.exports = 
  presets: ['next/babel'],
  plugins: [['transform-define', env]]

index.js

export default () => (
  <div>Loading data from  process.env.BACKEND_URL </div>
)

参考:here

3。使用下一个/配置:

next.config.js

module.exports = 
  publicRuntimeConfig: 
    API_URL: process.env.API_URL
  

index.js

import React from 'react'
import getConfig from 'next/config'

const publicRuntimeConfig = getConfig()
const API_URL = publicRuntimeConfig

export default class extends React.Component 
  static async getInitialProps () 
    // fetch(`$API_URL/some-path`)
    return 
  

  render () 
    return <div>
            The API_URL is API_URL
    </div>
  

参考:here

【讨论】:

谢谢,这是一个非常有帮助的答案! 我认为最后一个是最好的解决方案,谢谢! 最新的NextJS版本是否需要? @SalahAdDin 这取决于您的系统设计。如果您将后端(例如:nodejs)和前端 NextJS 组合在一个项目中,或者使用 NextJS 中的 s-s-r,则仍然需要 env 配置,如果您想将其传递给前端,您可以使用上述方式。否则,就像使用静态导出 NextJS 你不需要这个。

以上是关于Next.js 将 NODE_ENV 传递给客户端的主要内容,如果未能解决你的问题,请参考以下文章

如何将用户查询传递给 Next.js api?

将图像作为道具传递给 Next.js 中的样式化组件

在页面加载时将道具传递给子组件 - 与 next.js 做出反应

如何将可拖动属性传递给 Next.js Image 组件中的 <img>?

NODE_ENV 在 Express 应用程序中没有正确比较 [重复]

Next.js 使用 getServerSideProps 如何将道具从页面传递到组件?