SvelteKit报stream模块外部化500错误,Firebase认证后onMount未执行
问题根因
你使用的googleapis是Node.js专属服务端库,依赖Node.js内置的stream模块,浏览器环境不存在该模块。SvelteKit默认对页面做客户端水合时,你写在context="module"下的load函数会同时在服务端和客户端各执行一次,客户端执行时就会触发该报错,页面渲染直接终止,所以你写的onMount逻辑完全没有执行机会。
另外你直接在页面文件中硬编码服务账号私钥属于高危操作,会直接将敏感权限泄露到前端,被恶意爬取后会导致你的Firebase资源被完全控制。
解决方案
将所有服务端专属逻辑移到SvelteKit专属的服务端代码文件中,保证逻辑只会在服务端运行,不会打包到客户端代码。
具体操作步骤:
- 新建服务端load文件
src/routes/+page.server.js(SvelteKit v1+版本,根路由对应根页面),将现有服务端逻辑全部移到该文件:
// src/routes/+page.server.js import { google } from 'googleapis' // 敏感配置建议从私有环境变量读取,不要硬编码到代码库 const serviceAccount = { "type": "service_account", "project_id": "my-test-project-xxxxxx", "private_key_id": "0d33XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "private_key": "-----BEGIN PRIVATE KEY-----\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-----END PRIVATE KEY-----\n", "client_email": "firebase-adminsdk-xxxxx@my-test-project-xxxxxx.iam.gserviceaccount.com", "client_id": "9999999999999999999999", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-xxxxxx%40my-test-project-xxxxxx.iam.gserviceaccount.com" } async function firebaseAuth() { const scopes = [ 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/firebase.database', ] const jwtClient = new google.auth.JWT( serviceAccount.client_email, null, serviceAccount.private_key, scopes ) return new Promise((resolve, reject) => jwtClient.authorize((error, tokens) => { if (error) { console.log('Error making request to generate access token:', error) reject(error) } else if (!tokens.access_token) { reject(new Error('Provided service account does not have permission to generate access tokens')) } else { resolve(tokens.access_token) } }) ) } export async function load({ fetch }) { const firebaseAccessToken = await firebaseAuth() const res = await fetch( 'https://myfirebasedatabase.app/jsondb.json', { headers: { 'Authorization': `Bearer ${firebaseAccessToken}` }, } ) const data = await res.json() if (!res.ok) { return { status: res.status, error: new Error('Could not fetch data'), } } return { myData : data } }
- 修改
+page.svelte文件只保留客户端逻辑,删除所有服务端相关代码:
<script> import { onMount } from 'svelte' // 服务端返回的数据会自动注入到data属性 export let data const myData = data.myData onMount(() => { console.log(myData) }) </script> <!-- 你的页面UI代码 -->
额外优化建议
服务账号私钥建议通过SvelteKit的$env/static/private读取私有环境变量,不要硬编码在代码中,进一步降低敏感信息泄露风险。
内容的提问来源于stack exchange,提问作者Big_Boulard
相关产品推荐
相关产品推荐

