仅限服务器模块
就像好朋友一样,SvelteKit 会保守你的秘密。在同一个存储库中编写后端和前端时,很容易意外地将敏感数据导入前端代码(例如,包含 API 密钥的环境变量)。SvelteKit 提供了一种完全防止这种情况的方法:单一事实来源
¥Like a good friend, SvelteKit keeps your secrets. When writing your backend and frontend in the same repository, it can be easy to accidentally import sensitive data into your front-end code (environment variables containing API keys, for example). SvelteKit provides a way to prevent this entirely: server-only modules.
私有环境变量(Private environment variables)
¥Private environment variables
$env/static/private
和 $env/dynamic/private
模块只能导入到仅在服务器上运行的模块中,例如 hooks.server.js
或 +page.server.js
。
¥The $env/static/private
and $env/dynamic/private
modules can only be imported into modules that only run on the server, such as hooks.server.js
or +page.server.js
.
仅服务器实用程序(Server-only utilities)
¥Server-only utilities
$app/server
模块包含一个用于从文件系统读取资源的 read
函数,同样只能通过在服务器上运行的代码导入。
¥The $app/server
module, which contains a read
function for reading assets from the filesystem, can likewise only be imported by code that runs on the server.
你的模块(Your modules)
¥Your modules
你可以通过两种方式使自己的模块仅用于服务器:
¥You can make your own modules server-only in two ways:
将
.server
添加到文件名,例如secrets.server.js
¥adding
.server
to the filename, e.g.secrets.server.js
将它们放在
$lib/server
中,例如$lib/server/secrets.js
¥placing them in
$lib/server
, e.g.$lib/server/secrets.js
工作原理(How it works)
¥How it works
任何时候你有面向公众的代码导入仅限服务器的代码(无论是直接还是间接)...
¥Any time you have public-facing code that imports server-only code (whether directly or indirectly)...
export const atlantisCoordinates = [/* redacted */];
export { export atlantisCoordinates
atlantisCoordinates } from '$lib/server/secrets.js';
export const const add: (a: any, b: any) => any
add = (a, b) => a: any
a + b: any
b;
<script>
import { add } from './utils.js';
</script>
...SvelteKit 将出错:
¥...SvelteKit will error:
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 中,因此导入链被认为是不安全的。
¥Even though the public-facing code — src/routes/+page.svelte
— only uses the add
export and not the secret atlantisCoordinates
export, the secret code could end up in JavaScript that the browser downloads, and so the import chain is considered unsafe.
此功能还适用于动态导入,甚至是像 await import(
./${foo}.js)
这样的插值导入,但有一个小警告:在开发过程中,如果面向公众的代码和仅服务器模块之间有两个或更多动态导入,则第一次加载代码时不会检测到非法导入。
¥This feature also works with dynamic imports, even interpolated ones like await import(`./${foo}.js`)
, with one small caveat: during development, if there are two or more dynamic imports between the public-facing code and the server-only module, the illegal import will not be detected the first time the code is loaded.
像 Vitest 这样的单元测试框架不区分仅限服务器的代码和面向公众的代码。因此,在运行测试时,非法导入检测被禁用,由
process.env.TEST === 'true'
决定。¥[!NOTE] Unit testing frameworks like Vitest do not distinguish between server-only and public-facing code. For this reason, illegal import detection is disabled when running tests, as determined by
process.env.TEST === 'true'
.
进一步阅读(Further reading)
¥Further reading