context="module" 如何在 Svelte 和 Sapper 中工作?

How context="module" works in Svelte and Sapper?

当我使用 Sapper 构建项目时,每当我从服务器获取数据时,preload 函数是在脚本 context="module" 内声明的,如下所示。

<script context="module">
  export async function preload(page) {
    return await this.fetch(`https://reqres.in/api/users?page=1`)
    .then(res1 => {
      return res1.json()
    }).then(res2 => {
      return { 
        notices: res2.data,
      }
    })
  }
</script>

根据 document

A <script> tag with a context="module" attribute runs once when the module first evaluates, rather than for each component instance. 

但是模块第一次求值时是什么意思

是指组件第一次渲染的时候吗?那么在 onMount 生命周期方法中声明 api fetch 函数是不是和下面的代码一样?

<script>
  onMount(async() => {
    const res = await fetch(`https://reqres.in/api/users?page=1`);
    const json = await res.json();
  })
</script>

是的,确实如此,尽管存在细微差别:context="module" 调用是在创建组件之前执行的。

引用自official docs

it runs before the component is created

这对于产品列表等情况很有用...您不知道要显示哪些产品,因此您获取数据并为结果中的每个项目实例化一个产品组件。

考虑导出 class:

的常规 JavaScript 模块
// Component.js

console.log('evaluating module');

export class Component {
  constructor() {
    console.log('instantiating component');
  }
}

如果将该模块导入您的应用程序,该代码将立即 运行:

import { Component } from './Component.js';

// "evaluating module" has already been logged. This will only happen once
// for the entire application, however many modules import Component.js

const component1 = new Component(); // logs "instantiating component"
const component2 = new Component(); // logs "instantiating component" again

现在我们可以用 Svelte 术语来表达它了:

  • 'evaluating module' 代码是 <script context="module">
  • 中发生的事情
  • 'instantiating component' 代码等同于常规 <script> 标签中发生的事情

当使用 Sapper 或 SvelteKit(相当于 react 世界中的 Next.js)时,SSR 组件无法直接在标签中访问 window 对象,因此您需要等到该组件是“水合的”,或传统上呈现的。这意味着任何使用 window 的库,实际上任何需要在浏览器中 运行 的东西都必须通过 onMount

完成

使用 SSR 时,借助 SvelteKit 等工具,onMount() 不会在服务器上 运行。因此,您的客户端相关代码(例如本地存储访问)可以放在 onMount() 中,它不会抛出服务器错误。

来自 https://www.reddit.com/r/sveltejs/comments/p5p386/trying_to_understand_script_vs_onmount/