如何在SvelteKit项目的app.html中正确访问使用环境变量
问题根因
你尝试的三种写法全部不生效,是因为SvelteKit的app.html仅支持框架内置的固定占位符(如%sveltekit.head%、%sveltekit.body%、%sveltekit.assets%)的替换,原生不支持直接读取自定义VITE_前缀环境变量,无论是EJS风格的<% %>语法,还是仿照内置占位符写的%VITE_GOOGLE_TAG%,框架默认都不会做解析替换。
正确实现步骤
1. 按运行环境拆分环境变量文件
在项目根目录创建对应环境的变量文件,SvelteKit会根据运行的mode自动加载匹配的文件,无需手动做文件读取逻辑:
- 本地开发环境:根目录
.env,可写测试用的VITE_GTM_ID=test_id - Staging环境:根目录
.env.staging,写入VITE_GTM_ID=xxxxx - Production环境:根目录
.env.production,写入VITE_GTM_ID=yyyyy
注意:所有需要暴露给客户端侧的变量,必须以
VITE_作为前缀,否则仅能在服务端代码中读取,客户端侧无法获取,你之前的变量前缀规则是正确的。
2. 通过服务端钩子动态注入页面内容
不要尝试在app.html里直接引用自定义环境变量,官方推荐的做法是通过服务端钩子的页面转换能力,动态把GTM脚本、自定义meta标签注入到页面对应位置。
操作方式:
如果项目中不存在src/hooks.server.js文件,手动新建该文件,写入如下逻辑:
export async function handle({ event, resolve }) { // 直接从import.meta.env读取对应环境的VITE_变量 const gtmId = import.meta.env.VITE_GTM_ID; return resolve(event, { transformPageChunk: ({ html }) => { // 注入head区域的GTM脚本和测试meta标签 html = html.replace( '%sveltekit.head%', ` <!-- Google Tag Manager --> <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','${gtmId}');</script> <!-- End Google Tag Manager --> <meta name="TESTING" content="${gtmId}"> %sveltekit.head% ` ); // 注入body开头的GTM noscript降级片段 html = html.replace( '%sveltekit.body%', ` <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=${gtmId}" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> %sveltekit.body% ` ); return html; } }) }
3. 配置对应环境的启动/构建命令
在package.json的scripts字段中补充对应环境的命令,确保构建时加载正确的环境文件:
{ "scripts": { "dev": "vite dev", "build:staging": "vite build --mode staging", "build:prod": "vite build", "preview": "vite preview" } }
执行对应命令时,框架会自动加载匹配的.env文件,不需要额外手动传入环境变量。
可选方案:自定义app.html占位符替换
如果你一定要在app.html中直接写自定义占位符(比如你最开始写的%VITE_GOOGLE_TAG%),只需要在上面的transformPageChunk逻辑中增加一行字符串替换即可:
html = html.replaceAll('%VITE_GOOGLE_TAG%', gtmId);
框架本身没有做这个替换逻辑,你可以自己通过字符串替换实现任意占位符的解析,没有额外限制。
内容的提问来源于stack exchange,提问作者Bruno Francisco
相关产品推荐
相关产品推荐

