Angular Ivy 作為Angular 的最新渲染引擎,與我們看到的當今所有主流架構的引擎有根本不同,因為Angular Ivy使用了Incremental DOM(增量DOM).
什麼是 incremental DOM?它與virtual DOM有何不同?
讓我們對他們做下比較,看看為什麼Angular 要使用Incremental DOM
Virtual DOM 的工作原理
React是第一個使用virtual DOM的主流架構,它的設計思想是:
每個元件在每次渲染時建立一個新的virtual DOM.React把新的Virtual DOM樹
與現有的相比較,然後将一系列轉變應用于浏覽器DOM,進而比對新的Virtual DOM樹。
Virtual DOM有兩個主要優點:
- 我們可以使用任何語言去實作元件渲染,是以我們不需要重新編譯任何東西。React 開發者主要使用JSX,但我們使用原生的JavaScript一樣可以做到。
- 作為渲染元件的結果,我們得到一個值。它可以被用來測試,debug等。
Incremental DOM
Incremental DOM 被Google内部使用,它的主要設計思想為:
每個元件都被編譯成一系列指令。這些指令建立DOM樹并在資料更改時就地更新它們.
例如下面一個元件
@Component({
selector: 'todos-cmp',
template: `
<div *ngFor="let t of todos|async">
{{t.description}}
</div>
`
})
class TodosComponent {
todos: Observable<Todo[]> = this.store.pipe(select('todos'));
constructor(private store: Store<AppState>) {}
}
會被編譯成:
var TodosComponent = /** @class */ (function () {
function TodosComponent(store) {
this.store = store;
this.todos = this.store.pipe(select('todos'));
}
TodosComponent.ngComponentDef = defineComponent({
type: TodosComponent,
selectors: [["todos-cmp"]],
factory: function TodosComponent_Factory(t) {
return new (t || TodosComponent)(directiveInject(Store));
},
consts: 2,
vars: 3,
template: function TodosComponent_Template(rf, ctx) {
if (rf & 1) { // create dom
pipe(1, "async");
template(0, TodosComponent_div_Template_0, 2, 1, null, _c0);
} if (rf & 2) { // update dom
elementProperty(0, "ngForOf", bind(pipeBind1(1, 1, ctx.todos)));
}
},
encapsulation: 2
});
return TodosComponent;
}());
模闆函數包含了渲染和更新DOM的指令。架構的渲染引擎不會解釋指令,因為這些指令就是引擎。
為什麼選擇Incremental DOM
為什麼Google的工程師使用Incremental DOM來代替Virtual DOM呢?
一個目标在他們心中萦繞:應用必須在手機端表現良好。這就意味着要在兩個方面進行優化:
- 檔案大小
- 記憶體占用
要實作這兩個目标,
- 渲染引擎自身必須是 tree shakable 的。
- 渲染引擎必須具有較低的記憶體開銷
Tree Shakable
當使用 Incremental DOM時,架構不會編譯元件,而是元件引用指令。如果元件未使用特定指令,它就永遠不會被使用。是以,我們可以省略掉bundle中未使用的指令。
Virtual DOM需要一個解釋器。在編譯時,根本無法确定編譯器各個部分是否被使用,是以我們需要把所有東西都發送到浏覽器。
低記憶體開銷
每次重新渲染時,Virtual DOM都會從頭開始建立整個樹。
而Incremental DOM,在視圖未改變時,是不需要任何記憶體的。我們隻有在添加或删除DOM時需要配置設定記憶體。并且配置設定的記憶體大小與改變的DOM的大小成正比。
由于大多數模闆或渲染調用不會改變任何東西,或改變很少,是以可以節省大量記憶體。
更多功能
具有渲染傳回值可以提供更多用途,譬如測試。另一方面能夠使用FireFox DevTools逐行使用指令,使調試和性能分析更容易。
Ivy和 Incremental DOM
Angular一直在使用HTML和Templates.這也是virtual DOM 未被Angular所接受的原因。
鑒于此,加上Incremental DOM的低記憶體開銷和Tree Shakable .我認為使用Incremental DOM作為渲染引擎是正确的選擇。
文章原文來自NRWL