跳至主要内容

仅服务器端模块

就像一位好朋友,SvelteKit 会帮你保守秘密。当在同一个仓库中编写后端和前端代码时,很容易意外地将敏感数据导入到你的前端代码中(例如,包含 API 密钥的环境变量)。SvelteKit 提供了一种方法来完全防止这种情况:仅服务器端模块。

私有环境变量

$env/static/private$env/dynamic/private 模块只能被导入到仅在服务器上运行的模块中,例如 hooks.server.js+page.server.js

仅服务器端实用程序

$app/server 模块包含一个用于从文件系统读取资产的 read 函数,同样只能被服务器端代码导入。

你的模块

你可以通过两种方式将自己的模块设置为仅服务器端模块

  • 在文件名中添加 .server,例如 secrets.server.js
  • 将它们放在 $lib/server 中,例如 $lib/server/secrets.js

工作原理

每当你拥有导入仅服务器端代码(无论是直接还是间接)的公共代码时...

$lib/server/secrets
export const const atlantisCoordinates: never[]atlantisCoordinates = [/* redacted */];
src/routes/utils
export { export atlantisCoordinatesatlantisCoordinates } from '$lib/server/secrets.js';

export const const add: (a: any, b: any) => anyadd = (a, b) => a: anya + b: anyb;

src/routes/+page
<script>
	import { add } from './utils.js';
</script>

...SvelteKit 将会报错

Cannot import $lib/server/secrets.js into public-facing code:
- src/routes/+page.svelte
	- src/routes/utils.js
		- $lib/server/secrets.js

即使公共代码 — src/routes/+page.svelte — 仅使用 add 导出而不是秘密的 atlantisCoordinates 导出,秘密代码也可能最终出现在浏览器下载的 JavaScript 中,因此导入链被认为是不安全的。

此功能也适用于动态导入,甚至包括插值导入,如 await import(`./${foo}.js`),但有一个小问题:在开发过程中,如果在公共代码和仅服务器端模块之间存在两个或多个动态导入,则在代码第一次加载时不会检测到非法导入。

像 Vitest 这样的单元测试框架不会区分仅服务器端代码和公共代码。因此,在运行测试时(由 process.env.TEST === 'true' 确定),非法导入检测会被禁用。

进一步阅读

在 GitHub 上编辑此页面

上一页 下一页