代码之家  ›  专栏  ›  技术社区  ›  Jonathan

SvelteKit将数据从服务器传递到浏览器

  •  0
  • Jonathan  · 技术社区  · 3 年前

    我正试图将数据从服务器传递到客户端,以更快地加载我的应用程序,并防止多次调用数据库。

    通过Fetch

    SvelteKit通过 fetch 作用如果您有一个允许自定义获取的端点,这将非常好。但如果你不这样做呢?

    Firebase 是一个没有习俗的完美例子 fetch 作用

    Cookie

    我想我可以使用cookie,但当我设置cookie时,它只会打印“未定义”,永远不会被设置。

    <script lang="ts" context="module">
        import Cookies from 'js-cookie';
        import { browser } from '$app/env';
        import { getResources } from '../modules/resource';
    
        export async function load() {
    
            if (browser) {
    
                // working code would use JSON.parse
                const c = Cookies.get('r');
                return {
                    props: {
                        resources: c
                    }
                };
            } else {
    
                // server
                const r = await getResources();
    
                // working code would use JSON.stringify
                Cookies.set('resources', r);
    
                // no cookies were set?
                console.log(Cookies.get());
                return {
                    props: {
                        resources: r
                    }
                };
            }
        }
    </script>
    

    所以我的代码加载正确,然后在浏览器 load 函数已加载。。。

    肯定有一种行之有效的方法可以做到这一点吗?

    J

    0 回复  |  直到 3 年前
        1
  •  3
  •   Jonathan    2 年前

    看来 official Rich Harris的答案是使用和一个rest api端点and获取。

    路线/东西.ts

    import { getFirebaseDoc } from "../modules/posts";
    
    export async function get() {
        return {
            body: await getFirebaseDoc()
        };
    }
    

    路线/内容.svelte

    export async function load({ fetch }) {
      const res = await fetch('/resources');
      if (res.ok) {
        return {
          props: { resources: await res.json() }
        };
      }
      return {
        status: res.status,
        error: new Error()
      };
    }
    

    就我所说的而言,这似乎是无关的,也是有问题的 here ,但这似乎也是唯一的方法。

    J

        2
  •  1
  •   Ben Woodward    3 年前

    您需要使用一个将cookie注入服务器响应的处理程序(因为加载函数不会向浏览器公开请求或标头,所以我相信它们只是用于加载道具)。此处的示例: https://github.com/sveltejs/kit/blob/59358960ff2c32d714c47957a2350f459b9ccba8/packages/kit/test/apps/basics/src/hooks.js#L42

    https://kit.svelte.dev/docs/hooks#handle

    export async function handle({ event, resolve }) {
        event.locals.user = await getUserInformation(event.request.headers.get('cookie'));
    
        const response = await resolve(event);
        response.headers.set('x-custom-header', 'potato');
        response.headers.append('set-cookie', 'name=SvelteKit; path=/; HttpOnly');
    
    
        return response;
    }
    

    仅供参考:此功能11天前才在 @sveltejs/kit@1.0.0-next.267 : https://github.com/sveltejs/kit/pull/3631

        3
  •  1
  •   cubefox    2 年前

    无需使用fetch!

    您可以随心所欲地获取数据!

    <script context="module">
        import db from '$/firebaseConfig'
    
        export async function load() {
            const eventref = db.ref('cats/whiskers');
            const snapshot = await eventref.once('value');
            const res = snapshot.val();
    
            return { props: { myData: res.data } } // return data under `props` key will be passed to component
        }
    </script>
    
    <script>
        export let myData //data gets injected into your component
    </script>
    
    
    <pre>{JSON.stringify(myData, null, 4)}</pre>
    
    

    下面是一个关于如何使用axios获取数据的快速演示,同样的原理也适用于firebase: https://stackblitz.com/edit/sveltejs-kit-template-default-bpr1uq?file=src/routes/index.svelte


    如果你想 仅在服务器上加载数据 您应该使用“端点”( https://kit.svelte.dev/docs/routing#endpoints )

        4
  •  0
  •   NosiaD    2 年前

    我的解决方案可能会解决这个问题,尤其是对于那些使用(例如:laravel_session)的人来说,如果你想在每个端点上加载时保留cookie数据,那么在你的情况下。

    你应该做的是创建一个接口,在每个api()调用中传递事件

    interface ApiParams {
        method: string;
        event: RequestEvent<Record<string, string>>;
        resource?: string;
        data?: Record<string, unknown>;
    }
    

    现在我们需要修改默认的sveltekit api(),提供整个事件。

    // localhost:3000/users
    export const get: RequestHandler = async (event) => {
        const response = await api({method: 'get', resource: 'users', event});
        // ...
    });
    

    在你的 api() 函数,设置 event.locals 但一定要更新你的 app.d.ts

    // app.d.ts
    declare namespace App {
        interface Locals {
            r: string;
        }
        //...
    }
    
    // api.ts
    export async function api(params: ApiParams) {
        // ...
        params.event.locals.r = response.headers.get('r')
    });
    

    最后,更新您的 hooks.ts

    /** @type {import('@sveltejs/kit').Handle} */
    export const handle: Handle = async ({ event, resolve }) => {
        const cookies = cookie.parse(event.request.headers.get('cookie') || '');
        const response = await resolve(event);
    
        if (!cookies.whatevercookie && event.locals.r) {
            response.headers.set(
                'set-cookie',
                cookie.serialize('whatevercookie', event.locals.r, {
                    path: '/',
                    httpOnly: true
                })
            );
        }
        
        return response;
    });
    
    

    参考我的项目:

    推荐文章