通过 Vite 的方式
Warnning
需要注意的是,这种方式如果使用不当,可能会不小心把敏感信息暴露到客户端!
新版本的 Remix 基于 Vite,而 Vite 本身提供了读取环境变量的方法,所以可以使用 Vite 的 import.meta.env.<环境变量名> 来使用环境变量中的值。前提是环境变量以 VITE_ 为前缀命名。
参考: https://vitejs.dev/guide/env-and-mode#env-variables-and-modes
在项目下创建一个 .env 文件,填入如下内容:
VITE_EXAMPLE=abc
此时项目里可以通过 import.meta.env.VITE_EXAMPLE 来调用这个环境变量。
Vite 导入环境变量的类型提示
Info
注意确保你的 TypeScript 能够读取到
env.d.ts文件。
如果想要类型提示,可以在项目下创建 env.d.ts 文件,其中填入如下内容:
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_EXAMPLE: string
}
这样再使用 import.meta.env. 时就能够自动提示有哪些可以调用的环境变量了。
通过 Remix 建议的方式
在 Remix 的服务端代码中可以通过 process.env.<环境变量名> 来使用环境变量。
这种方式只能在 ActionFunctions 和 LoaderFunctions 里访问环境变量,不能直接在 export default 的组件里使用。这也意味着不能直接在浏览器端访问环境变量中的值(通过 Vite 的方式是可以那样做的)。
这里先说下使用例子,后面再说怎么在浏览器端访问环境变量值(直接在浏览器端的代码里使用 Vite 的那种方式也是可以的,只是说不推荐)。
假设当前已经有个 .env 文件,且其中有如下值:
API_KEY=abc
BASE_URL=http://example.com
像下面这样使用这些环境变量:
// Loaders
export async function loader({ request }) {
const apiKey = process.env.API_KEY
const baseUrl = process.env.BASE_URL
const response = await fetch(`${baseUrl}/data?api_key=${apiKey}`)
const data = await response.json()
return data
}
// Actions
export async function action({ request }) {
const apiKey = process.env.API_KEY
const baseUrl = process.env.BASE_URL
const response = await fetch(`${baseUrl}/submit?api_key=${apiKey}`, {
method: 'POST',
body: JSON.stringify({ data: 'example' }),
})
return response
}
在浏览器中使用
/* eslint-disable react-dom/no-dangerously-set-innerhtml */
// 如果使用了 ESLint,那么可能需要在文件开头使用这一行 ⬆️
export async function loader() {
return json({
ENV: {
baseUrl: process.env.BASE_URL,
},
})
}
export function Root() {
const data = useLoaderData<typeof loader>()
return (
<html lang="en">
<head>
<Meta />
<Links />
</head>
<body>
<Outlet />
<script
dangerouslySetInnerHTML={{
__html: `window.ENV = ${JSON.stringify(
data.ENV
)}`,
}}
/>
<Scripts />
</body>
</html>
)
}
现在可以在浏览器里通过 window.ENV.baseUrl 来调用环境变量了。
Process Env 类型提示
Info
注意确保你的 TypeScript 能够读取到
env.d.ts文件。
当通过 process.env.<环境变量名> 去调用环境变量时,可以发现没有提供提示,可以在项目下添加一个 env.d.ts 文件,其中填入如下内容,以此增加 process.env. 中的提示内容:
namespace NodeJS {
interface ProcessEnv {
// 无须指定任何特定前缀
readonly 环境变量名称: string
}
}
ESLint 读取不到 process
ESLint 可能会提示:
Unexpected use of the global variable 'process'. Use 'require("process")' instead.
这是因为这条 node/prefer-global/process 规则要求的,可以禁用它。