GWT 工具包:使用 Java 構建強大的 JavaScript 前端
已發表: 2022-03-11GWT Web Toolkit,以前稱為 Google Web Toolkit,是一組開發工具,用於使用 Java 編程語言構建和優化基於瀏覽器的複雜應用程序。
GWT 之所以不是“另一個編寫 Web 應用程序的 Java 工具”,是因為該工具包的核心是將 Java 轉換為 JavaScript(以及 HTML 和 CSS)的編譯器,使開發人員能夠編寫前端 Web 應用程序同時利用 Java 的所有優勢。
甚至可以輕鬆混合使用 Java 和 JavaScript,因為 GWT 包含用於與 Web 平台交互的強大互操作性架構。 就像 Java 原生接口 (JNI) 允許 Java 虛擬機 (JVM) 調用特定於平台的例程(例如,訪問特定的硬件功能,或使用來自其他語言的外部庫),GWT 允許我們編寫大部分Java 中的應用程序,然後,如果需要使用特定的 Web API,或者利用現有的 JavaScript 庫,“進入原生”並跳轉到 JavaScript。
GWT 作為 Google 產品誕生,但在 2011 年底畢業並開源,現在在 Apache 許可(第 2 版)下以GWT Open Source Project的名義發布。 它由一個指導委員會管理,該委員會的代表來自多家公司,包括 Google、RedHat、ArcBees、Vaadin 和 Sencha,以及來自社區的獨立開發人員。
GWT 的過去和未來
Google Web Toolkit 於 2006 年首次發布。它的創建是為了幫助 Google 工程師開發基於瀏覽器的複雜應用程序,例如 AdWords、Google Wallet 和 Google Flights,最近,它被用於谷歌表格和收件箱應用程序。
早在 2006 年,瀏覽器(和 JavaScript 解釋器)還遠未標準化。 前端代碼很慢、有缺陷並且難以可靠地使用。 幾乎完全缺乏用於 Web 開發的高質量庫和框架。 例如,jQuery 直到今年才出現。 因此,為了能夠開發大型 Web 應用程序,Google 的工程師決定利用現有的工具和能力。 Java 是最適合他們需求的語言,它廣為人知並完美集成到 IDE 中,例如 Eclipse,因此 Google Web Toolkit 開始了它的生命。
目標或多或少是隱藏瀏覽器之間的差異,並將編寫高效 JavaScript 所需的技巧封裝在 Java 編譯器中,讓開發人員擺脫瀏覽器技術的束縛。
當然,在過去的十年裡,網絡發生了變化。 瀏覽器變得更快,並在實現標准上趨同,並且開發了許多很棒的前端框架和庫,包括 jQuery、Angular、Polymer 和 React。 所以你可能自然會問的第一個問題是,“GWT 還有用嗎?”
一句話:是的。
在現代 Web 開發的背景下,針對瀏覽器是不可避免的,JavaScript 已成為前端應用程序的通用語言。 但當然,不同的工具和語言更適合不同的任務。 GWT 以及一些類似的項目旨在針對瀏覽器而不限制開發人員使用 JavaScript。
在不久的將來,萬維網聯盟的 WebAssembly 小組將促進像 GWT 這樣的“編譯到網絡”工具的開發和使用。 不僅有巨大的空間用於編譯為 JavaScript 的工具,而且這種方法可以滿足從將部分計算卸載到瀏覽器、重用現有代碼和庫、在後端和前端之間共享代碼等環境的實際需求,利用現有的能力和工作流程,並利用不同語言的特性(例如,GWT 的靜態類型)。
GWT 項目預計將很快發布 2.8 版本,3.0 版本正在開發中,在工作中有很大的改進:
- 重塑與 JavaScript 的互操作性
- 改進的(幾乎完全重寫的)編譯器
- 最先進的 Java 支持(例如 lambdas)
實際上,GWT 3.0 的大部分功能已經在公共 Git 存儲庫中可用。 只需在此處查看主幹並按照此處的文檔編譯 GWT。
GWT 社區
自 GWT 於 2011 年開源以來,社區在項目的發展中發揮了關鍵作用。
所有開發都在 gwt.googlesource.com 上託管的 Git 存儲庫上進行,所有代碼審查都在 gwt-review.googlesource.com 上完成。 在這些頁面上,任何對工具包的開發感興趣的人都可以做出貢獻並查看社區正在做什麼。 在過去幾年中,來自非 Google 員工的新補丁的比例從 2012 年的 5% 左右上升到去年的 25% 左右,這證實了參與度的增長。
今年,社區聚集在美國和歐洲舉行了幾次大型會議。 由 Vaadin 組織的 GWT.create 於 1 月在德國慕尼黑和加利福尼亞州山景城舉行,共有來自數十個國家的 600 多名參與者參加。 11 月 11 日,我們將在意大利佛羅倫薩舉行第二屆 GWTcon,這是一個社區驅動的 GWT 會議,我正在幫助組織。
GWT 適合什麼?
Vaadin 發布的關於 GWT 工具包的年度調查討論了 GWT 的開發演變、開發人員對工具包的看法、好與壞等。 該調查還讓我們了解 Toolkit 的用途、用戶社區的變化以及開發人員對 Toolkit 未來的期望。
可以在這裡找到 2015 年GWT 的未來報告,它清楚地表明 GWT 在構建大型 Web 應用程序方面非常受歡迎。 例如,在第 14 頁,它指出,“大多數應用程序都是數據量很大的業務應用程序,每天要使用數小時。”
正如預期的那樣,很容易得出結論,GWT 的自然環境是大型 Web 應用程序領域,其中代碼的可維護性很重要,大型團隊從 Java 語言的結構中受益。
另一方面,查看 GWT 生成的代碼的基準(例如,在去年 GWT.create 會議的主題演講中,第 7、8 和 11 頁)很容易看出,在性能和代碼大小,編譯後的 JavaScript 非常棒。 如果使用得當,所獲得的性能可與最好的手寫 JavaScript 相媲美。 因此,使用 GWT 將 Java 庫移植到 Web 實際上是可行的。
這闡明了 GWT 的另一個理想方案。 Java 生態系統充滿了高質量的庫,在 JavaScript 中沒有現成的對應物。 GWT 編譯器可用於為 Web 調整此類庫。 換句話說,GWT 允許我們混合 Java 和 JavaScript 中可用的庫,並在瀏覽器中運行它們。
這種方法可以在 PicShare 的開發中看到,我們展示瞭如何使用 GWT 將幾個通常不考慮用於 Web 的 Java 庫(例如 NyARToolkit)移植到瀏覽器,並結合 Web API,包括 WebRTC 和 WebGL,以實現獲得一個完全基於網絡的增強現實工具。 我很自豪能夠在去年 1 月的 2015 GWT.create 會議上展示 PicShare。
幕後:將 Java 轉換為 JavaScript
GWT Toolkit 是一組中等複雜的工具,但任何人都可以立即開始使用它,這要歸功於與 Eclipse 的令人驚訝的易於使用的集成。
對於具有 Java 開發項目背景的任何人來說,使用 GWT 創建一個簡單的應用程序都相對容易。 但要了解“真正發生的事情”,有必要分析工具包的主要組件:

