Youda introduced the following three front-end areas at different levels:
  • Development paradigms & underlying frameworks (Note: frameworks such as Vue and React are familiar to everyone)
  • Toolchain (note: build tools like webpack)
  • Upper framework (Note: such as Next.js, Nuxt.js)
Before the official sharing, You Da made a statement: "This sharing only represents personal opinions, because I am the author of the framework and construction tools, and will definitely contain interests and personal biases, but I will try to be as objective as possible. Please bear with me", let's enjoy this "delicious" meal!

The following content is based on the sharing of You Da and a little personal summary. If there is any ambiguity in the content, you can leave a message in the comment area!

Trends in development paradigms & underlying frameworks

The most influential development paradigm-level change in the past few years is definitely ours. React HooksWith its launch, it can be said that it has inspired many new paradigms of component logic expression and logic reuse, which have Reactbeen completely replaced in the ecology Class Components, including few now can Reactbe seen Class Componentsin ,

Not only that, in fact, it React Hookshas also , such as Vuethe Vue Composition APIcomposition , including React Hooksthe ones inspired by Svelte3, and SolidJSmore similar in syntax and React Hooksmore similar in implementation Vue Composition API.

picture

With the promotion of React Hooks and the widespread use of them by developers, some experience problems in his development have gradually been faced. The root causes of some unavoidable experience problems here are as follows:

  • HooksThe difference between the execution principle and the mental model of native JS: because React Hooksit simulates some behaviors by repeatedly calling the code of the component every time it is updated, which leads to some counterintuitive limitations;
  • Conditional calls are not allowed React force;
  • Stale ClosureThe mental burden: if you don't pass the correct dependency array, then you will have an expired closure;
  • use Effectdependencies must be declared manually ;
  • How to use 'correctly' use Effectis a complex issue;
  • Need to useMemo/useCallbackwait for manual optimization, otherwise it will cause some performance problems unknowingly;

Youda said that as the author of a competing framework, his views on the React Hooks framework may be relatively more direct, but these are not the views of Youda alone, but problems that the React community and React team have also realized in recent years. Of course, React The team is also making efforts to improve these problems. According to the representative improvement, the following three aspects:

picture

Based on Dependency Tracking Paradigm

Before the above improvements, in fact, many React community members also included some users who did not apply React themselves. Although React Hooks had a significant impact, everyone also realized some of his problems, but some of them were related to React Hooks. Some similar logical composition capabilities, on the other hand, the paradigm based on dependency tracking has begun to gain attention again; for example, Recoil within React, of course, there are more outside the community, such as:

picture

We can look at the code for the above three scenarios in terms of the dependency tracking based paradigm:

SolidJS

