天天看點

淺析eTS的起源和演進

淺析eTS的起源和演進

引言 

Mozilla創造了JS,Microsoft建立了TS,Huawei進一步推出了eTS。

從最初的基礎的邏輯互動能力,到具備類型系統的高效工程開發能力,再到融合聲明式UI、多元狀态管理等豐富的應用開發能力,共同組成了相關的演進脈絡。 

eTS(extended TypeScript)是鴻蒙生态的一種應用開發語言。它在TypeScript(簡稱TS)的基礎上,擴充了聲明式UI、狀态管理等相應的能力,讓開發者可以以更簡潔、更自然的方式開發高性能應用。TS是JavaScript(簡稱JS)的超集,eTS則是TS的超集。eTS會結合應用開發和運作的需求持續演進,包括但不限于引入分布式開發範式、并行和并發能力增強、類型系統增強等方面的語言特性。本期我們結合JS和TS以及相關的開發架構的發展,為大家介紹eTS的起源和演進思路。

一、JS

JS語言由Mozilla創造,最初主要是為了解決頁面中的邏輯互動問題,它和HTML(負責頁面内容)、CSS(負責頁面布局和樣式)共同組成了Web頁面/應用開發的基礎。随着Web和浏覽器的普及,以及Node.js進一步将JS擴充到了浏覽器以外的環境,JS語言得到了飛速的發展。在2015年相關的标準組織ECMA釋出了一個主要的版本ECMAScript 6(簡稱ES6),這個版本具備了較為完整的語言能力,包括類(Class)、子產品(Module)、相關的語言基礎API增強(Map/Set等)、箭頭函數(Arrow Function)等。從2015年開始,ECMA每年都會釋出一個标準版本,比如ES2016/ES2017/ES2018等,JS語言越來越成熟。

為了提升應用的開發效率,相應的JS前端架構也不斷地湧現出來。其中比較典型的有Facebook發起的React.js,以及個人開發者尤雨溪發起的Vue.js。React和Vue的主要出發點都是将響應式程式設計的能力引入到應用開發中,實作資料和界面内容的自動關聯處理。具體的實作方式上,React對JS做了一些擴充,引入了JSX(JavaScript XML)文法,可以将HTML的内容統一表示成JS來處理;Vue則是通過擴充的模闆文法(Template)的方式來處理。

