Svelte Summit 2020 notes and experience

Written byKalanKalan
💡

If you have any questions or feedback, pleasefill out this form

This post is translated by ChatGPT and originally written in Mandarin, so there may be some inaccuracies or mistakes.

Introduction

Svelte is one of my favorite front-end frameworks, thanks to its simple syntax, flexibility, the author's philosophy, and the various ways to implement animations and transitions. I've previously written a few articles sharing my thoughts on Svelte:

The Svelte Summit took place on October 18, 2020, and due to the pandemic, it was streamed live online, featuring a total of 7 hours and 17 talks. Here, I’d like to record some interesting talks and share my insights.

The Zen of Svelte

This talk discusses the various "philosophies" within Svelte, which are similar to the philosophies found in Python.

Svelte starts with the syntax to minimize the learning curve, making it accessible even for those outside the front-end realm or complete beginners. The official documentation provides insight as well; in addition to reading the instructional text, there's also a REPL where you can directly manipulate the code to see the actual effects.

Svelte Official Documentation

The author, Rich Harris, mentioned in his talk Rethink Reactivity:

Rich Harris - Rethinking reactivity

Frameworks are not tools for organizing your code; frameworks are tools for organizing your mind. — Rich Harris

For example, the emergence of React sparked a revolution in front-end concepts such as Component, Immutable, Reactivity, and State, laying the foundation for many subsequent frameworks that fundamentally changed front-end development practices. More important than the "syntax" of these frameworks is the underlying concepts and design philosophies they aim to convey.

The author also noted that tools like jQuery have enabled individuals without a formal programming background to participate in web development. From this, we can glean a bit about the author’s vision for Svelte.

Note: I discuss this in more detail in this article, which you may find interesting.

harris-jquery

If you understand HTML, CSS, and JavaScript, it means you can write Svelte; and vice versa. Unlike traditional template engines, Svelte compiles differently. Template engines often work in conjunction with the backend, passing variables to the template engine to generate HTML code; in Svelte, all the code is compiled into corresponding JavaScript (when not in SSR mode) and can be executed dynamically.

I appreciate this philosophy—programming doesn't necessarily require one to become an engineer, just as cooking doesn't mean you have to be a chef. Sometimes, you might just want to solve everyday problems.

From another perspective, some may wonder if it's beneficial to skip the basics of JavaScript and jump straight into learning Svelte. My view is: "It depends on your goals."

If you plan to become a competent front-end engineer, you will eventually need to understand the underlying principles. However, if your goal is simply to create a web page to solve your problems, then a lack of deep foundational knowledge is not a significant issue.

This talk also references the article The Zen of Just Writing CSS. In Svelte, you can directly write styles within components, achieving a unified effect of HTML, CSS, and JavaScript. Svelte handles hashing, effectively avoiding naming conflicts. In React, we often use CSS-in-JS solutions to avoid these issues, but is there a better way to handle styling?

For example, with styled-components, we might write:

const Component = styled.div`
  padding: ${props => props.padding}px;
`

// With theme
const ThemeComponent = styled.div`
  background-color: ${props => props.theme.mainColor};
`;

This is a very useful and interesting approach, allowing us to define theme in context and dynamically access it when declaring components. However, due to the dynamic declaration, these styles must be executed at runtime, as we cannot know which props may be passed in, meaning styles cannot be fully statically generated.

In Svelte, you can render an additional standalone stylesheet using SSR:

result: {
	js,
	css,
	ast,
	warnings,
	vars,
	stats
} = svelte.compile(source: string, options?: {...})

Styles declared in components will be placed in css, allowing for a separation of styles and code. Whether this is good or bad may be subjective; for common constants like shared colors and fonts, it may not be as convenient (compared to solutions like styled-components).

Prototyping with Svelte

Svelte's built-in transition and animation directives are incredibly useful, enabling even designers to quickly create prototypes to validate their ideas. You can also see results rapidly in the REPL, making it a great tool for designers who want to challenge engineers with their designs.

How does Svelte's crossfade function work

The crossfade transition is quite handy. What is crossfade? It's when elements move between two areas, creating a crossfade effect.

In this talk, the speaker explains how crossfade is implemented in Svelte, and how it's applied in his products.

Crossfade uses the concept of keys in Svelte; each time it executes, it looks for the corresponding key node, calculates the positions between the two, and applies a transition for the animation. Because it can utilize the built-in transition directive, it's relatively easy to use. (The example is taken from the official documentation.)

Svelte Animation

Svelte has a built-in directive called animate. When using the each loop, if the elements in the list change, it will trigger the animation. The usage looks like this:

{#each list as item (item.id)}
  <div animate:flip>
    ...
  </div>
{/each}

In Svelte, there’s a built-in animate directive called flip, which is a technique for animation combining First, Last, Invert, and Play. First, we record the positions of the elements before and after changes (First, Last), then calculate the differences (width, height, movement offsets, etc.), and finally execute the animation. For a detailed explanation, refer to Tech Bridge's article — FLIP Technique Review.

Svelte simplifies this series of calculations into flip, providing you with an out-of-the-box solution. When combined with crossfade, the effect looks like this:

Every movement has a transition, making it feel much smoother, right?

Unlocking The Power of Svelte Action

This section discusses action in Svelte, which feels somewhat like hooks. In Svelte, you can write it like this:

<div use:keyboard={{shortcut}} class="player-container">
</div>

Here, use is the directive for Svelte actions. The keyboard is a custom function, and its function signature looks like this:

function keyboard(node, options) {}

This function can return an object containing update and destroy, which represent the update function when parameters change and the function executed during destruction. Since the first function corresponds to the node itself, it's convenient for DOM-related operations.

The speaker in the video shares his insights on using Svelte Action, which is worth checking out.

Demystifying Svelte Transitions

This part dives into how Svelte transitions are implemented, breaking down the source code step by step—truly exciting! The transition mechanism in Svelte is fascinating and doesn't rely on JavaScript for dynamic operations.

In jQuery animations, jQuery adds inline styles to elements based on the parameters you provide, like this:

$('.div').animate({
  ...
})

jQuery continuously updates the inline CSS properties until the animation stops. The internal implementation might look something like this (pseudo-code):

while (!stop) {
  updateCSS()
}

setTimeout(() => stop = true, duration);

This means JavaScript will keep executing during this time, which can significantly impact performance as applications grow larger.

So how do typical frameworks implement transitions? In frameworks like Vue and React, you might write:

// vue
<transition name="fade">
    <p v-if="show">hello</p>
</transition>

// React
<CSSTransition in={inProp} timeout={200} classNames="fade">
  <div>
		
  </div>
</CSSTransition>

In this case, Vue automatically inserts class names like fade-leave-active, fade-enter-active, and fade-enter at the appropriate times. React follows a similar principle, inserting class names like fade-enter, fade-active, fade-exit, and fade-exit-active. However, the transition method requires you to define everything in your CSS.

While this avoids performance issues caused by JavaScript calculations, relying solely on CSS for animations can sometimes be cumbersome. Is there a way to combine the dynamic calculation capabilities of JavaScript with CSS animations? Yes! Svelte accomplishes this.

When you declare the following code, Svelte does several things:

<div transition:scale={{duration: 1000}}>
</div>
  1. transition applies the same transition method for both entering and exiting.
  2. Svelte calculates how many frames this animation will require. Assuming an animation time of 1000 milliseconds, the calculation is 1000 / 16, which results in 62.5 frames. The 16 here represents the milliseconds required for each frame at a refresh rate of 60Hz (1000 / 60).
  3. Svelte uses the animation start time as 0 and the end time as 1, naming the variable t, and applies an easing function for interpolation based on t.
  4. Svelte dynamically creates a CSS keyframe and adds this animation to the element.
  5. It uses stylesheet.insertRule to add styles dynamically to the current document.

Let’s take a look at the source code:

// src/runtime/internal/style_manager.ts
export function create_rule(node: Element & ElementCSSInlineStyle, a: number, b: number, duration: number, delay: number, ease: (t: number) => number, fn: (t: number, u: number) => string, uid: number = 0) {
	const step = 16.666 / duration;
	let keyframes = '{\\n';

	for (let p = 0; p <= 1; p += step) {
		const t = a + (b - a) * ease(p);
		keyframes += p * 100 + `%{${fn(t, 1 - t)}}\\n`;
	}

	const rule = keyframes + `100% {${fn(b, 1 - b)}}\\n}`;
	const name = `__svelte_${hash(rule)}_${uid}`;
	const doc = node.ownerDocument as ExtendedDoc;
	active_docs.add(doc);
	const stylesheet = doc.__svelte_stylesheet || (doc.__svelte_stylesheet = doc.head.appendChild(element('style') as HTMLStyleElement).sheet as CSSStyleSheet);
	const current_rules = doc.__svelte_rules || (doc.__svelte_rules = {});

	if (!current_rules[name]) {
		current_rules[name] = true;
		stylesheet.insertRule(`@keyframes ${name} ${rule}`, stylesheet.cssRules.length);
	}

	const animation = node.style.animation || '';
	node.style.animation = `${animation ? `${animation}, ` : ``}${name} ${duration}ms linear ${delay}ms 1 both`;

	active += 1;
	return name;
}

This function generates CSS similar to the following:

@keyframes __svelte__dynamic_hash_name {
  0% {
    transform: scale(0);
  }
  1.6% {
    transform: scale(0);  
  }
  ...
  100% {
    transform: scale(1);
  }
}

This is example code, and the actual output will vary based on the duration and easing function. Svelte not only helps you create transitions but also manages them. For instance, if a transition is interrupted midway, Svelte will remove the animation and stop it, managing various lifecycle events.

This integration combines the performance of CSS animations with the dynamic control benefits of JavaScript.

If you want to learn more, be sure to check out the video where the speaker explains everything clearly!

Futuristic Web Development

Rich Harris himself shares insights about the changing processes in next-generation web development. However, the current proposals are not finalized, so we should watch with anticipation.

In the past, we used tools like Rollup or Webpack for resource bundling, relying on their dependency tracking mechanisms for updates. The bottleneck then was that browsers generally didn't understand ES6 syntax and the import mechanism. To help developers better manage their code, these tools emerged. Now that browser support has matured, more applications directly rely on native ES Modules. For example, recent frameworks like VuePress and Snowpack utilize native ES Module applications, which means we don't have to wait as long to see results; instead, we can import everything directly through the browser's mechanisms without waiting for bundlers to compile the code. Svelte is also expected to integrate with Snowpack in the future, which you might want to look into.

Conclusion

In this latest IT Ironman Competition, I created a series of tutorial videos about Svelte, explaining its various features, advanced applications, common UI implementations, and the principles behind Svelte, culminating in a simple version of Svelte. Feel free to check them out!

I will also convert the content from the videos into articles for easier reading, so please continue to follow my blog or subscribe directly via RSS!

If you found this article helpful, please consider buying me a coffee ☕ It'll make my ordinary day shine ✨

Buy me a coffee