//状态
const [count,setCount] = createSignal(0)
//副作用
createEffect(() => console.log(`${count()`}
//状态更新
setCount(count() + 1)

It can be seen that SolidJS and React Hooks are very similar

  • The createEffect in the side effect is actually similar to the use Effect in React, but createEffect does not need to declare dependencies, and actually collects the dependencies for you when calling the count function;

  • When the state is updated, we don't need to use the useCallback extra way to create functions to pass to our event listeners; these are very intuitive;

Vue Composition API

//状态
const count = ref(0)
//副作用
watchEffect(() => console.log(count.value))
//状态更新
count.value++

In fact Vue, the internal implementation used in is almost the same as the intrinsicComposition API internal implementation, but it looks more like , but through a ref object, the value machine on the object can be read or written, and it will automatically be read and written. Track and update dependencies.SolidJSSolidJSReactVue

Ember Starbeam

//状态
const count = Cell(0)
//副作用
DEBUG_RENDERER.render({render: () => console.log(count.current)})
//状态更新
count.set(prev => prev + 1)

Ember StarbeamThis one Cellin is actually almost the same as Vuethe api in , exposing to update the state for the current value and methodrefcountset

Based on Dependency Tracing Paradigm - Common Ground

What do the three Dependency Tracing-based paradigms mentioned above have in common?

picture

At the same time, in the framework with the concept of dependency tracking as the first-class concept, the design of its own components must be closely integrated with dependency tracking, so the update and rendering of components will also have automatic dependency tracking, which means that the update of components will be more accurate. Instead of relying on a state being passed from parent component to child component layer by layer, every deeply nested component can be updated spontaneously, and the overall performance will be better.

Such solutions in the reactecology Recoilalso provide automatic dependency tracking and a certain degree of gradual update optimization, but because they still need to be used React Hooksin the large system of , they will still be used in many other aspects. Subject to hooksthe problem of , then Hooksin addition to these solutions, there will still be problems such as expired closures and user fact.

React HooksIt is indeed an era that inspired a new paradigm, but slowly we also found some problems of his own. Of course, the Reactteam is trying to solve these problems, and at the same time React, outside the system, there are some others with the same logical combination ability. , but at the same time, these solutions that avoid React Hooksthese problems exist and gradually receive the attention of the front-end community.

Compilation-based reactive system

picture

However, even if it is a solution based on dependency tracking, we can also perform some optimizations based on compile time, and the first one here isSvelte3

Svelte

picture

Svelte3From the very beginning, it is a compile-time optimization scheme. The above is the code of a use state in the Sveltecomponent . We see that he and his state are this javaScriptand this let. Declaring a variable in this way is a responsive state, then you have to update this The state can directly operate this variable,

The side effect is to use a magical compilation magic, which is this ,$ a label of this , which is actually a label syntax of , and the following statement will automatically track the change of this variable. When it changes, this statement It will be automatically re-executed, then we can see that this is the same as our previous code examples, the goal he achieved is actually the same, but he uses the means of compiling to make the code more concise, but it is precisely because of the simplicity So there are the following restrictions:$javaScript$countcount

picture

Vue Reactivity Transform

Inspired by the above restrictions, Vue introduced a functional Vue Reactivity Transformresponsive . The following is a piece of code after Vue conversion:

picture

It is still a simple variable declaration, but we use a function such as $ref. This function is actually a concept of a macro at compile time. This function does not really exist. It just gives a hint to the compilation. This will then be converted into the real ref based code we saw earlier.

But when using it, the experience becomes just declaring a function, and then using this variable and updating this variable is no different from using a normal javaScriptvariable . At the same time, this grammar will explicitly declare which variable is the response sound and which variable is not the response.

So this syntax can be used in nested functions, but also in TS/JS files, it's not limited to Vue files, so it's a more naive compiled reactive model.

Solid -labels

picture

In Solidthe ecology of , he was actually inspired by the fact Vue Reactivity Transformthat his community users made a responsive solution basedSolid-label on , and then did a layer of compiled optimization, so it can be seen that the effect that can be achieved is very similar to that of .SolidReactivity Transform

The ultimate purpose is to allow everyone to express component logic with more concise code, without giving up this logic combination, and the ability to perform free logic combination like React Hooksthat . So this is also an interesting direction to explore.

Advantages and costs of a unified model

picture

Advantages:Svelte Compared with Vue's Reactivity Transformand , Solid \-labelsboth belong to a unified model, that is, it is not limited to the component context, it can be used within the component, or it can be used outside the component. The advantage is that it is conducive to long-term refactoring and reuse. Because many times the logic reuse in our large-scale projects is when one of our components is written and found that this component has become very bloated. When it is very big, we start to think about reorganizing the logic for extraction and reuse. SvelteThe syntax can only be used within the component, which makes it a costly behavior to move the logic outside the component. It is not a simple copy of the logic to copy the text, but a complete refactoring is required.

Because a completely different system is used outside the component, but Reactivity Transformwith Solid \-labelssolutions like and , we can copy the logic in the component directly to the outside of the component, and then wrap it in a function to extract It is completed, then the cost of such refactoring is very small, and this kind of optimization by the team is more encouraged, which is more helpful for long-term maintainability.

Cost: Because we need to explicitly declare responsive variables, it will have a certain degree of abstraction leakage of the underlying implementation, that is, users actually need to understand the implementation of the underlying responsive model before they can better Understand how this syntactic sugar works, Svelteunlike the syntax in the composition, even if you don't know how its underlying operation works, you can get started at almost zero cost, which is a long-term maintainability and an initial stage A balance and trade-off between start-up costs.

Compile-based runs are optimized

picture

After talking about state management, we can also talk about runtime optimization based on compilation. Compilation runtime optimization is the three main representatives. As shown in the figure above, we can first look at different strategies:

picture

SvelteThis code generation strategy is relatively more cumbersome, but Solidis based on first generating a basic HTML string, and then finding the corresponding DOMnode in it to bind, Sveltebut by generating a node by node of this imperative, and then putting the node These javaScriptcodes , but this strategy will lead to Sveltethe compilation output of each component under the same component source code will be more bloated, so although everyone feels that it Svelteis famous for its light weight,

But in fact, we will find that in relatively large projects, after more than 15 projects are formed in the project, Sveltethe overall packaging volume advantage has almost disappeared. Then when more than 50 or even 100 are formed, all the The volume will become more and more bloated.

Relatively speaking, we can Vuesee Solidthe output of the compilation of and . The overall curve is much flatter, so it is actually in larger projects. On the contrary, Sveltethe size advantage is a disadvantage. As far as I know, the Svelteteam also wants to optimize this aspect, which may be realized in the next major version, so we will wait and see.

At the same time Solid, the is indeed very fierce. In fact, after our Vue has introduced a lot of compile-time optimizations, our performance has been Sveltebetter, but there is Solidstill a certain distance from it.

Vue Vapor Mode (input)

As for the compile-time performance optimization mentioned above, in fact, our Vue also explored this aspect in the early days, such as a project that is still in the test Vue Vapor Mode.

picture

That same one only has a single-file component input, we now DOMimplement it at runtime by compiling the template into a virtual rendering function. But since a template is a compiled source, we can also choose to compile it into a different output in another mode, one more similar to the Svelteoutput .

picture

The code for this output here is just a sample code. It is not necessarily the final code, nor the code you need to write. It is completely the output of a compiler. Its overall idea is to generate the static structure and static nodes of the template at one time, and then generate the imperative format. , find the dynamic node, and responsively bind it to the state of such code, this strategy is essentially Solidthe strategy adopted,

So in fact, this strategy can be used by all template engines. We are also exploring an optional such a mode in a certain version Vue, compiling the template into this, with better performance and runtime. It's also a smaller mode, and of course it won't be a breaking update, as our goal is to allow you to use this feature incrementally.

toolchain

The use of native languages ​​in front-end toolchains

picture

Regarding the use of native languages ​​in front-end toolchains, the following insights are greatly proposed:

picture

Toolchain abstraction level

picture

The earliest packaging tools, including brow/webpack/rollupthem are focused on packaging, and their abstraction level is relatively low. When you want to use these tools to make a real application, you need to use a lot of third-party plug-ins and a lot of configuration to Reach a final form that meets your own requirements.

Then on this basis, there Parcel/Vue-cli/CRAare some so-called scaffolding, these tools at a higher abstraction level, these tools are characterized by their high level of abstraction, that is to say, they focus on application, focus on solving a complete As for the application scheme, its relative disadvantage is that it is a relatively complex and large black box.

When you need to do custom customization, you will inevitably encounter some problems. For example, when you have some conflicts with his default functions, you will be more painful.

Well, the new project we are doing now may Viteactually be used by some students. In fact, we decided after thinking about this abstraction level. What kind of route is he going to take, that is to say Vite, CLIit is focused on The application level has a high level of abstraction. It has a lot of out-of-the-box notes, that is, you can send the configured functions in advance for you. In most cases, you can achieve these functions that are Parcel/Vue-cli/CRAalmost , but at our APIlevel, this may be used by fewer students.

But its APIlevel is actually focused on supporting the upper-level framework, our abstraction level will be lower, we only solve meta frameworksome problems that must be solved, but for the upper-level framework, what do you use, we will not do it Instead, it should be as flexible as possible to support the use cases of any upper-layer framework, so this is why Viteit has almost become a meta frameworkcommon base layer choice for the next generation.

Vite-based upper framework

picture

We see that so many upper-level frameworks above are based on the Vitedescription that Vitethe route we take is relatively successful.

The upper framework Meta Frameworks

What is the meaning of JS full stack?

If we talk about this Meta Frameworks, which is the most typical example, that is NextJS 、NuxtJS, and the rookies in the React community now, Remixetc. , then when we think about this type of JS full stack, what does it mean for us to do full stack?

Then I believe that many friends of large enterprises in China know that because we can use the same language to do the connection before and after, we can do some things that pure front-end and pure back-end can't do respectively, or we need very complex before. Some things that can only be achieved by joint debugging, then the JS full stack can better complete a language so that we can get through the front and back. So what can we get through?

The front and back ends of the data are connected

picture

Types of front-end and back-end connections

picture

The cost of JS full stack

picture

Some of the new full stack frameworks are now trying to improve some of the problems first. Our existing front-end frameworks, such as mainstream ones, after React、Vuewe do server-side rendering, we also need to perform a so-called water injection on the front-end, that is, Hydratein the process of pursuit, we must ensure that the client-side and front-end have the same data, so actually although our data is already used to render HTML,

These data have been used in HTML in theory, but we have to send this data again, send it to the front end together, and let the front end go through Hydratesuch a process. Because without this data, we have no way to guarantee Hydratethe .

On the client side, some components may or may not be on the client side. What needs to be interacted with is static, but he uses the dynamic data on the server side, but this component will still be sent to the server side, and it may still generate this javascriptThe cost of running time, and the slowness Hydratewill affect the interactive index of the page, that is, time to interactive.

There are some relatively complex and huge projects. He may freeze the page during the water injection process, so that although he can see the page, he cannot interact. It takes a second to interact, etc., which will cause such problems. .

Directions for community exploration

picture

The new generation of full-stack frameworks in the community are trying to solve these problems. For example, it is Reactproposed . server only componentsIn fact, from this definition, we find that he does not have a full-stack framework, and does it around a full-stack framework. In fact, users are There is no way to simply use a concept, so it is React server only componentsactually must be done on the whole site. Of course, Next will also do it.

Then, in fact, Nuxt has recently server only componentsopened a proposal, so to say that this is server only componentsnot just a Reactunique concept. In many other frameworks, we may gradually appear similar and similar things.

Another direction is to reduce hydrationthe cost of water injection, then it is also called local water injection, or it is island architecturelike an island in the sea, only these small islands can inject water to him, so that he can interact with each other. Then the more representative ones astro、islesare freshthese frameworks in and ecology.

Then, there is another exploration direction, which is the so-called fine-grained+resumabl hydrationfine-grained lazy loading. This data is actually Qwikinvented by this framework. QuickThe author Misko Heveryis Angularthe original author of . After leaving Google, this framework is now newly developed. , then Qwikits main feature is that it does not need to resend the data again.

It directly embeds the required data in the generated rendered html, so that the client-side js can directly obtain the required data in the html, or even skip some js steps that need to be executed, and jump directly to a completed state Going to the top, this is the so-called, and it is resumablealso a direction worthy of attention.

And there is one of ours in our Vue ecosystem. VitePressWe are actually exploring how to do it efficiently under the premise that it is actually a static MD file, which is the core content of our page. hydrationThen what we do is the so-called hydrationwhole. This layer of ui wrapped by the external framework content is dynamic, and then continues to perform partial water injection in the internal static, and then we can still get the experience of a single-page application, but it is very good performance of client water injection.

write at the end

This is the end of You Da's sharing. If there is any dispute in the content of this summary, you can leave a message in the comment area, hoping to bring you some harvest and growth!

Author: Geometry

https://juejin.cn/post/7124551017382805518

- EOF -

Recommended reading   Click on the title to jump

1. Implementation of "selection" and "cursor" requirements in the Web

2. How does web application development evolve step by step?

3. Web 3.0, the era of "inspired creativity"


Think this article was helpful to you? please share with more people

Follow "The Road to Big Front-end Technology" and add a star to improve your front-end skills

Like and watching is the biggest support ❤️