下面通過兩個示例,為大家簡要介紹React和Vue。(示例來源于w3schools網站:https://www.w3schools.com/whatis/)

1. React示例

淺析eTS的起源和演進

圖1 React

示例以上代碼描述了React怎麼在指定的頁面元素(id為id01的div元素)中改變相應的字元串内容(從"Hello World!"到"Hello John Doe!")。其中第5行的ReactDOM.render()是React JS庫提供的一個方法,它可以将相應的内容重新整理到指定的HTML元素中。第6行是符合JSX語義的一段代碼,它包含了一個類似HTML結構的字元串(<h1>...</h1>),以及一個表達資料綁定語義的字段({name}),會關聯到第4行定義的name變量。通過這種方式,JSX把HTML的語義以及資料綁定機制和JS語言結合起來,可以友善地在JS語言中使用。

2. Vue示例

淺析eTS的起源和演進

圖2 Vue示例

以上Vue示例代碼也描述了類似的功能。其中第1~3行是類似HTML的文法,描述一個id為app的div頁面元素,其中的{{message}}是資料綁定的語義,在Vue中表示為Template。第6~9行是JS代碼,描述了一個Vue對象,對應了上述的app頁面元素以及所需的資料變量message的内容資訊。第11~13行則是JS函數,它改變message變量的值為"John Doe"。執行這個函數時Vue會自動實作相應的UI界面重新整理。

如上所示,React和Vue所表達的能力是類似的,不過側重點稍微有所不同。React主要是基于JSX的文法,将類HTML的文法融合到JS語言中;Vue則是基于Template機制,在HTML的基礎上擴充相應的語義。當然,上面這兩個例子隻是簡要地描述了React和Vue的基礎資訊,更詳細的文法以及CSS相關的使用等都沒涉及。

從運作時的次元來看,基于React以及Vue的應用都可運作在Web引擎上。為了進一步提升相應的性能體驗,2015年Facebook在React基礎上推出了React Native, 在渲染架構上沒有采用傳統的Web引擎渲染路徑,而是橋接到相應OS平台的原生UI元件上。2019年Facebook引入全新實作的JS引擎Hermes,并推出一系列架構改進來進一步提升React Native的性能體驗。2016年阿裡巴巴開源的Weex則是基于Vue做了一些類似的改進,也是采用了橋接到原生UI元件的渲染路徑。

二、TS

随着JS生态的發展,如何更有效地支撐大型的應用工程開發變成了一個重要的課題。大型的應用工程一般會涉及較複雜的代碼以及較多的團隊協作,對語言的規範性,子產品的複用性、擴充性以及相關的開發工具都提出了更高的要求。為此,Microsoft在JS的基礎上,建立了TS語言,并在2014年正式釋出了1.0版本。TS主要從以下幾個方面做了進一步的增強:

  • 引入了類型系統,并提供了類型檢查以及類型自動推導能力,可以進行編譯時錯誤檢查,有效的提升了代碼的規範性以及錯誤檢測範圍和效率。​
  • 在類型系統基礎上,引入了聲明檔案(Declaration Files)來管理接口或其他自定義類型。聲明檔案一般是以d.ts的形式來定義子產品中的接口,這些接口和具體的實作做了相應的分離,有助于各子產品之間的分工協作。另外,TS通過接口,泛型(Generics)等相關特性的支援,進一步增強了設計複雜的架構所需的擴充以及複用能力。​

在工具層面,TS也有相應的編輯器、編譯器、IDE(Integrated Development Environment)插件等相關的工具,來進一步提升開發效率。

TS在相容JS生态方面也做了較好的平衡,TS應用通過相應編譯器可以編譯出純JS應用,可以在标準的JS引擎上運作。同時,TS定位為JS的超集,即JS應用也是合法的TS應用。此外,在标準層面上,TS相容ECMA的相應标準,并維護那些還未成為ECMA标準的新特性。 

三、eTS

如上所述,基于JS的前端架構以及TS的引入,進一步提升了應用開發效率,但依然存在一些不足。

從開發者次元來看:

寫一個應用需要了解三種語言(JS/TS、HTML和CSS)。這對Web開發者相對友好,但對非Web開發者來說,負擔較重。

從運作時次元來看:

  • 在語言運作時方面,盡管TS有了類型的加持,但也隻是用于編譯時檢查,然後通過TS Compiler轉成JS,運作時引擎還是無法利用到基于類型系統的優化。​
  • 在渲染方面,主流Web引擎由于本身複雜度以及曆史原因,性能、資源占用方面與常見OS原生架構都有一定的差距,尤其在移動平台上。React Native通過渲染架構的改進一定程度上提升了性能體驗,但在平台渲染效果和能力的一緻性,以及JS語言性能等方面還是存在一定的不足。​

Google在2018年底推出的Flutter則走了另外一條路,結合新的語言Dart,引入新的聲明式開發範式,基于Skia的自繪制引擎建構可跨平台的獨立的渲染能力。這是一種較為創新的方案,不過也有幾點不足:

  • Dart語言生态。盡管Dart語言2011年就已推出,而且目标是取代JS,但整個生态還是非常弱小,Dart語言釋出7年後随着Flutter的推出才有所改善。整體而言,Dart和主流語言生态相比還是有非常大的差距。​
  • 開發範式。Flutter暴露了很多細粒度的Widget接口,整體開發的簡潔度,開發門檻,尤其是和Apple推出的SwiftUI相比,存在一定的差距。​

有意思的是,Google在2021年又推出了新的開發架構Jetpack Compose,結合了Kotlin的語言生态,設計了新的聲明式UI開發範式。

2019年,我們在思考如何建構新的應用開發架構的時候,從以下幾個次元進行了重點考慮:

  • 語言生态​
  • 開發效率​
  • 性能體驗​
  • 跨裝置/跨平台能力​

由于JS/TS有比較完善的開發者生态,語言也比較中立友好,有相應的标準組織可以逐漸演進,JS/TS語言成了比較自然的選擇。以JS/TS為基礎,在開發架構的次元,我們做了如下的架構演進設計:

  • 通過基于JS擴充的類Web開發範式,來支援主流的前端開發方式。同步的,在運作時方面,通過渲染引擎的增強(平台無關的自繪制機制、聲明式UI後端設計、動态布局/多态UI元件等),語言編譯器和運作時的優化增強(代碼預編譯、高效FFI-Foreign Function Interface、引擎極小化等),進一步提升相關的性能體驗,并可部署到不同裝置上(包括百KB級記憶體的輕量裝置)。另外,通過平台适配層的設計,建構了跨OS平台的基礎設施。​
  • 通過基于TS擴充的聲明式UI開發範式,提供了更簡潔更自然的開發體驗。在運作時方面,在上述的基礎上,結合語言運作時的類型優化,以及渲染運作時的扁平化流水線技術等,進一步提升性能體驗。​
淺析eTS的起源和演進

圖3 ArkUI開發架構

圖3描述了ArkUI開發架構的整體架構,其中,基于TS擴充的聲明式UI範式中所用的語言就是eTS。下面結合一個具體示例,從應用開發視角簡單介紹下基于eTS的全新聲明式開發範式。 

如圖4所示的代碼示例,UI界面會顯示一個 “Hello World” 的文本和一個 “Click me” 按鈕。當使用者點選“Click me”按鈕時,字元串變量 myText 的值會從“World” 變為“ACE”,文本最終顯示為 “Hello ACE”。

淺析eTS的起源和演進

圖4 eTS聲明式開發範式

這個示例中所包含的eTS聲明式開發範式的基本組成說明如下: 

(1) 裝飾器
用來裝飾類、結構體、方法以及變量,賦予其特殊的含義,如上述示例中 @Entry 、 @Component 、 @State 都是裝飾器。具體而言, @Component 表示這是個自定義元件; @Entry 則表示這是個入口元件; @State 表示元件中的狀态變量,這個狀态變化會引起 UI 變更。
(2) 自定義元件
可複用的 UI 單元,可組合其它元件,如上述被 @Component 裝飾的 struct Hello。
(3) UI 描述
聲明式的方式來描述 UI 的結構,如上述 build() 方法内部的代碼塊。
(4) 内置元件
架構中預設内置的基礎和布局元件,可直接被開發者調用,比如示例中的 Column、Text、Divider、Button。
(5) 事件方法
用于添加元件對事件的響應邏輯,統一通過事件方法進行設定,如跟随在Button後面的onClick()。
(6) 屬性方法
用于元件屬性的配置,統一通過屬性方法進行設定,如fontSize()、width()、height()、color() 等,可通過鍊式調用的方式設定多項屬性。      

從UI架構的需求角度,eTS在TS的類型系統的基礎上,做了進一步的擴充:定義了各種裝飾器、自定義元件和UI描述機制,再配合UI開發架構中的UI内置元件、事件方法、屬性方法等共同構成了應用開發的主體。在應用開發中,除了UI的結構化描述之外,還有一個重要的方面:狀态管理。如上述示例中,用 @State 裝飾過的變量 myText ,包含了一個基礎的狀态管理機制,即 myText 的值的變化會自動觸發相應的 UI 變更 (Text元件)。ArkUI 中進一步提供了多元度的狀态管理機制。和 UI 相關聯的資料,不僅可以在元件内使用,還可以在不同元件層級間傳遞,比如父子元件之間,爺孫元件之間,也可以是全局範圍内的傳遞,還可以是跨裝置傳遞。另外,從資料的傳遞形式來看,可分為隻讀的單向傳遞和可變更的雙向傳遞。開發者可以靈活的利用這些能力來實作資料和 UI 的關聯。

總體而言,ArkUI開發架構通過擴充成熟語言、結合文法糖或者語言原生的元程式設計能力、以及UI元件、狀态管理等方面設計了統一的UI開發範式,結合原生語言能力共同完成應用開發。這些構成了目前eTS基于TS的主要擴充。

ArkUI完整的開發範式可參考這裡:

​​https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/ui/Readme-CN.md​​​

四、下一步演進

接下來,除UI架構需求之外,eTS也會結合應用開發及運作的其他方面需求持續演進:

1. 更完善的類型系統
我們已經設計并實作了專門運作時,利用eTS的類型輸入,在程式執行一開始就獲得較高的運作性能(不像其它傳統JS引擎需要預熱才能擷取高性能)。但是目前的類型系統在運作時的設計上仍然考慮了相容模式,即在運作時,當對象類型發生變化時會走Bailout機制,以使程式在類型不比對時仍能正常運作。一種更極緻的方式是:引入一種特定模式來支援确定類型的表達,當開發者可以明确類型時,提供相應的資訊,這樣運作時可以通過針對性設計,進一步提升性能體驗。另外,eTS将來也會在類型系統中拓展一些新的類型,在與運作時結合的優化中會提供更好的性能體驗。
2. 更靈活的并行化處理
目前的移動裝置基本都是多核裝置(包括同一配置的多核以及不同配置的大小核),有些裝置還會攜帶多種計算晶片(CPU/GPU/NPU/...)。語言在并發特性上如何充分應用多核裝置甚至異構晶片是一個重要的課題。目前我們采用的仍然是業界常見的類Actor模型的并發接口——Worker,它彌補了Actor模型的些許劣勢,即允許使用者轉移和共享大量的Buffer以避免通信時拷貝的開銷。但是開發者仍需自己去管理Worker的生命周期,利用Worker也不能非常友善地觸發一個異步并行任務。我們已經在嘗試在Actor模型上封裝一種任務接口,友善使用者更容易利用多核觸發異步并行任務。我們也一直在關注Swift、Dart、Kotlin、Go這些語言并發特性的發展和運作時的實作,eTS的特定模式中靜态類型模型的引入也會給并發機制帶來更多高性能實作的可能性,比如對象的當機、所有權轉移、值語義等等。我們将持續緻力于提供簡潔高效的并發API,幫助應用開發者更容易開發出高性能的應用。      

當然,eTS以及ArkUI開發架構還很年輕,還有很多其它方面也會持續演進,比如UI自定義能力的進一步完善,語言運作時以及跨語言互動的進一步優化,跨OS平台能力的擴充(包括Android、iOS等),分布式開發範式等等。

繼續閱讀