自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

前端框架的JIT與AOT,傻傻分不清楚

開發(fā) 前端
本文會聊聊兩者的區(qū)別,及前端框架中AOT的應用。Angular同時提供這兩種編譯方案,下面我們用Angular舉例說明兩者的區(qū)別。

[[433991]]

大家好,我卡頌。

現(xiàn)代前端框架都需要“編譯”這一步驟,用于:

  • 將框架中描述的UI轉換為宿主環(huán)境可識別的代碼
  • 代碼轉化,比如將ts編譯為js、實現(xiàn)polyfill等
  • 執(zhí)行一些編譯時優(yōu)化
  • 代碼打包、壓縮、混淆

編譯可以選擇放在兩個時機執(zhí)行:

  • 代碼構建時,被稱為AOT(Ahead Of Time,提前編譯或預編譯),宿主環(huán)境獲得的是編譯后的代碼
  • 代碼在宿主環(huán)境執(zhí)行時,被稱為JIT(Just In Time,即時編譯),代碼在宿主環(huán)境編譯并執(zhí)行

本文會聊聊兩者的區(qū)別,及前端框架中AOT的應用。

AOT和JIT的區(qū)別

Angular同時提供這兩種編譯方案,下面我們用Angular舉例說明兩者的區(qū)別。

考慮如下Angular代碼:

  1. import { Component } from "@angular/core"
  2.  
  3. @Component({ 
  4.   selector: "app-root"
  5.   template: "<h3>{{getTitle()}}</h3>" 
  6. }) 
  7. export class AppComponent { 
  8.   public getTitle() { 
  9.     return 'Hello World'
  10.   } 

定義AppComponent,最終瀏覽器(作為宿主環(huán)境)渲染的結果為:

現(xiàn)在將模版中使用的getTitle方法修改為未定義的getTitleXXX:

  1. // 從 
  2. template: "<h3>{{getTitle()}}</h3>" 
  3. // 修改為 
  4. template: "<h3>{{getTitleXXX()}}</h3>" 

 如果使用AOT,編譯后會立刻報錯:

ERROR occurs in the template of component AppComponent.

如果使用JIT,編譯后不會報錯,代碼在瀏覽器中執(zhí)行時會報錯:

ERROR TypeError: _co.getTitleXXX is not a function

造成以上區(qū)別的原因是:當使用JIT時,構建階段僅僅使用tsc將ts編譯為js并將代碼打包。

打包后的代碼在瀏覽器運行后,執(zhí)行到Decorator(上例中的@Component語句)時,Angular的模版編譯器才開始編譯template字段包含的模版語法,并報錯。

當使用AOT時,tsc、Angular的模版編譯器都會在構建階段進行編譯,所以會立刻發(fā)現(xiàn)template字段包含的錯誤。

除了以上區(qū)別外,JIT與AOT的區(qū)別還包括:

  • 使用JIT的應用在首次加載時慢于AOT,因為其需要先編譯代碼,而使用AOT的應用已經(jīng)在構建時完成編譯,可以直接執(zhí)行代碼
  • 使用JIT的應用代碼體積普遍大于使用AOT的應用,因為在運行時會多出編譯器代碼

基于以上原因,在Angular中一般在開發(fā)環(huán)境使用JIT,在生產(chǎn)環(huán)境使用AOT。

從前端框架的角度看AOT可以用兩個步驟描述前端框架的工作原理:

  1. 根據(jù)組件狀態(tài)變化找到變化的UI
  2. 將UI變化渲染為宿主環(huán)境的真實UI

借助AOT對模版語法編譯時的優(yōu)化,就能減少步驟1的開銷。

這是大部分采用模版語法描述UI的前端框架都會進行的優(yōu)化,比如Vue3、Angular、Svelte。

其本質原因在于模版語法的寫法是固定的,固定意味著「可分析」。

「可分析」意味著在編譯時可以標記模版語法中的靜態(tài)部分(不變的部分)與動態(tài)部分(包含自變量,可變的部分),使步驟1在尋找變化的UI時可以跳過靜態(tài)部分。

甚至Svelte、Solid.js直接利用AOT在編譯時建立了「組件狀態(tài)與UI中動態(tài)部分的關系」,在運行時,組件狀態(tài)變化后,可以直接執(zhí)行步驟2。

AOT與JSX

而采用JSX描述UI的前端框架則很難從AOT中受益。

原因在于JSX是ES的語法糖,作為JS語句只有執(zhí)行后才能知道結果,所以很難被靜態(tài)分析。

為了讓使用JSX描述UI的前端框架在AOT中受益,有兩個思路:

  • 使用新的AOT思路
  • 約束JSX的靈活性

React嘗試過第一種思路。prepack是meta(原Facebook)推出的一款React編譯器,用來實現(xiàn)AOT優(yōu)化。

[[433994]]

他的思路是:在保持運行結果一致的情況下,改變源代碼的運行邏輯,輸出性能更高的代碼。

即:代碼在編譯時將計算結果保留在編譯后代碼中,而不是在運行時才去求值。

比如,如下代碼:

  1. (function () { 
  2.   function hello() { return 'hello'; } 
  3.   function world() { return 'world'; } 
  4.   global.s = hello() + ' ' + world(); 
  5. })(); 

經(jīng)由prepack編譯后輸出:

  1. s = "hello world"

遺憾的是,由于復雜度以及人力成本考慮,prepack項目已于三年前暫停了。

Solid.js同樣使用JSX描述視圖,他實現(xiàn)了幾個內(nèi)置組件用于描述UI的邏輯,從而減少JSX的靈活性,使AOT成為可能。比如:

For替代數(shù)組的map方法:

  1. <For each={state.list} fallback={<div>Loading...</div>}> 
  2.   {(item) => <div>{item}</div>} 
  3. </For

 Show替代if條件語句:

  1. <Show when={state.count > 0} fallback={<div>Loading...</div>}> 
  2.   <div>My Content</div> 
  3. </Show> 

總結

總結一下,前端框架可以從AOT中收獲很多益處,其中最主要的一條是:

減少“根據(jù)組件狀態(tài)變化找到變化的UI”這一步驟的工作量

要實現(xiàn)AOT的前提是:組件代碼易于分析。

 

責任編輯:姜華 來源: 魔術師卡頌
相關推薦

2021-03-10 08:56:37

Zookeeper

2021-07-27 07:31:16

JavaArrayList數(shù)組

2022-05-15 21:52:04

typeTypeScriptinterface

2024-02-29 09:08:56

Encoding算法加密

2018-12-17 12:30:05

Kubernetes存儲存儲卷

2020-10-30 08:20:04

SD卡TF卡存儲

2018-05-22 16:24:20

HashMapJavaJDK

2024-11-04 00:00:03

viewportDOMSPA

2023-09-03 21:18:07

Python編程語言

2020-03-03 17:35:09

Full GCMinor

2023-02-27 15:46:19

數(shù)據(jù)元元數(shù)據(jù)

2022-02-25 09:14:33

類變量共享實例變量

2016-11-04 12:51:46

Unix網(wǎng)絡IO 模型

2021-02-08 23:47:51

文件存儲塊存儲對象存儲

2021-01-13 08:10:26

接口IEnumeratorIEnumerable

2020-11-11 07:32:18

MySQL InnoDB 存儲

2023-04-11 15:57:49

JavaScriptCSSHTML

2021-02-14 22:33:23

Java字符字段

2021-12-29 07:34:40

Filter CSS backdrop-fi

2019-11-21 14:22:12

WiFiWLAN區(qū)別
點贊
收藏

51CTO技術棧公眾號