环境变量

未匹配的标注

AdonisJS 不是为每个环境维护单独的配置文件,而是使用 环境变量 来获取经常在本地环境和生产环境之间变化的值。例如:数据库凭据、用于切换模板缓存的布尔标记等等。

访问环境变量

Node.js 本地允许你使用 process.env 对象访问环境变量。例如:

process.env.NODE_ENV
process.env.HOST
process.env.PORT

但是,我们建议使用 AdonisJS Env 工具,因为它通过添加对验证的支持并提供静态类型信息来进一步改进 API 以配合使用环境变量。

import Env from '@ioc:Adonis/Core/Env'

Env.get('NODE_ENV')

// 用默认值
Env.get('HOST', '0.0.0.0')
Env.get('PORT', 3333)

为什么要验证环境变量?

环境变量从外向内注入到你的应用程序中,你在代码库中几乎无法控制它们。

例如,你的代码库的有一部分依赖于 SESSION_DRIVER 环境变量的存在。

const driver = process.env.SESSION_DRIVER

// 虚拟代码
await Session.use(driver).read()

无法保证在运行程序时 SESSION_DRIVER 环境变量存在并且具有正确的值。因此,你必须对其进行验证,而不是在程序运行出现错误后抱怨 「undefined」 值。

const driver = process.env.SESSION_DRIVER

if (!driver) {
  throw new Error('Missing env variable "SESSION_DRIVER"')
}

if (!['memory', 'file', 'redis'].includes(driver)) {
  throw new Error('Invalid value for env variable "SESSION_DRIVER"')  
}

现在想象一下需要在你的代码库中到处写这些条件? 显然,这不是很好的开发体验

验证环境变量

AdonisJS 允许你在启动应用程序的生命周期的早期可选地验证环境变量,如果任何验证失败,则拒绝启动。

你可以先在 env.ts 文件中定义验证规则。

import Env from '@ioc:Adonis/Core/Env'

export default Env.rules({
  HOST: Env.schema.string({ format: 'host' }),
  PORT: Env.schema.number(),
  APP_KEY: Env.schema.string(),
  APP_NAME: Env.schema.string(),
  CACHE_VIEWS: Env.schema.boolean(),
  SESSION_DRIVER: Env.schema.string(),
  NODE_ENV: Env.schema.enum(['development', 'production', 'test'] as const),
})

同样,AdonisJS 将从验证规则中提取静态类型信息,并为验证的属性提供 IntelliSense。

Schema API

以下是验证环境变量的可用方法列表。

Env.schema.string

验证值以检查它是否存在以及它是否为有效字符串。空字符串无法通过验证,你必须使用其他可选项来允许空字符串。

{
  APP_KEY: Env.schema.string()
}

// 将其标记为可选
{
  APP_KEY: Env.schema.string.optional()
}

你还可以强制该值具有一种预定义格式。

// 必须是有效的主机 (url or ip)
Env.schema.string({ format: 'host' })

// 必须是有效的 URL
Env.schema.string({ format: 'url' })

// 必须是有效的邮件地址
Env.schema.string({ format: 'email' })

在验证 url 格式时,你还可以定义其他选项来强制/忽略 tldprotocol

Env.schema.string({ format: 'url', tld: false, protocol: false })

Env.schema.boolean

转化该值为布尔值的有效字符串表示形式。以下值被视为有效布尔值,并将被转换为 truefalse

  • '1', 'true' are casted to Boolean(true)
  • '0', 'false' are casted to Boolean(false)
{
  CACHE_VIEWS: Env.schema.boolean()
}

// 将其标记为可选
{
  CACHE_VIEWS: Env.schema.boolean.optional()
}

Env.schema.number

转化该值为数字的有效字符串表示形式。

{
  PORT: Env.schema.number()
}

// 将其标记为可选
{
  PORT: Env.schema.number.optional()
}

Env.schema.enum

转化该值为预定义值之一。

{
  NODE_ENV: Env
    .schema
    .enum(['development', 'production'] as const)
}

// 将其标记为可选
{
  NODE_ENV: Env
    .schema
    .enum
    .optional(['development', 'production'] as const)
}

自定义函数

对于所有其他验证用例,你可以定义自定义函数。

{
  PORT: (key, value) => {
    if (!value) {
      throw new Error('Value for PORT is required')
    }

    if (isNaN(Number(value))) {
      throw new Error('Value for PORT must be a valid number')    
    }

    return Number(value)
  }
}
  • 确保在验证后始终返回该值。
  • 返回值可以不同于初始输入值。
  • 我们从返回值推断静态类型。在这种情况下,Env.get('PORT') 是一个数字。

在开发中定义变量

在开发过程中,你可以在项目根目录下的 .env 文件中定义环境变量,AdonisJS 会自动处理它。

// 文件名:.env
PORT=3333
HOST=0.0.0.0
NODE_ENV=development
APP_KEY=sH2k88gojcp3PdAJiGDxof54kjtTXa3g
SESSION_DRIVER=cookie
CACHE_VIEWS=false

变量替换

除了对解析 .env 文件的标准支持外,AdonisJS 还允许变量替换。

HOST=localhost
PORT=3333
// 高亮开始
URL=$HOST:$PORT
// 高亮结束

所有 letternumbers 和美元 ($) 符号后面的下划线 (_) 都被解析为变量。如果你的变量包含任何其他字符,那么你必须将其包裹在花括号 {} 内。

REDIS-USER=foo
// 高亮开始
REDIS-URL=localhost@${REDIS-USER}
// 高亮结束

转义 $ 符号

如果变量的值包含$符号,则必须对其进行转义以防止变量替换。

PASSWORD=pa\$\$word

不要提交 .env 文件

.env 文件不可移植。这意味着,你本地和生产环境上的数据库凭据将始终不同,因此将 .env 推送到版本控制是没有意义的。

你必须将 .env 文件视为本地环境的个人文件,并在生产服务器或登台服务器上创建单独的 .env 文件(并确保其安全)。

.env 文件可以位于服务器上的任何位置。例如,你可以将其存储在 /etc/myapp/.env 中,然后按如下方式通知 AdonisJS。

ENV_PATH=/etc/myapp/.env node server.js

在测试期间定义变量

当应用程序使用 NODE_ENV=test 环境变量启动时,AdonisJS 将查找 .env.test 文件。

.env.test 文件中定义的变量会自动与 .env 文件合并。这允许你在编写测试时使用不同的数据库或不同的会话驱动程序。

在生产环境中定义变量

大多数现代托管服务提供商都为在其 Web 控制台中定义环境变量提供一流的支持。在部署你的 AdonisJS 应用程序之前,请确保你阅读了托管服务提供商的文档并定义了环境变量。

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/adonisjs/5.x/fu...

译文地址:https://learnku.com/docs/adonisjs/5.x/fu...

上一篇 下一篇
贡献者:2
讨论数量: 0
发起讨论 只看当前版本


暂无话题~