You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Svelte客户端获取Bearer Token遇导入错误,求可行实现方案

Solution for Passing Read-Only Access Token to Client in SvelteKit

Your original approach fails because any file importing server-only code (like $lib/server/fetchaccesstoken) can't be imported into client-side components (e.g., +layout.svelte). Here are two clean, maintainable ways to solve this:


Solution 1: Centralized Server-Side Fetch + Layout Data Prop

This is the recommended approach—fetch the token once on the server, cache it, and pass it to all client components via the layout.

Step 1: Add Caching to Your Server Token Function

Update $lib/server/fetchaccesstoken.ts to cache the token (avoids repeated calls to the auth server):

let cachedToken: { value: string; expiresAt: number } | null = null;

export async function fetchAccessToken() {
  // Return cached token if it's still valid
  if (cachedToken && Date.now() < cachedToken.expiresAt) {
    return cachedToken.value;
  }

  // Fetch new token from auth server
  const response = await fetch('https://your-auth-server/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${import.meta.env.VITE_API_KEY}` // Your API key here
    },
    body: JSON.stringify({
      // Add your auth request parameters (e.g., grant_type, scope)
    })
  });

  if (!response.ok) throw new Error('Failed to fetch access token');
  const data = await response.json();

  // Cache token with expiry (subtract 1 minute to avoid edge cases)
  cachedToken = {
    value: data.access_token,
    expiresAt: Date.now() + (data.expires_in * 1000) - 60000
  };

  return cachedToken.value;
}

Step 2: Fetch Token in Root Layout Server Load

Create +layout.server.ts in your root directory to fetch the token once and pass it to the client:

import { fetchAccessToken } from '$lib/server/fetchaccesstoken';

export async function load() {
  return {
    accessToken: await fetchAccessToken()
  };
}

Step 3: Access Token in Client Layout

In +layout.svelte, receive the token via the data prop and make it available to child components (use a store for easy access):

<script>
  export let data;
  import { writable } from 'svelte/store';

  // Create a store to share the token with child components
  export const accessTokenStore = writable(data.accessToken);
</script>

<!-- Your layout markup here -->

Use Token in Child Components

Import the store from the layout in any client component:

<script>
  import { accessTokenStore } from '$layout';
  let accessToken;
  
  accessTokenStore.subscribe(token => accessToken = token);
</script>

{#if accessToken}
  <!-- Make API requests using the token -->
  <button on:click={() => fetch('https://api.example.com/data', {
    headers: { 'Authorization': `Bearer ${accessToken}` }
  })}>Fetch Data</button>
{/if}

Solution 2: API Route for Client-Side Token Refresh (Optional)

If you need to refresh the token without reloading the page, create a server-side API route that returns the token:

Create routes/api/token/+server.ts

import { fetchAccessToken } from '$lib/server/fetchaccesstoken';
import type { RequestHandler } from './$types';

export const GET: RequestHandler = async () => {
  const token = await fetchAccessToken();
  return new Response(JSON.stringify({ token }), {
    headers: { 'Content-Type': 'application/json' }
  });
};

Call the Route from Client

In your client code, fetch a new token when needed:

async function refreshToken() {
  const response = await fetch('/api/token');
  const { token } = await response.json();
  accessTokenStore.set(token);
}

Key Notes

  • Your API key stays secure in server-only code, never exposed to the client.
  • The cached token reduces redundant calls to your auth server.
  • This approach avoids duplicating code across multiple +page.server.js files.

内容的提问来源于stack exchange,提问作者vasculum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 15:45:05