-
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)
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 Hooks
With its launch, it can be said that it has inspired many new paradigms of component logic expression and logic reuse, which have React
been completely replaced in the ecology Class Components
, including few now can React
be seen Class Components
in ,
Not only that, in fact, it React Hooks
has also , such as Vue
the Vue Composition API
composition , including React Hooks
the ones inspired by Svelte3
, and SolidJS
more similar in syntax and React Hooks
more similar in implementation Vue Composition API
.
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:
-
Hooks
The difference between the execution principle and the mental model of native JS: becauseReact Hooks
it 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 Closure
The mental burden: if you don't pass the correct dependency array, then you will have an expired closure; -
use Effect
dependencies must be declared manually ; -
How to use 'correctly' use Effect
is a complex issue; -
Need to useMemo/useCallback
wait 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:
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:
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.SolidJS
SolidJS
React
Vue
Ember Starbeam
//状态
const count = Cell(0)
//副作用
DEBUG_RENDERER.render({render: () => console.log(count.current)})
//状态更新
count.set(prev => prev + 1)
Ember Starbeam
This one Cell
in is actually almost the same as Vue
the api in , exposing to update the state for the current value and methodref
count
set
Based on Dependency Tracing Paradigm - Common Ground
What do the three Dependency Tracing-based paradigms mentioned above have in common?
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 react
ecology Recoil
also provide automatic dependency tracking and a certain degree of gradual update optimization, but because they still need to be used React Hooks
in the large system of , they will still be used in many other aspects. Subject to hooks
the problem of , then Hooks
in addition to these solutions, there will still be problems such as expired closures and user fact.
React Hooks
It is indeed an era that inspired a new paradigm, but slowly we also found some problems of his own. Of course, the React
team 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 Hooks
these problems exist and gradually receive the attention of the front-end community.
Compilation-based reactive system
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
Svelte3
From the very beginning, it is a compile-time optimization scheme. The above is the code of a use state in the Svelte
component . We see that he and his state are this javaScript
and 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
$
count
count
Vue Reactivity Transform
Inspired by the above restrictions, Vue introduced a functional Vue Reactivity Transform
responsive . The following is a piece of code after Vue conversion:
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 javaScript
variable . 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
In Solid
the ecology of , he was actually inspired by the fact Vue Reactivity Transform
that 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 .Solid
Reactivity 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 Hooks
that . So this is also an interesting direction to explore.
Advantages and costs of a unified model
Advantages:Svelte
Compared with Vue's Reactivity Transform
and , Solid \-labels
both 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. Svelte
The 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 Transform
with Solid \-labels
solutions 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, Svelte
unlike 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
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:
Svelte
This code generation strategy is relatively more cumbersome, but Solid
is based on first generating a basic HTML string, and then finding the corresponding DOM
node in it to bind, Svelte
but by generating a node by node of this imperative, and then putting the node These javaScript
codes , but this strategy will lead to Svelte
the compilation output of each component under the same component source code will be more bloated, so although everyone feels that it Svelte
is 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, Svelte
the 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 Vue
see Solid
the output of the compilation of and . The overall curve is much flatter, so it is actually in larger projects. On the contrary, Svelte
the size advantage is a disadvantage. As far as I know, the Svelte
team 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 Svelte
better, but there is Solid
still 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
.
That same one only has a single-file component input, we now DOM
implement 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 Svelte
output .
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 Solid
the 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
Regarding the use of native languages in front-end toolchains, the following insights are greatly proposed:
Toolchain abstraction level
The earliest packaging tools, including brow/webpack/rollup
them 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/CRA
are 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 Vite
actually 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
, CLI
it 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/CRA
almost , but at our API
level, this may be used by fewer students.
But its API
level is actually focused on supporting the upper-level framework, our abstraction level will be lower, we only solve meta framework
some 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 Vite
it has almost become a meta framework
common base layer choice for the next generation.
Vite-based upper framework
We see that so many upper-level frameworks above are based on the Vite
description that Vite
the 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, Remix
etc. , 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
Types of front-end and back-end connections
The cost of JS full stack
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、Vue
we do server-side rendering, we also need to perform a so-called water injection on the front-end, that is, Hydrate
in 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 Hydrate
such a process. Because without this data, we have no way to guarantee Hydrate
the .
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 javascript
The cost of running time, and the slowness Hydrate
will 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
The new generation of full-stack frameworks in the community are trying to solve these problems. For example, it is React
proposed . server only components
In 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 components
actually must be done on the whole site. Of course, Next will also do it.
Then, in fact, Nuxt has recently server only components
opened a proposal, so to say that this is server only components
not just a React
unique concept. In many other frameworks, we may gradually appear similar and similar things.
Another direction is to reduce hydration
the cost of water injection, then it is also called local water injection, or it is island architecture
like 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、isles
are fresh
these frameworks in and ecology.
Then, there is another exploration direction, which is the so-called fine-grained+resumabl hydration
fine-grained lazy loading. This data is actually Qwik
invented by this framework. Quick
The author Misko Hevery
is Angular
the original author of . After leaving Google, this framework is now newly developed. , then Qwik
its 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 resumable
also a direction worthy of attention.
And there is one of ours in our Vue ecosystem. VitePress
We 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. hydration
Then what we do is the so-called hydration
whole. 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 -
1. Implementation of "selection" and "cursor" requirements in the Web
2. How does web application development evolve step by step?
Think this article was helpful to you? please share with more people
Like and watching is the biggest support ❤️