- Java 到 JavaScript 轉換器
- 模擬 Java 運行時環境
- 互操作層
GWT 的優化編譯器
對編譯器如何工作的深入描述很早就變得技術性很強,我們不需要深入挖掘,但一些一般概念值得一看。
首先要了解的是,GWT 通過源代碼級別的翻譯將 Java 編譯成 JavaScript。 也就是說,Java 源代碼被翻譯( transpiled是技術術語)為 JavaScript。 這與使用 JavaScript 編寫的執行 Java 字節碼的某種 Java 虛擬機形成對比。 (這實際上是可能的,並且是 Doppio 使用的方法,但這不是 GWT 的工作方式。)
相反,Java 代碼被分解成抽象語法樹 (AST),表示代碼的語法元素。 然後將其映射到等效的(和優化的)Javascript AST,最終轉換回實際的 JavaScript 代碼。
權衡轉譯的利弊遠非本文的目的,但讓我觀察一下,通過這種方法,GWT 可以直接利用 JavaScript 解釋器的垃圾收集服務,以及瀏覽器原生的任何其他功能。
當然,也有一些棘手的部分。 例如,JavaScript 只有一種數值類型,它不能包含 Java 的 64 位long
整數類型,因此long
類型需要編譯器進行一些特殊處理。 此外,Java 靜態類型在 JavaScript 中沒有直接意義,因此必須特別注意保持轉換後的類型轉換操作等價。
另一方面,轉譯的一個容易理解的優勢是 GWT 可以在 Java 級別和JavaScript 級別執行優化(針對大小和性能)。 生成的標準 JavaScript 代碼甚至可以在您的部署管道中進一步處理。 例如,現在已集成到標準 GWT 發行版中的一種常見做法是使用高度專業化的 JavaScript-to-JavaScript 閉包編譯器(Google 眾神的另一個禮物)優化轉譯器的 JavaScript 輸出。
我所知道的對 GWT 編譯器最深入的描述可以在這個幻燈片中找到,以及它來自的原始談話。 在這裡,您可以找到有關編譯過程的其他酷特性的詳細信息,例如 GWT 進行代碼拆分、生成多個單獨的腳本文件以供瀏覽器獨立加載的能力。
模擬的 JRE
如果不補充 Java 運行時環境 (JRE) 的實現,Java 到 JavaScript 的編譯器將只不過是一種新事物,它提供了幾乎所有 Java 應用程序所依賴的核心庫。 粗略地說,在沒有集合或字符串方法的情況下使用 Java 工作會令人沮喪,當然,移植這些庫是一項艱鉅的工作。 GWT 用所謂的仿真 JRE 填補了這個漏洞。
Emulated JRE 絕不是對 Java JRE 的完全重新實現,而是一種對客戶端有用(和可用)的類和方法的選擇。 Java JRE 中但在 Emulated JRE 中找不到的功能分為三類:
不能移植到客戶端的東西。 例如,
java.lang.Thread
或java.io.File
不能在具有相同 Java 語義的瀏覽器中實現。 瀏覽器頁面是單線程的,不能直接訪問文件系統。可以實現但在代碼大小、性能或依賴性方面“成本過高”的東西,因此社區不希望在 GWT 中擁有這些東西。 例如,包含在此類別中的是 Java 反射 (
java.lang.reflect
),它需要轉譯器保留每種類型的類信息,這會導致編譯後的 JavaScript 的大小膨脹。沒有人感興趣的事情,因此沒有實施。
如果 Emulated JRE 不符合您的需要(例如,您需要一些未提供的類),GWT 允許您編寫自己的實現。 這種強大的機制,通過標籤<super-source>
可用,使得在調整使用未模擬的部分 JRE 的新外部庫時可以規避問題。
提供 JRE 某些部分的完整實現可能過於復雜,甚至不可能,因此對於特定任務,您自己的實現可能不會嚴格遵循 Java JRE 的語義,即使它們適用於您的特定情況。 實際上,如果您正在考慮將您的類歸還給項目,請記住對於仿真 JRE 來說至關重要的是,每個包含的類都遵循與原始 Java JRE 完全相同的語義。 這確保了任何人都可以將 Java 代碼重新編譯為 JavaScript,並相信他們會得到預期的結果。 在將代碼返回給社區之前,請始終確保您的代碼經過徹底測試。
互操作層
要成為生產真實世界 Web 應用程序的有效工具,GWT 必須允許開發人員輕鬆地與底層平台交互。 也就是瀏覽器和DOM。
從一開始,GWT 就是為了通過 JavaScript 原生接口 (JSNI) 支持這種交互而構建的,這使得訪問瀏覽器內的 API 變得輕而易舉。 例如,使用 GWT 編譯器獨有的語法特性,您可以編寫以下 Java 代碼:
public static native void nativeMethod(T1 a1, T2 a2, ...) /*-{ //place your JavaScript code here }-*/;
並且您可以自由地在 JavaScript 中實現方法的主體。 您甚至可以將 JavaScript 對象包裝在 JavaScriptObject (JSO) 中,並使其在您的 Java 代碼中可訪問。
這個層發揮作用的一個例子可以在 UI 組合的上下文中找到。 主流 Java 一直使用標準的 Widgets 工具包來構建 UI 元素,利用 Java Native Interface 來訪問底層操作系統的窗口和輸入系統。 GWT 的互操作層做同樣的事情,因此傳統的 Widget 可以在瀏覽器中無縫工作。 唯一的區別是,在這種情況下,底層系統是瀏覽器和 DOM。
然而,本機前端框架近年來迅速改進,如今與 GWT 的 Widgets 相比具有顯著優勢。 隨著這些框架變得越來越複雜,在 JSNI 中實現它們的嘗試暴露了互操作層架構中的缺陷。 從 2.7 版開始,GWT 引入了 JsInterop,這是一種基於 Java 註釋的新方法,它允許您快速輕鬆地將 GWT 類與 JavaScript 集成。 不再需要編寫 JSNI 方法或 JSO 類。 相反,您可以簡單地使用@JSType
或@JSProperty
類的註解,讓您可以像使用 Java 一樣使用原生 JavaScript 類。
JsInterop 的完整規範仍在進行中,最新的更新只能通過從 GWT 存儲庫編譯源來試用。 但很明顯,這是允許 GWT 跟上不斷發展的 Web 平台的新方向。
一個利用 JsInterop 的正在進行的項目是最近發布的 gwt-polymer-elements,它使來自 Polymer 的所有 Iron 和 Paper 元素都可用於 GWT。 這個庫的有趣之處在於開發人員不需要手動生成 Java API。 項目使用 gwt-api-generator 通過解析 Polymer 庫和 JSDoc 註解直接生成大部分接口。 這使得保持綁定更新變得容易。
最後的話
隨著過去兩年對編譯器、互操作層以及生成代碼的性能和大小的改進,很明顯 GWT 不僅僅是“另一個 Web 開發工具”,而且有望成為主要的參考工具包開發大型、複雜的 Web 應用程序,甚至可以成為製作更簡單的應用程序的絕佳選擇。
作為一名開發人員和顧問,我每天都會在工作中使用 GWT,但我更喜歡 GWT,因為它讓我突破了瀏覽器功能的極限,並展示了現代 Web 應用程序可以與桌面應用程序一樣強大。
GWT 項目的社區非常活躍,基於 GWT 的新庫、項目和應用程序不斷被提出。 在佛羅倫薩,社區驅動的 GWTcon2015 將於 11 月 11 日舉行會議。 如果您在該地區,我希望您能來會見一些核心開發人員,並了解所有參與這個令人驚嘆的工具包發展的機會。