当从 S3 加载数据时,我应该如何构建 Sapper/Svelte 路由?

How should I structure a Sapper/Svelte route when the data is loaded from S3?

假设我有一堆数据文档,它们是 S3 中的 JSON 文档,每年一个。我通过目录结构在 Sapper 中定义了一条路线:

├── routes
│   ├── _error.svelte
│   ├── _layout.svelte
│   ├── about.svelte
│   ├── data
│   │   ├── [year].svelte

我的 script 块中的代码:

  let yearData;
  onMount(async () => {
    const f = await fetch(yearDataUrl(year), {
      headers: { 'Access-Control-Allow-Origin': '*' }
    });
    const jsonResults = await f.json();
    yearData = jsonResults;
  });

每个数据集在 S3 中为 [s3 url]/[year here].json。导航栏中有一组链接显示每个数据集。我可以让数据以 onMount 的速度加载,但随后点击导航栏链接不会加载新数据。所以 onMount 可能是错误的选择。

我应该如何构建它?另外值得注意的是,我想在以后将这些页面呈现为静态文件(数据很少更改,尤其是前几年)。

有两种选择。第一个也是最惯用的——在你的情况下是正确的,因为听起来你想使用服务器端渲染——是使用 preload:

<script context="module">
  export async function preload(page) {
    const f = await this.fetch(yearDataUrl(page.params.year), {
      headers: { 'Access-Control-Allow-Origin': '*' }
    });

    return {
      yearData: await f.json()
    };
  }
</script>

<script>
  export let yearData;
</script>

<!-- use yearData here -->

预加载函数将 运行 在创建组件之前为其提供 yearData 属性。每当 page.params 改变时,preload 将再次 运行,设置一个新的属性。

因为这在服务器和客户端上都有效(因此使用 this.fetch 而不是 fetch,它在两种环境下都有效),您将获得服务器呈现的页面,而不是而不是在 onMount 运行 秒后闪烁到页面中的加载消息。

为了完整起见,第二个选项是使用 page store:

<script>
  import { stores } from '@sapper/app';

  const { page } = stores();

  let yearData;

  $: if (process.browser) {
      fetch(yearDataUrl($page.params.year))
        .then(f => f.json())
        .then(data => {
          yearData = data;
        });
  }
</script>

在这种情况下 yearData 不会 服务器呈现。 (为了完整起见,您还需要处理竞争条件和错误,这不是 preload 的问题。)