Hello, I’m Carson.

Recently, there was a guy who often appeared under the front-end frame related tweets.

I thought, “Who are you, brother?”

It is a framework author, the work is called SolidJS.

Flip through the introduction to the frame, and this sentence caught my attention:

Support for modern front-end features such as: JSX, Fragments, Context, Portals, Suspense, Streaming SSR, Progressive Hyaline, Error Boundaries and Concurrent Rendering

I assume you are not the Princess on the Run by React? It’s not like React, is it exactly the same?

As a traditional Chinese, it’s all about ideas. I tried it for a day and looked at the source code. It turns out this framework is a treasure trove.

This article will compare SolidJS and React, and explain its unique advantages. After reading it, I wonder if you will have the same sigh with me:

It’s more React than React.

After reading this article, I believe I can not only understand a new framework, but also have a deeper understanding of React.

On the whole!

At first glance, it looks similar

Let’s look at the differences with the React syntax from a counter example:


import { render } from "solid-js/web";
import { createSignal } from "solid-js";

function Counter() {
  const [count, setCount] = createSignal(0);
  
  const increment = () => setCount(count() + 1);

  return (
    <button type="button" onClick={increment}>
      {count()}
    </button>
  );
}

render(() => <Counter />, document.getElementById("app"));

What’s different about React:

  • useStateChanged its name intocreateSignal
  • To obtaincountState fromReactDirect use incountTo be changed through a method call, that is:count()

Is it just a React -like framework?

Don’t worry, let’s look at three aspects: compile time, run time, and response theory.

Compile time is different

React is very thin at compile time and basically just compiles JSX syntax.

SolidJS, on the other hand, takes a similar approach to Svelte: at compile time, state updates are compiled into separate DOM manipulation methods.

What’s the good of this? There are two main points.

Volume advantage under certain conditions

You don’t have to pay for code you don’t use

When you use React, the code appears in the final compiled code even if no Hooks are used.

In SolidJS, unused functionality does not appear in the compiled code.

For example, in the timer example above, the compiled code has a line like this:

delegateEvents(["click"]);

The purpose of this line of code is to register the Click event agent on the Document.

If onClick is not used in the timer, this line will not appear in the compiled code.

One enthusiastic user compared the size difference between source code and compiled code between SVELTE and React, which are similar to compile-time solutions.

The horizontal axis represents source code volume, the vertical axis represents compiled code volume, the red line represents Svelte, and the blue line represents React:

As you can see, the compile-time scenario has some bulk advantage up to the threshold (120KB of business source volume).

Because SolidJS uses JSX to describe the view, which is more flexible than SVelte’s Vue-like template syntax, it is not able to achieve the same extreme compilation optimization at compile time as SVelte, making it a little heavier than the SVelte runtime.

This gives him an added bonus: In a real project (> 120KB), the SolidJS code size is about 25% smaller than SVelte’s.

Really? A blessing in disguise?

Faster update speed

We know that in React and Vue there is a layer of virtual DOM (called Fiber Tree in React).

Each time an update occurs, the virtual DOM is compared (the Diff algorithm), and the results of the comparison perform different DOM operations (add, delete, change).

When SolidJS and SVelte are updated, they can directly call the compiled DOM operation method, saving the time of virtual DOM comparison.

For example, the timer above, when clicked, has the following stack of calls from triggering updates to view changes:

Trigger events, update status, update views, call all the way to the end, clear and clear.

The same example is in React, where the call stack looks like this:

Red, green, and blue call stacks correspond to:

  • Handle events
  • Contrast and generateFiberThe tree
  • Execute according to the comparison resultsDOMoperation

As you can see, SolidJS has a much shorter update path than React.

Why, you ask? This still has to start from its special response principle.

Principle of response

Suppose you have a state name with an initial value of Kasong. We want to render a div based on name.

The compiled code for SolidJS looks like this:

const [name, setName] = createSignal("KaSong");

const el = document.createElement("div");
createEffect(() => el.textContent = name());

CreateEffect is similar to UseEffect of React.

Because it relies on name in its callback, when name changes, it triggers the CreateEffect callback, which changes el.textContent and causes DOM updates.

React like:

useEffect(() => {
  el.textContent = name;
}, [name])

First screen rendering results:

<div>KaSong</div>

Next, trigger the update:

setName("XiaoMing") 

Updated results:

<div>XiaoMing</div>

Why does updating a name trigger a createEffect?

There is no black magic here, just subscribe to publish.

The CreateEffect callback depends on the Name, so it subscribes to changes in the Name.

Due to the limited space, the implementation details I will discuss in detail next time.

The key here is that the SolidJS state is atomic.

That is, states have dependencies on each other, and they form a local dependency graph. When one state is changed, the other states in the dependency graph also change.

If these dependencies are used in CreateEffect, their changes are subscribed to.

When the state changes, the CreateEffect callback executes, which in turn executes the specific DOM method to update the view.

The true. Responsive type update, refers to which hit which, Li Yunlong calls to the expert.

Some of you ask, isn’t React like that?

So let me ask you a question:

Why do Hooks have a requirement that the order of the calls cannot be changed?

Why do useEffect callbacks have closure issues?

The answer is clear: React is responsive only under these constraints.

Toil toil React

Here’s a potentially counterintuitive piece of knowledge: React doesn’t care which component triggered the update.

In React, any component triggers an update (such as calling this.setState) and all components go through the process again. You need to build a new Fiber tree.

To reduce pointless render, there are some tuning policies inside React that determine whether a component can reuse the last updated Fiber node (and thus skip Render).

There are also many APIs (UseMemo, PureComponent…). Let the developer tell him which components can skip Render.

If you say that the SolidJS update process is like a painter, where the picture needs to be updated to draw a few strokes.

So the React update process is like a person taking a photo with a camera, looking for a different picture from the last one, and then updating it in different places.

conclusion

Today, we talked about SolidJS and React differences, mainly reflected in three aspects:

  • Compile time
  • The runtime
  • Principle of response

Do you like this framework that has no Hooks order, no useEffect closure issues, no Fiber trees, and is more reactive than reactive?

If you ask me which one? Of course, I’ll take whichever one gives me a higher salary.