Svelte (pronounced: [svelt]) is a front-end framework similar to React and Vue written by Rich Harris and the author of Rollup.
Compilers not frameworks (no runtime)
It’s not appropriate to say that Svelte is a framework; it’s really a compiler, not dependencies like React and Vue.
We know that frameworks like React and Vue are runtime-based frameworks, and applications must import the framework itself — the runtime code that builds the virtual DOM, handles diff algorithms, and so on. Also, all of this work is done in the browser. As the user performs various actions on the page to change the state of the component, the framework Runtime calculates (diff) which DOM nodes need to be updated to update the view based on the new component state.
Svelte, on the other hand, compiles the Svelte components we’ve written (also the idea of componentalization) into native JavaScript code that interacts directly with the DOM. This is done during the build process, without having to add an intermediate layer to the code at runtime. This means that there is no additional need to introduce a so-called framework runtime. So Svelte is a compiler, not a framework.
Of course, it’s not that Svelte doesn’t have runtime code at all. It does have runtime code built in when it’s compiled. These are helper functions, but they’re very small, about 200 lines uncompressed.
Because there is no runtime, components developed using Svelte do not need additional dependencies when compiled and can be used independently. React and Vue projects can be easily introduced and used directly.
Two, how to achieve high performance
React and Vue frameworks use the Virtual DOM. We know that Virtual DOM improves application performance in many scenarios. How does Svelte achieve high performance without Virtual DOM?
Templates
Svelte uses template syntax to compile templates into relatively low-level instructions to render content. Compared to the flexibility of JSX, template syntax is more strict and semantic (static), giving more room for optimization during compilation.
Of course, JSX has the full expressiveness of JavaScript and can be used to build arbitrarily complex logic (components).
For example, the following template code:
(Photo from Internet)
We can know very easily:
- What are the
p
Labels don’t change div
的id
It’s not going to change- Which tags don’t change
- The only thing that can change is that
message
variable
At compile time, Svelte compiles the template as an imperative native DOM operation, such as the following template:
<a>{{ msg }}</a>
Copy the code
Is compiled into native JavaScript code that interacts directly with the DOM:
function renderMainFragment(root, component, target) {
var a = document.createElement("a");
var text = document.createTextNode(root.msg);
a.appendChild(text);
target.appendChild(a);
return {
update: function (changed, root) {
text.data = root.msg;
},
teardown: function (detach) {
if(detach) a.parentNode.removeChild(a); }}; }Copy the code
Compared to JSX based on the virtual DOM, this output does not require the corresponding code to maintain the virtual DOM and diff operations, the code size is much smaller, the memory footprint is much lower, and the performance is very good.
Code example from: What about Svelte, the front-end framework? – especially the rain stream of answer: www.zhihu.com/question/53…
2. The VIRTUAL DOM isn’t always fast
The advantage of the virtual DOM lies in the React diff algorithm and batch processing strategy. React minimizes the number of calls to the real DOM by gathering all DOM operations before the page is updated and committing them to the real DOM at once, rather than rebuilding the entire DOM every time something changes.
In fact, when we directly manipulate DOM, this calculation process can also be determined and implemented by ourselves (redraw and rearrange optimization), but it will definitely take a lot of energy and time, and often our own work is not as good as React. So React helped us “boost performance” in the process.
The virtual DOM is not without its drawbacks. When using the virtual DOM, rendering the DOM for the first time may be slower than HTML due to an extra layer of virtual DOM computation. Also, if the component’s data changes, React will re-render the component and all its children, even if the children don’t need to be re-rendered. That’s why React has shouldComponentUpdate, useMemo, React.PureComponent, useCallback, etc.
Note that re-render does not mean that the native DOM has been re-rendered, but that the render method or component function of the custom class component has been re-executed. Components are re-rendered because the virtual DOM is built on diff algorithms, and to have diff, the component must be re-rendered to generate a new virtual DOM tree (React maintains two virtual DOM trees in memory). This allows you to know if the new state of the component has changed compared to the old state, and to figure out which DOM nodes need to be updated.
(photo: https://www.youtube.com/watch?v=AdNJ3fydeao)
React’s solution to this problem is not to focus on making the virtual DOM itself faster, but rather better perceived performance, so it introduces runtime scheduling, concurrent modes, and time sharding as a runtime solution, all of which require a lot of runtime. When you load React, you also need to load all the code needed to handle complex runtime scheduling.
If you want to learn more about React’s mechanics, read the following article:
- zhuanlan.zhihu.com/p/37095662
- React.iamkasong.com/process/fib…
What is the update rendering process for Svelte?
Svelte uses bitMask technology to track what data is dirty — that is, what data has changed since the component was last updated. For example, given four values A, B, C, and D, binary 0000 0001 indicates that the first value A has changed, 0000 0010 indicates that the second value B has changed, and so on. This representation makes maximum use of space. For example, the decimal number 3 (converted to binary 0000 0011) can indicate that data A and B are dirty and the rest of the data is clean.
However, binary in JavaScript has a 31-bit limit (32 bits, minus one bit for positive and negative symbols), and if you use binary storage, you can only hold up to 31 data in a Svelte component. So, Svelte uses arrays (in Svelte this array is called Component.? .dirty), an entry in the array is a binary 31 bits. If there are more than 31 numbers, the excess goes to the next item in the array.
So, setting up dirty data is to set component.? The dirty array binary bit is set to 1. At this point, Svelte has already saved the mapping between the data and the actual DOM nodes. Svelte will walk into different IF bodies and directly update corresponding DOM nodes, without the diff of the complex virtual DOM to figure out which DOM nodes need to be updated. In addition, when Svelte is compiled, the relationship between the data and the real DOM node is analyzed, and when the data changes, the DOM update method can be invoked to update the node very efficiently.
Third, the volume of the constructed product is very small
The resulting code package size for Svelte applications is very small, thanks to the run-time nature and the fact that for certain functions, if a function is missing at compile time, the corresponding code will not be compiled at all.
Comparison results source: www.freecodecamp.org/news/a-real…
True responsive programming
Reactive programming means that the target operation is not performed directly, but achieved by proxy. Here’s an example:
let a = 3;
let b = a * 10;
console.log(b); / / 30
a = 4;
// b = a * 10
console.log(b); / / 30
Copy the code
Here, variable B does not automatically change with variable A. It needs to be executed again each time b = a * 10 to change the value of b. So this code example is not reactive.
In React, when data changes, we need to call this.setstate () or useState() to tell React that the data has changed and the virtual DOM needs to be updated. So React isn’t reactive.
Responsiveness in Svelte is very natural and powerful. In Svelte, a statement starting with $: is a reactive statement. Svelte automatically analyzes the variables that the reactive statement depends on. When the dependent variables change, Svelte will re-execute the corresponding reactive statement. Here’s an example:
<script>
let count = 0;
$: doubled = count * 2;
function handleClick() {
count += 1;
}
$: if (count >= 10) {
console.log(`count is dangerously high! `);
count = 9;
}
</script>
<button on:click="{handleClick}">
Clicked {count} {count === 1 ? 'time' : 'times'}
</button>
<p>{count} doubled is {doubled}</p>
Copy the code
When Svelte sees any statement prefixed with $:, it knows to assign the right variable to the left variable without binding the value of one variable to another using let; And Svelte can run any statement in a reactive manner. In the example above, it can also record and respond to a change in count through a reactive if statement.
Note, however, that Svelte responses are assignment based, and array push, splice, and so on do not trigger reactive updates. Such as:
<script>
let numbers = [1.2.3.4];
function addNumber() {
numbers.push(numbers.length + 1);
}
$: sum = numbers.reduce((t, n) = > t + n, 0);
</script>
<p>{numbers.join(' + ')} = {sum}</p>
<button on:click="{addNumber}">Add a number</button>
Copy the code
The update will not be triggered when the button is clicked. We need to change the push operation to an assignment:
. numbers = [...numbers, numbers.length +1]; .Copy the code
5. Automatic subscription Store
Svelte has a built-in state management feature that makes it easy for responsive stores to share state between components. When used, the store is stored in a separate JS file that can be created by wrapping a value with writable.
Here’s an example:
Store. Js:
import { writable } from "svelte/store";
export const count = writable(0);
Copy the code
App. Svelte:
<script>
import { count } from "./stores.js";
import Incrementer from "./Incrementer.svelte";
import Decrementer from "./Decrementer.svelte";
</script>
<h1>The count is {$count}</h1>
<Incrementer />
<Decrementer />
Copy the code
The Incrementer. Svelte:
<script>
import { count } from "./stores.js";
function decrement() {
count.update((n) = > n - 1);
}
</script>
<button on:click="{decrement}">-</button>
Copy the code
Decrementer. Svelte:
<script>
import { count } from "./stores.js";
function increment() {
count.update((n) = > n + 1);
}
</script>
<button on:click="{increment}">+</button>
Copy the code
Compared to Redux, Svelte’s Store functionality is very simple to use.
Support TypeScript
Svelte3 now supports TypeScript: svelte.dev/blog/svelte…
Seven, Scoped style
The style code associated with the component is placed in the style tag, where CSS is scoped and does not affect other components.
8. Concise grammar
The syntax of Svelte is fairly concise, and the official REPL (Read Eval Print Loop: Interactive interpreter) works very well.
Svelte.dev /tutorial/ba…
Nine, weaknesses
1, routing,
Sapper, the official routing tool, is still in its early stages of development, and some apis may change in future 1.0 releases. For a formal delivery project, this is not a small concern.
There are also some third-party routing tools to choose from, some of which are relatively perfect at present:
- svelte-routing
- svelte-spa-router
2. UI component library
There is currently no mature library of UI components, which makes Svelte not a good choice for scenarios with complex requirements and delivery pressures.
Here are some of the more mature UI component libraries:
- Sveltestrap.js.org/?path=/stor…
- sveltematerialui.com/
3. Only Svelte components support the Svelte static template feature
Using reactive features in JS will result in an error:
function increment() {
$count += 1; // error
}
Copy the code
4. Props is mutable and cannot validate types
And of course that’s intentional, so that the props can be responsive.
<script>
export let answer;
</script>
<p>The answer is {answer}</p>
Copy the code
5. Duplicate code
React and Vue’s built-in runtime code increases the size of the bundle.js file loaded on the first screen, but as the project grows larger, the framework’s runtime code becomes a smaller portion of the bundle.js file. Once the number of Svelte components (template code) increases, more “runtime” code will be generated, and the actual production project may eventually exceed the size of the React and Vue runtime code, which is also a potential problem.
No build tools
There is currently no build tool like create-React-app.
7. Performance in large projects needs to be verified
Because it is a new front-end framework, few enterprises have put it into use in some large projects, and the final performance of Svelte has yet to be verified.
10. Refer to the article
- Svelte updates the rendering principle
- What do you think of Svelte as a front-end framework?
- Rich Harris – Rethinking reactivity