如何判断 Svelte 组件是否完全是静态内容?

How to tell if a Svelte component is entirely static content?

我正在开发一个静态站点生成器,我希望它能够支持反应式 JavaScript 交互和标准的加载新页面到浏览器超链接。我突然想到像 Svelte 这样的东西可能很适合这个;我可以使用服务器端呈现支持为我的所有页面生成 HTML,然后我可以使用 hydratable: true 编译和发布 JavaScript 个组件以支持动态功能。

我用这种方法想到的一个问题是我项目的大部分组件将完全是静态内容:只有 HTML 和超链接,没有任何状态或事件处理程序,我不会更改道具除非我为不同的页面生成一个新的 HTML 文件。如果我天真地生成 JavaScript 来在页面加载时混合所有这些组件,我最终可能会得到比我实际需要的更大的包(并且在运行时完成更多的工作)。

Svelte 是否提供任何方法来优化这种情况?我能以某种方式检查一个组件是否是它的 props 的纯函数,这样我就可以在不需要的时候避免对它进行补水吗?或者编译器是否足够聪明可以为我做这件事?

这是一个很好的问题,我们目前没有简单的答案。

可以确定单个组件是否具有可以更改的值 — svelte.compile(...) returns 具有 vars 属性,这是组件内部所有值的数组。检查这个数组会告诉你哪些值永远不会被重新分配或改变。 (它不会告诉您组件是否具有具有副作用但 影响状态的事件处理程序,这对于确定组件是否完全静态也是必要的。这是我们可以在未来 3.x 版本中添加的信息。)

但这只是故事的一半。考虑一个声明 name prop...

的组件
<script>
  export let name;
</script>

<h1>Hello {name}!</h1>

...在您的应用中使用的是这样的:

<Greeting name="world"/>

就编译器而言,在编译 <Greeting> 组件时,name 值可能随时更改,因此将其视为完全静态是不安全的。但是,如果它能够更全面地理解您的应用程序,它就能够将 {name} 替换为 world,这将带来各种好处。

补水时,Svelte 假设现有的 DOM 与应该存在的存在差异。在许多情况下,以其他方式假设并跳过检查它知道是静态的子树是安全的,这将避免将它们包含在生成的 JS 中的需要。

作为编译器,Svelte 非常有能力利用这些技术,但这是我们尚未开展的工作。理想情况下,我们能够升级编译器,使您的应用程序变得更小,而无需更改任何内容。如果您同时热衷于开始尝试可能发生的事情,那么从 svelte.compile(...) 返回的 vars 属性(以及 ast 属性,我假设)是开始的地方。