”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 为什么应该始终向环境变量添加类型安全?

为什么应该始终向环境变量添加类型安全?

发布于2024-11-08
浏览:447

一点背景

如果您已经编码了一段时间,您就会知道环境变量的重要性及其所扮演的角色,以及找出由于项目中未设置该死的环境变量而导致的错误的痛苦, 哈哈!

今年早些时候,我在一家基于产品的初创公司担任全栈开发人员实习生。随着项目的增长,环境变量的数量也随之增加。而且,每个人都在不同的分支上开发不同的功能,所以我们不知道是否有人在他们的分支中引入了一些新的环境变量,这些变量后来被合并到主分支中。当我尝试部署我的分支时,这产生了问题,我知道一个新的环境变量已添加到项目中。

然后,后来我接触到了 T3 堆栈,它有一个出色的解决方案,可以为环境变量添加类型安全。我什至不知道存在这样的解决方案。在你最意想不到的时候学习新东西总是感觉很好。 T3 堆栈使用 zod 和 @t3-oss/env-nextjs 包为您的应用程序添加类型安全性,我非常喜欢。之后,我承诺无论如何都会保证我的环境变量的类型安全。

如果您正在开始一个新项目,或者已经在团队中工作,我强烈建议您向您的环境添加类型安全。仅添加此内容将节省您解决代码库中问题的精力。

以下是如何将其添加到您的项目中的方法。很简单。

佐德是什么?

Zod 是一个轻量级、快速的模式声明和验证库。架构可以是从简单字符串、数字到复杂对象类型的任何内容。

基本用法

import {z} from 'zod';

const myBoolean = z.boolean();

myBoolean.parse('true'); // throws error
myBoolean.parse(true) // valid

创建嵌套对象架构

import { z } from 'zod';

const userSchema = z.object({
    name: z.string(),
    age: z.number(),
    address: z.object({
        house_no: z.string(),
        locality: z.string(),
        city: z.string(),
        state: z.string(),
    })
});

您可以创建简单的对象架构或创建嵌套对象架构。

什么是 t3-oss/env-nextjs?

它只是一个包,它将帮助我们为环境变量添加类型安全性

让我们创建类型安全的环境变量

在项目的根目录创建一个 env.js 文件。

import {createEnv} from "@t3-oss/env-nextjs"; import {z} from "zod";

export const env = createEnv({
  /*
   * Serverside Environment variables, not available on the client.
   * Will throw if you access these variables on the client.
   */
  server: {
    DB_URI: z.string().url(),
  },
  /*
   * Environment variables available on the client (and server).
   *
   * You'll get type errors if these are not prefixed with NEXT_PUBLIC_.
   */
  client: {
    NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().min(1),
  },
  /*
   * Due to how Next.js bundles environment variables on Edge and Client,
   * we need to manually destructure them to make sure all are included in bundle.
   *
   * You'll get type errors if not all variables from `server` & `client` are included here.
   */
  runtimeEnv: {
    DB_URI: process.env.DATABASE_URL,
    NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY:
      process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY,
  },
});

用法

import {env} from '@/env';

const CLERK_PUBLISHABLE_KEY = env.NEXT_PUBLISHABLE_KEY;

如果将光标悬停在 NEXT_PUBLISHABLE_KEY 上方,您可以看到该值被输入为字符串,这意味着我们的环境变量现在已输入。

我们添加了类型安全的环境变量,但这不会在每次构建时运行。我们必须将新创建的文件导入到 next.config.js 文件中。您可以使用 unjs/jiti 包。

首先,从 npm 安装 jiti pacakge。

import { fileURLToPath } from "node:url";
import createJiti from "jiti";
const jiti = createJiti(fileURLToPath(import.meta.url));

jiti("./app/env");

使用 import.meta.url 时,它提供您当前正在使用的文件的 URL。但是,它包含您可能不想要的 file:/// 前缀。要删除该前缀,您可以使用 node:url 模块中的 fileURLToPath 函数。

例如:

import {fileURLToPath} from 'node:url';

// Convert the file URL to a path
const filename = fileURLToPath(import.meta.url);

现在,如果您没有所需的环境变量,您将看到这样的错误 -

Why you should always add type safety to your environment variables?

如何为 Node.js 项目中的环境变量添加类型安全?

import dotenv from "dotenv";
import { z } from "zod";

dotenv.config();

const schema = z.object({
  MONGO_URI: z.string(),
  PORT: z.coerce.number(),
  JWT_SECRET: z.string(),
  NODE_ENV: z
    .enum(["development", "production", "test"])
    .default("development"),
});

const parsed = schema.safeParse(process.env);

if (!parsed.success) {
  console.error(
    "❌ Invalid environment variables:",
    JSON.stringify(parsed.error.format(), null, 4)
  );
  process.exit(1);
}

export default parsed.data;

在 Node.js 项目中,我们将简单地创建一个 zod 模式并根据 process.env 解析它,以检查是否设置了所有 env 变量。

用法

import express from "express";
import env from "./env";

const app = express();
const PORT = env.PORT || 5000; // PORT is type safe here....

app.listen(PORT, () => {
console.log("Connected to server on PORT ${PORT}");
connectDB();
});

这就是为环境变量添加类型安全的方法。我希望您在本教程中学到一些新东西。

快乐编码! ?

