I'm working on a static site generator where I'd like to be able to support both reactive JavaScript interaction and standard load-a-fresh-page-into-the-browser hyperlinks. It occurred to me that something like Svelte might be a good fit for this; I could use the server-side rendering support to generate HTML for all my pages, and then I could compile and ship JavaScript components with hydratable: true
to support the dynamic features.
One issue I thought of with this approach is that most of my project's components will be entirely static content: just HTML and hyperlinks, without any state or event handlers, and I won't change the props except when I generate a new HTML file for a different page. If I naively generate JavaScript to hydrate all those components at page load time, I could end up with a much larger bundle (and more work done at runtime) than I actually need.
Does Svelte offer any way to optimize this situation? Can I somehow check if a component is a pure function of its props so I can avoid hydrating it if I don't need to? Or is the compiler smart enough to do that for me?
This is a good question that we don't currently have a simple answer for.
It is possible to determine whether an individual component has values that can change — svelte.compile(...)
returns an object with a vars
property, which is an array of all the values inside the component. Inspecting this array will tell you which values are never reassigned to or mutated. (It won't tell you if a component has event handlers that have side-effects but which don't affect state, which would also be necessary to determine whether a component is entirely static. That's information that we could add in a future 3.x release.)
But it's only half the story. Consider a component that declares a name
prop...
<script>
export let name;
</script>
<h1>Hello {name}!</h1>
...and which is used in your app like so:
<Greeting name="world"/>
As far as the compiler is concerned when it compiles the <Greeting>
component, the name
value could change at any moment, so it's unsafe to treat it as entirely static. But if it could understand your app more holistically, it would be able to replace {name}
with world
, which would have various benefits.
When hydrating, Svelte assumes that there could be a discrepancy between the existing DOM and what's supposed to be there. In many situations it would be safe to assume otherwise, and skip checking subtrees it knew to be static, which would obviate the need to include them in the generated JS.
As a compiler, Svelte is unusually well-positioned to be able to take advantage of these techniques, but it's work that we haven't undertaken yet. Ideally we'll be able to upgrade the compiler in such a way that your apps will get smaller without anything needing to change. If you're keen to start experimenting with what's possible in the meantime, then the vars
property returned from svelte.compile(...)
(and also the ast
property, I suppose) is the place to start.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With