84 Matching Annotations
  1. Oct 2023
  2. Sep 2023
    1. ``js // SSE only supports GET request export async function GET({ url }) { const stream = new ReadableStream({ start(controller) { // You can enqueue multiple data asynchronously here. const myData = ["abc", "def"] myData.forEach(data => { controller.enqueue(data: ${data}\n\n`) }) controller.close() }, cancel() { // cancel your resources here } });

      return new Response(stream, {
          headers: {
              // Denotes the response as SSE
              'Content-Type': 'text/event-stream', 
              // Optional. Request the GET request not to be cached.
              'Cache-Control': 'no-cache', 
          }
      })
      

      } ```

    1. On subsequent page loads using client-side navigation, we can allow the slow data to be streamed in. Client-side navigation will only occur if JavaScript is available, so there are no downsides to using promise streaming. If the user doesn’t have JavaScript, each navigation will trigger a full page load, and we will again wait for all data to resolve.We can switch between these two behaviors using the isDataRequest property on the RequestEvent passed to the load function. When this property is false, the request is for the HTML for the initial page load, and we should wait for all data to resolve. If the property is true, then the request is from SvelteKit’s client-side router and we can stream the data in.

      js export async function load({isDataRequest}) { const slowData = getSlowData(); return { nested: { slow: isDataRequest ? slowData : await slowData } }; }

    2. We can use Promise.race to give our promise a few hundred milliseconds to resolve. Promise.race takes an array of promises, and resolves when any one of those promises resolve. We can pass our delay call and our data fetching call, and conditionally await the result depending on which one resolves first.

      In this example, we race two promises: a 200ms delay and the actual data call we want to make. If the delay resolves first, then the data call is taking longer than 200ms and we should go ahead and render the page with partial data. If the data call resolves first, then we got the data under the time limit and we can render the page with complete data.

      ```js const TIME_TO_RESOLVE_MS = 200; export async function load() { const slowData = getSlowData();

      const result = await Promise.race([delay(TIME_TO_RESOLVE_MS), slowData]);

      return { nested: { slow: result ? result : slowData } }; }

      async function getSlowData() { // randomly delay either 50ms or 1s // this simulates variable API response times await delay(Math.random() < 0.5 ? 50 : 1000); return '😴'; }

      function delay(ms) { return new Promise(res => setTimeout(res, ms)); } ```

    1. Did you know you can now use streaming promises in SvelteKit? No need to import anything - it just works out of the box

      Every property of an object returned by the load function can be a promise which itself can return an object that can have a promise as property, and so on.

      Can build a tree of promises based on data delivery priority.

    1. Otherwise, you can manually call goto instead of history.replaceState is a good way to maintain client-side navigation (no reloads).
    2. I highly recommend using GET forms to implement this as SvelteKit will intercept and retain client-side navigation on form submission. https://kit.svelte.dev/docs/form-actions#get-vs-post Submitting the form will update the URL with the search parameters matching the input names and values.

      ```html

      <form action="/baz"> <label> Query <input name="query"> </label> <label> Sort <input name="sort"> </label> <label> Order <input name="order"> </label> <label> Page <input name="page"> </label> </form>

      ```

  3. Aug 2023
    1. ```js / * .env.development VITE_API_URL=http://localhost:1337/api/blog-posts /

      / * .env.production VITE_API_URL=https://APP.herokuapp.com/api/blog-posts /

      import { error, type Load } from '@sveltejs/kit';

      import { VITE_API_URL } from '$env/static/private';

      export const load: Load = async () => { const res = await fetch(VITE_API_URL); const { data } = await res.json();

      if (res.ok) return { blogs: data }; throw error(404, 'Unable to fetch blogs'); }; ```

    1. SvelteKit will automatically await the fetchPost call before it starts rendering the page, since it’s at the top level. However, it won’t wait for the nested fetchComments call to complete – the page will render and data.streamed.comments will be a promise that will resolve as the request completes. We can show a loading state in the corresponding +page.svelte using Svelte’s await block:

      js export const load: PageServerLoad = () => { return { post: fetchPost(), streamed: { comments: fetchComments() } }; }; ```svelte

      <script lang="ts"> import type { PageData } from './$types'; export let data: PageData; </script> <article> {data.post} </article>

      {#await data.streamed.comments} Loading... {:then value} <br />

        {#each value as comment}
      1. {comment}
      2. {/each}

      {/await} ```

    1. ```js // CSRF

      /* @type {import('@sveltejs/kit').Config} / const config = { kit: { checkOrigin?: true, } };   export default config; ```

    2. ```js // CSP svelte.config.js

      /* @type {import('@sveltejs/kit').Config} / const config = { kit: { csp: { directives: { 'script-src': ['self'] }, reportOnly: { 'script-src': ['self'] } } } };

      export default config; ```

  4. Jul 2023