版本声明 本文转载于:https://dev.to/shaancodes/why-you-should-always-add-type-safety-to-your-environment-variables-24lk?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 为什么HTML无法打印页码及解决方案
    为什么HTML无法打印页码及解决方案
    无法在html页面上打印页码? @page规则在@Media内部和外部都无济于事。 HTML:Customization:@page { margin: 10%; @top-center { font-family: sans-serif; font-weight: bo...
    编程 发布于2025-04-30
  • HTML格式标签
    HTML格式标签
    HTML 格式化元素 **HTML Formatting is a process of formatting text for better look and feel. HTML provides us ability to format text without us...
    编程 发布于2025-04-30
  • 组件驱动CSS框架:开发者的新选择
    组件驱动CSS框架:开发者的新选择
    核心要点 Web Components日益流行,对能够处理这种开发类型的CSS框架的需求也日益增长。传统的CSS框架(如Bootstrap或Foundation)由于其广泛的内置样式和代码,可能会限制开发人员使用Web Components。 组件驱动型CSS框架(如Pattern Lab、SUI...
    编程 发布于2025-04-30
  • 如何在Chrome中居中选择框文本?
    如何在Chrome中居中选择框文本?
    选择框的文本对齐:局部chrome-inly-ly-ly-lyly solument 您可能希望将文本中心集中在选择框中,以获取优化的原因或提高可访问性。但是,在CSS中的选择元素中手动添加一个文本 - 对属性可能无法正常工作。初始尝试 state)</option> < op...
    编程 发布于2025-04-30
  • 在Java中使用for-to-loop和迭代器进行收集遍历之间是否存在性能差异?
    在Java中使用for-to-loop和迭代器进行收集遍历之间是否存在性能差异?
    For Each Loop vs. Iterator: Efficiency in Collection TraversalIntroductionWhen traversing a collection in Java, the choice arises between using a for-...
    编程 发布于2025-04-30
  • 如何高效地在一个事务中插入数据到多个MySQL表?
    如何高效地在一个事务中插入数据到多个MySQL表?
    mySQL插入到多个表中,该数据可能会产生意外的结果。虽然似乎有多个查询可以解决问题,但将从用户表的自动信息ID与配置文件表的手动用户ID相关联提出了挑战。使用Transactions和last_insert_id() 插入用户(用户名,密码)值('test','test...
    编程 发布于2025-04-30
  • `ConfigurationManager.AppSettings.Set`为何不保存App.Config更改?
    `ConfigurationManager.AppSettings.Set`为何不保存App.Config更改?
    app.config值修改quandary 在提供的代码片段中,尝试修改app.config文件中的值。但是,这种修改并不像预期的那样持续。要识别此问题的来源,让我们深入研究提供的代码并探索潜在问题。代码段: lang =“ Russian”; 私有void main_formclosing(对象...
    编程 发布于2025-04-30
  • 如何避免Go语言切片时的内存泄漏?
    如何避免Go语言切片时的内存泄漏?
    ,a [j:] ...虽然通常有效,但如果使用指针,可能会导致内存泄漏。这是因为原始的备份阵列保持完整,这意味着新切片外部指针引用的任何对象仍然可能占据内存。 copy(a [i:] 对于k,n:= len(a)-j i,len(a); k
    编程 发布于2025-04-30
  • C++20 Consteval函数中模板参数能否依赖于函数参数?
    C++20 Consteval函数中模板参数能否依赖于函数参数?
    [ consteval函数和模板参数依赖于函数参数在C 17中,模板参数不能依赖一个函数参数,因为编译器仍然需要对非contexexpr futcoriations contim at contexpr function进行评估。 compile time。 C 20引入恒定函数,必须在编译时进行...
    编程 发布于2025-04-30
  • Java开发者如何保护数据库凭证免受反编译?
    Java开发者如何保护数据库凭证免受反编译?
    在java 在单独的配置文件保护数据库凭证的最有效方法中存储凭据是将它们存储在单独的配置文件中。该文件可以在运行时加载,从而使登录数据从编译的二进制文件中远离。使用prevereness class import java.util.prefs.preferences; 公共类示例{ 首选项...
    编程 发布于2025-04-30
  • 如何使用Regex在PHP中有效地提取括号内的文本
    如何使用Regex在PHP中有效地提取括号内的文本
    php:在括号内提取文本在处理括号内的文本时,找到最有效的解决方案是必不可少的。一种方法是利用PHP的字符串操作函数,如下所示: 作为替代 $ text ='忽略除此之外的一切(text)'; preg_match('#((。 &&& [Regex使用模式来搜索特...
    编程 发布于2025-04-30
  • MySQL中如何保持UTF8编码的表格输出格式?
    MySQL中如何保持UTF8编码的表格输出格式?
    在使用包含非英语字符的MySQL数据库时,请使用MySQL命令行表达式输出格式格式化,而在切换到utf8编码时,表格查询结果的输出格式可能会中断。本文提供了解决此格式问题的综合指南。简短答案 使用-default-character-character-set = utf8选项将mysql cli...
    编程 发布于2025-04-30
  • 如何使用Java.net.urlConnection和Multipart/form-data编码使用其他参数上传文件?
    如何使用Java.net.urlConnection和Multipart/form-data编码使用其他参数上传文件?
    使用http request 上传文件上传到http server,同时也提交其他参数,java.net.net.urlconnection and Multipart/form-data Encoding是普遍的。 Here's a breakdown of the process:Mu...
    编程 发布于2025-04-30
  • FastAPI自定义404页面创建指南
    FastAPI自定义404页面创建指南
    response = await call_next(request) if response.status_code == 404: return RedirectResponse("https://fastapi.tiangolo.com") else: ...
    编程 发布于2025-04-30
  • 如何使用Python的请求和假用户代理绕过网站块?
    如何使用Python的请求和假用户代理绕过网站块?
    如何使用Python的请求模拟浏览器行为,以及伪造的用户代理提供了一个用户 - 代理标头一个有效方法是提供有效的用户式header,以提供有效的用户 - 设置,该标题可以通过browser和Acterner Systems the equestersystermery和操作系统。通过模仿像Chro...
    编程 发布于2025-04-30

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3