在前端项目中使用环境变量

736 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情

在 Next 项目中,我们有如下启动命令:

"dev": "cross-env NEXT_ENV=dev next dev",

可以看到,我们在启动时会向 NodeJS 环境中注入 NEXT_ENV 这个变量,问题是:如何在项目中(运行时)使用这个变量?

根据 NextJS官方文档的说明,在 next.config.js 中进行配置:

// next.config.js
const nextConfig = {
	...
	env: {
	    customKey: 'my-value',
	},
}

然后就可以在代码中通过 process.env.customKey 获得该值:

function Page() {
  return <h1>The value of customKey is: {process.env.customKey}</h1>
}

export default Page

无法访问的情况

但是,这里不能使用 ES 解构 的方式访问,如:

// ❌ Bad
const _env = process.env
const { customKey } = _env

NextJS 官方也有解释:

Next.js will replace process.env.customKey with 'my-value' at build time. Trying to destructure process.env variables won't work due to the nature of webpack DefinePlugin.

大意是:NestJS 在构建时使用了 webpack DefinePlugin,但也是由于 Webpack DefinePlugin 的限制,不支持这样使用。

我们顺藤摸瓜,再看下 webpack.DefinePlugin 的用法,使用时也是直接用字符串来定义属性的键

new webpack.DefinePlugin({
	...
  'typeof window': JSON.stringify('object'),
  'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
});

Note that because the plugin does a direct text replacement, the value given to it must include actual quotes inside of the string itself. Typically, this is done either with alternate quotes, such as '"production"', or by using JSON.stringify('production').

注意,由于此插件是直接替换字面量的方式,特别是在包含了引号的情况下。换句话说,在构建时,只有判断字面量完全一致才会执行替换,否则替换失败。

FAQ

我仍有一个好奇点,为什么定义的 NodeJS 变量会在运行时生效?

If you perform logging in your development build but not in the production build you might use a global constant to determine whether logging takes place. That's where DefinePlugin shines, set it and forget it rules for development and production builds.

DefinePlugin 文档中说明,它可以用来定义一个全局变量,方便我们在运行时处理不同的操作,如:在开发环境不走登录。

因此把 Node env 挂载到了 global 对象上,所以我们也能在运行时 JS 代码里访问。不管是 NextJS 还是 umiJS,构建工具凡使用到的 webpack,都是遵循这个规律。

Links

next.config.js: Environment Variables | Next.js

DefinePlugin | webpack

如果文章对你有帮助,记得点赞、收藏加关注,thx~🥳🥳