In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-02 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly shows you the "example analysis of incremental DOM in the Ivy compiler", which is easy to understand and well-organized. I hope it can help you solve your doubts. Let me lead you to study and study the "example analysis of incremental DOM in the Ivy compiler".
As a front-end framework designed for large-scale front-end projects, Angular actually has many designs worth referring to and learning from. This series is mainly used to study the implementation principles of these designs and functions. This article focuses on the core function of Angular, Ivy compiler, and introduces the design of incremental DOM.
When introducing the front-end framework, I often talk about the template engine. For the rendering process of the template engine, a design such as virtual DOM is used in frameworks like Vue/React.
In the Angular Ivy compiler, virtual DOM is not used, and incremental DOM is used.
Incremental DOM
In the Ivy compiler, the product compiled by the template is different from View Engine in order to support separate compilation, incremental compilation, and so on.
For example, the template code My name is {{name}}, compiled in the Ivy compiler, looks something like this:
/ / create modeif (rf & RenderFlags.Create) {elementStart (0, "span"); text (1); elementEnd ();} / update modeif (rf & RenderFlags.Update) {textBinding (1, interpolation1 ("My name is", ctx.name));}
As you can see, compared with elementDef in View Engine, elementStart (), elementEnd () these API are more refreshing, and they use the design of incremental DOM.
Incremental DOM vs virtual DOM
Virtual DOM must be known to all, and its core computing process includes:
The DOM tree is simulated by JavaScript object, and a virtual DOM tree is obtained.
When the page data changes, a new virtual DOM tree is generated, and the differences between the new and old virtual DOM trees are compared.
Apply the differences to the real DOM tree.
Although virtual DOM solves the performance problems caused by frequent page updates and rendering, traditional virtual DOM still has the following performance bottlenecks:
Within a single component, you still need to traverse the entire virtual DOM tree of that component
When there are only a few dynamic nodes in the whole template of some components, these traverses are a waste of performance.
Recursive traversal and update logic can easily cause UI rendering to be blocked and user experience degraded.
In view of these situations, frameworks such as React and Vue also have more optimizations. For example, tree diff, component diff and element diff are optimized respectively in React. At the same time, task scheduling is introduced to control the calculation and rendering of state updates. In Vue 3.0, the update of the virtual DOM is adjusted from the overall scope to the tree scope, and the tree structure will bring about the simplification of the algorithm and the improvement of performance.
In any case, there is an inevitable problem in the design of virtual DOM: each rendering operation allocates a new virtual DOM tree, which is at least large enough to accommodate the changed nodes, and is usually larger, which results in more memory footprint. Performance can be affected when large virtual DOM trees require a large number of updates, especially on memory-constrained mobile devices.
The core idea of incremental DOM design is:
When creating a new (virtual) DOM tree, walk along the existing tree and find out the changes as you go.
If there is no change, no memory is allocated
If so, change the existing tree (allocate memory only when absolutely necessary) and apply the differences to the physical DOM.
Compared to the virtual DOM-based approach, incremental DOM has two main advantages:
The incremental feature allows a significant reduction in memory allocation during rendering, resulting in more predictable performance
It is easy to map to a template-based approach. Control statements and loops can be freely mixed with element and attribute declarations
The design of incremental DOM was proposed by Google, and they also provide an open source library, google/incremental-dom, which is used to express and apply DOM tree updates. JavaScript can be used to extract, iterate over, and convert data into calls that generate HTMLElements and Text nodes.
But instead of using it directly, the new Ivy engine implements its own version.
Incremental DOM in Ivy
The Ivy engine is based on the concept of incremental DOM, which differs from the virtual DOM method in that diff operations are performed against DOM increments (that is, one node at a time) rather than on the virtual DOM tree. Based on this design, incremental DOM works well with the dirty detection mechanism in Angular.
Incremental DOM element creation
A unique feature of incremental DOM's API is that it separates the opening (elementStart) and closing (elementEnd) of tags, so it is suitable as a compilation target for template languages that allow (temporarily) HTML imbalances in templates (such as open and closed tags in separate templates) and arbitrary logic for creating HTML attributes.
In Ivy, create an empty Element implementation using elementStart and elementEnd as follows (in Ivy, the specific implementations of elementStart and elementEnd are the following:
Export function matching element (index: number, name: string, attrsIndex?: number | null, localRefsIndex?: number): void {matching elementStart (index, name, attrsIndex, localRefsIndex); matching elementEnd ();}
Where destroy elementStart is used to create the DOM element, which must be followed by a call to declare elementEnd ().
Export function alternative elementStart (index: number, name: string, attrsIndex?: number | null, localRefsIndex?: number): void {const lView = getLView (); const tView = getTView (); const adjustedIndex = HEADER_OFFSET + index; const renderer = lView [RENDERER]; / / create DOM element const native = (lView [adjustedIndex] = createElementNode (renderer, name, getNamespace ()) here) / / get TNode / / need to collect matching const tNode = tView.firstCreatePass in the first template delivery? ElementStartFirstCreatePass (adjustedIndex, tView, lView, native, name, attrsIndex, localRefsIndex): tView.data [adjustedIndex] as TElementNode; setCurrentTNode (tNode, true); const mergedAttrs = tNode.mergedAttrs; / / assign all attribute values to the supplied element if (mergedAttrs! = = null) {setUpAttributes (renderer, native, mergedAttrs);} / / write className to RElement const classes = tNode.classes through the inferred renderer If (classes! = = null) {writeDirectClass (renderer, native, classes);} / / write cssText to RElement const styles = tNode.styles; if (styles! = = null) {writeDirectStyle (renderer, native, styles);} if ((tNode.flags & TNodeFlags.isDetached)! = = TNodeFlags.isDetached) {/ / add child elements appendChild (tView, lView, native, tNode) Any direct child of the component or template container must be monkey patched with the component view data in advance / / so that the element if (getElementDepthCount () = 0) {attachPatchData (native, lView) {attachPatchData (native, lView);} increaseElementDepthCount () can be checked later using any element discovery utility method; / / the processing if (isDirectiveHost (tNode)) {createDirectivesInstances (tView, lView, tNode) of a pair of instructions Host ExecuteContentQueries (tView, tNode, lView);} / / gets a list of local names and indexes, and pushes the parsed local variable values to LView if (localRefsIndex! = = null) {saveResolvedLocalsInData (lView, tNode);} in the same order as they were loaded into the template.
As you can see, LView, TView, and TNode are the main dependencies in the process of creating the DOM element by destroy elementStart.
In Angular Ivy, LView and TView.data are used to manage and track the internal data required by the rendering template. For TNode, in Angular is the binding data (share element) for a specific node that is shared among all templates of a particular type.
Marker elementEnd () is used to mark the end of the element:
Export function optional elementEnd (): void {}
There is not much detail about the detailed implementation of benchmark elementEnd (), which basically includes some processing of instructions such as Class and @ input in the style, looping through the instructions on the provided tNode, queuing the hooks to be run, processing at the element level, and so on.
Component creation and incremental DOM instructions
In incremental DOM, each component is compiled into a series of instructions. These instructions create DOM trees and update them in place when the data changes.
When Ivy compiles a component at run time, it creates a template to parse the relevant instructions:
Export function compileComponentFromMetadata (meta: R3ComponentMetadata, constantPool: ConstantPool, bindingParser: BindingParser): R3ComponentDef {/ / other temporarily omitted / / create a TemplateDefinitionBuilder for creating template-related processing const templateBuilder = new TemplateDefinitionBuilder (constantPool, BindingScope.createRootScope (), 0, templateTypeName, null, null, templateName, directiveMatcher, directivesUsed, meta.pipes, pipesUsed, R3.namespaceHTML, meta.relativeContextFilePath, meta.i18nUseExternalIds) / / create template to parse related instructions, including: / / first round: create mode, including all create mode instructions (such as bindings in parsing listeners) / / second round: bind and refresh mode, including all update mode instructions (such as parsing attributes or text bindings) const templateFunctionExpression = templateBuilder.buildTemplateFunction (template.nodes, []) / / provide this so that when the dynamically generated component is instantiated, it knows which projected content blocks to pass to the component const ngContentSelectors = templateBuilder.getNgContentSelectors (); if (ngContentSelectors) {definitionMap.set ("ngContentSelectors", ngContentSelectors);} / generate the consts part of ComponentDef const {constExpressions, prepareStatements} = templateBuilder.getConsts (); if (constExpressions.length > 0) {let constsExpr: o.LiteralArrayExpr | o.FunctionExpr = o.literalArr (constExpressions) / / convert consts to function if (prepareStatements.length > 0) {constsExpr = o.fn ([], [... prepareStatements, new o.ReturnStatement (constsExpr)]);} definitionMap.set ("consts", constsExpr);} / generate template definitionMap.set of ComponentDef ("template", templateFunctionExpression);}
It can be seen that when the component is compiled, it will be compiled into a series of instructions, including const, vars, directives, pipes, styles, changeDetection and so on, as well as the related instructions in the template template. The resulting instructions will be reflected in the compiled components, such as a Component file mentioned in the previous article:
Import {Component, Input} from "@ angular/core"; @ Component ({selector: "greet", template: "Hello, {{name}}!",}) export class GreetComponent {@ Input () name: string;}
After being compiled by ngtsc, the product includes the .js file of the component:
Const i0 = require ("@ angular/core"); class GreetComponent {} GreetComponent. Ideal cmp = i0. GreetComponent defineComponent ({type: GreetComponent, tag: "greet", factory: () = > new GreetComponent (), template: function (rf, ctx) {if (rf & RenderFlags.Create) {if (rf & RenderFlags.Create) {if (0, "div"); i0. Permanent text (1); i0. } if (rf & RenderFlags.Update) {i0.simplified advance (1); i0.featured textInterpolate1 ("Hello", ctx.name, "!");}},})
Among them, elementStart (), text (), elementEnd (), advance (), textInterpolate1 () are all instructions related to incremental DOM. When the component is actually created, its template template function is also executed, and the related instructions are also executed.
Because in Ivy, it is the component that references the relevant template instructions. If a component does not reference an instruction, it will never be used in our Angular. Because component compilation takes place during compilation, we can exclude unreferenced instructions based on references to instructions, so that unused instructions can be removed from the package during Tree-shaking, which is why incremental DOM can shake trees.
The above is all the content of the article "sample Analysis of incremental DOM in Ivy Compiler". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.