1. 程式人生 > >[譯] Hummingbird: 構建Flutter Web應用

[譯] Hummingbird: 構建Flutter Web應用

在今天的Flutter Live上,我們宣佈正嘗試在Web上執行Flutter。在這篇文章中,描述了我們如何應對嘗試過程中遇到的挑戰以及當前該技術的狀態。在本文的最後,您將找到有關互操作和嵌入的問題及答案;



讓我們快速回顧一下Flutter的架構。 Flutter是一個多層系統,更高的層級更方便開發者使用及操作,並允許開發者用更少的程式碼完成更多的功能,而較低的層級雖然為開發者提供更多的控制能力,然而這種控制也是有代價的:開發者必須處理一些更復雜的事項,當較高層不能滿足開發人員的需求時,他們可以深入到較低層。開發人員可以訪問Flutter Engine上方的所有層程式碼;


                                                    Flutter 移動端架構 Flutter Engine作為Flutter暴露出來的最底層庫,比如dart:ui。它對widgets,物理模擬(如重力等),動畫或佈局(文字佈局除外)一無所知。它所知道的是如何將圖片組合到螢幕上並將它們變成畫素呈現。在dart:ui上直接編寫應用程式是很困難的,這就是我們為開發者建立更高層的原因; dart:ui之上的層級就是我們所謂的“框架”層。它下面的層級我們稱之為“引擎”。該框架完全使用Dart程式語言編寫。大多數引擎都是用C ++編寫的,特定於Android的部分用Java編寫,而iOS特定的部分用Objective-C編寫。 dart:ui中的一些基本類和函式是用Dart編寫的,主要用作Dart和C ++之間的橋樑。 Flutter還提供系統外掛。外掛是用一種語言編寫的程式碼,它可以直接訪問移動生態系統的OEM庫和第三方庫。要為Android建立外掛,您可以使用Java或Kotlin編寫程式碼。 iOS外掛是使用Objective-C或Swift程式碼編寫的。

Hello, The Web

Web平臺已經發展了數十年,包括許多技術和規範。有一些術語用於描述相關功能:HTML,CSS,SVG,JavaScript,WebGL。為了在Web上執行Flutter,我們需要:
  • 編譯Dart程式碼:Flutter是用Dart編寫的,我們需要在Web上執行Dart
  • 選擇要在Web上執行的Flutter子集:在Web上執行所有Flutter程式碼是不切實際也是毫無幫助的。其中一些是特定於具體平臺的,例如Android和iOS。
  • 選擇足夠的Web功能子集:隨著時間的推移,Web平臺會累積功能重疊的功能。例如,您可以使用HTML + CSS,SVG,Canvas和WebGL繪製圖形。
從Dart語言誕生起,Dart語言就可以被編譯成JavaScript語言。許多重要的應用程式從Dart編譯為JavaScript,並已經被投放到生產環境中執行。 Flutter的編譯策略依賴於同樣的基礎設施。 當我們開始探索時,我們面臨著UI渲染的幾種選擇。我們很快意識到我們想要支援的特定Flutter層決定了我們將採用何種Web技術實現。我們製作了三個原型:
  1. 只是Widgets:這個原型實現了Flutter的Widget框架,並提供了一組核心佈局Widget作為構建自定義Widget的基礎。對於佈局和定位,它依賴於Web的內建功能,例如flexbox,網格佈局,瀏覽器滾動等。
  2. Widgets+自定義佈局:此原型包括Flutter的佈局系統(由RenderObject提供),但將渲染物件直接對映到HTML元素。
  3. Flutter Web Engine:這個原型保留了dart:ui之上的所有層,並提供了一個在瀏覽器中執行的dart:ui實現;
Flutter最有價值的功能之一是它可以跨平臺移植。您可以(我們鼓勵您)編寫自定義平臺特定程式碼,該程式碼可以共享到各跨平臺而不需要有任何差別。這允許使用單個程式碼庫編寫面向多個平臺的應用程式; 在嘗試將幾個示例應用程式移植到Web之後,我們意識到原型#1和#2不能提供Flutter開發人員喜歡(可接受)的可移植性級別。因此,我們決定使用原型#3:Flutter Web Engine,因為這將允許最高的框架級程式碼在不同平臺之間重用:


                            Flutter for the Web Architecture (Hummingbird) 既然知道了我們想要實現整個dart:ui API,我們需要選擇一組Web技術來構建。 Flutter一次呈現一幀UI。在每一幀內,Flutter構建Widget,執行佈局,最後在螢幕上繪製它們。 建立Widgets Widget的構建機制不依賴於應用程式執行的環境。該過程只需要例項化記憶體中的物件並跟蹤它們的狀態,當狀態改變時,計算佈局和繪畫所需的最小更新。將此部分移植到Web上非常簡單,當Dart團隊在dart2js中實現了super-mixin支援之後,編譯器將所有widget和widget框架編譯為JavaScript時幾乎沒有任何問題; 佈局 佈局系統有點棘手。最大的挑戰是文字佈局。其他所有Widget - Center,Row, Column, Stack, Scrollable, Padding, Wrap等 - 這些widget都由框架佈局,因此無需修改即可編譯到Web上執行。 在Flutter中,您可以通過建立Paragraph物件並呼叫其layout()方法來放置一段文字。不幸的是,Web缺少直接的文字佈局API。我們用來測量文字佈局屬性的技巧是讓瀏覽器將其佈局,然後從DOM元素中讀回相關屬性。 放置文字段落時,Flutter測量段落的高度,寬度,最大內在寬度,最小內在寬度以及字母和表意基線(下圖黃色虛線)。這些屬性如下所示。


                                          Paragraph layout attributes 您可以在Flutter的 段落文件中找到更多詳細資訊。 要測量這些屬性,我們首先在HTML DOM元素中放置一個段落,然後我們讀取元素的尺寸。這會導致瀏覽器將其佈局。例如,要獲取元素的寬度和高度,我們呼叫 offsetWidthoffsetHeight。為了測量基線,我們將段落放置在一個元素中,該元素配置為使用flex row進行自我佈局。在段落旁邊,我們放置另一個名為“探針”的元素。因為探針與文字的基線對齊,所以呼叫 getBoundingClientRect就可以得到基線。我們使用類似的技巧來測量最小和最大固有寬度。

Painting(繪製)

最後但同樣重要的是,我們需要繪製上述這些Widgets。我們在這方面的探索經歷了很多誤區,它仍然是我們研究中最活躍的領域之一。在幀渲染結束時,我們所有的widgets都需要在螢幕上變成畫素。在瀏覽器中,這意味著它們必須歸結為HTML / CSS,Canvas,SVG和WebGL的某種組合。 我們還沒有看過WebGL,主要是因為它是較底層級別的,並且要求我們重新實現瀏覽器已經可以做的事情,例如文字佈局和光柵化2D圖形,也因為我們還沒有弄清楚如何使用非Flutter元件的可訪問性,文字選擇和合成可以與WebGL一起使用。 我們的早期原型之一就是為每個RenderObject生成了一個HTML元素。我們確實獲得了有希望的結果,但結果卻證明了API的變化太大了。我們必須用Flutter維持一個巨大的程式碼增量,所以我們擱置了這個想法。 我們目前正在同時探索的兩種方法:
  1. HTML+CSS+Canvas的組合
  2. CSS Paint API

HTML+CSS+Canvas

通過這種方法,我們將框架生成的圖片分類為使用HTML + CSS表達的圖片,以及使用Canvas 2D表達的圖片。然後,我們輸出結合了HTML,CSS和2D畫布的HTML DOM。 我們更喜歡HTML + CSS,因為它有瀏覽器的 顯示列表支援。這意味著我們可以優化圖片的光柵化在瀏覽器上的渲染引擎。這也意味著我們可以應用任意變換,尤其是旋轉和縮放,而不必擔心畫素化。我們將此畫布實現稱為“DomCanvas”。 如果我們無法使用HTML + CSS表達圖片,我們會回到畫布。 Canvas 2D允許我們繪製幾乎所有的Flutter繪圖命令。如果將Flutter的 Canvas與Web的 CanvasRenderingContext2D進行比較,您會發現許多相似之處,在畫布上繪畫是高效的,因為它不會建立需要隨時間維護的可變樹節點,如HTML DOM或SVG。 2D畫布的一個挑戰是瀏覽器將其表示為點陣圖,即儲存寬度x高度畫素的記憶體緩衝區。因此,縮放畫布會導致畫素化。如果縮放導致圖片大小的變形,我們需要調整畫布大小。我們發現分配畫布相當昂貴,因此調整它們的大小。最重要的是,當將多個畫布合成到同一頁面上時,瀏覽器必須執行柵格合成,合成柵格與顯示列表的工作方式不同。您可以將多個顯示列表繪製到同一個記憶體緩衝區中。我們呼叫Canvas 2D支援的canvas實現BitmapCanvas。我們正在研究使點陣圖畫布更有效的方法。 為了表達Flutter的 opacity, transform, offset, clip rect和其他 圖層,我們使用純HTML元素。例如,不透明度層變為<flt-opacity>元素,其上具有不透明度CSS屬性,變換層變為帶有變換CSS屬性的<flt-transform>元素,而clip rect變為帶有overflow:hidden的<flt-clip-rect>。 完成所有操作後,幀將被渲染在作為HTML元素樹的頁面上呈現,其中DomCanvas和BitmapCanvas作為葉節點。例如:

相關推薦

[] Hummingbird: 構建Flutter Web應用

在今天的Flutter Live上,我們宣佈正嘗試在Web上執行Flutter。在這篇文章中,描述了我們如何應對嘗試過程中遇到的挑戰以及當前該技術的狀態。在本文的最後,您將找到有關互操作和嵌入的問題及答案; 讓我們快速回顧一下Flutter的架構。 Flu

使用Nginx+CppCMS構建高效Web應用服務器(之三)

影響 size ppc light .html 數據顯示 com logs cppcms 使用Nginx+CppCMS構建高效Web應用服務器(之三)   --充分利用服務器和客戶端計算能力              歡迎測試,攻擊:http://www.lite

第五章構建Spring Web應用程序——SpringMVC起步

而是 ack 前端控制器 ota ring ron urn pan 處理器 跟蹤Spring MVC的請求   註:流程:     1)請求離開瀏覽器到達的第一站就是前端控制器,在這裏一個單例的Servlet將請求委托給應用程序的其他組件來執行實際處理。Dispatche

構建Spring web 應用程序 (三)

auto BE lib www itl last pub oos bean 處理表單 一、首先寫一個表單 <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEnc

Spring實戰4 第5章 構建Spring Web應用程式

一,構建Spring Web應用程式## 1,Spring MVC起步 1.1跟蹤Spring Mvc請求 在請求離開瀏覽器是,帶有使用者請求的內容資訊 第一站是Spring的DispatcherServlet,在Spring MVC中,它就是前端控制器。它的任務是將請求傳送給Sp

使用SSM技術構建Java Web應用時的中文亂碼問題

需要把握並檢查以下幾點: 1)提交頁面表單時,要求JSP的contentType和pageEncoding都要是"UTF-8" 。且method要採用POST。 2)web.xml中要設定過濾器,使用了spring庫中的編碼類,使編碼為utf-8。 3) Mybatis連線M

使用SuperWebSocket 構建實時 Web 應用

Web 應用的資訊互動過程通常是客戶端通過瀏覽器發出一個請求,伺服器端接收和稽核完請求後進行處理並返回結果給客戶端,然後客戶端瀏覽器將資訊呈現出來,這種機制對於資訊變化不是特別頻繁的應用尚能相安無事,但是對於那些實時要求比較高的應用來說,比如說線上遊戲、線上證券、裝置監控、新聞線上播報、RSS 訂閱推送等等,

Spring實戰——構建Spring Web應用程式

本篇部落格記載搭建springmvc的過程,使用Java將DispatcherServlet配置在Servlet容器中,而不是使用web.xml 進行配置。 注意:使用Java配置僅適用於支援servlet3.0的伺服器,如Tomcat7或者更高版本。 專案使用Maven搭建:

《Spring實戰》學習筆記-第五章:構建Spring web應用

之前一直在看《Spring實戰》第三版,看到第五章時發現很多東西已經過時被廢棄了,於是現在開始讀《Spring實戰》第四版了,章節安排與之前不同了,裡面應用的應該是最新的技術。 本章中,將會接觸到Spring MVC基礎,以及如何編寫控制器來處理web請求,如何通明地繫

Spring 註解學習手札(一) 構建簡單Web應用

轉載自 http://snowolf.iteye.com/blog/577989 我們將用到如下jar包:  引用 aopalliance-1.0.jar  commons-logging-1.1.1.jar  log4j-1.2.15.ja

Spring實戰 | 第二部分 Web中的Spring(第五章 構建Spring Web應用程式)

第五章 構建Spring Web應用程式 對映請求到Spring控制器 透明地繫結表單引數 校驗表單提交 一

如何使用 Azure Active Directory 認證和 Microsoft Graph 構建 Blazor Web 應用

# 如何使用 Azure Active Directory 認證和 Microsoft Graph 構建 Blazor Web 應用 英文原文:https://developer.microsoft.com/en-us/identity/blogs/how-to-build-a-blazor-web-app

用ASP.NET Core MVC 和 EF Core 構建Web應用 (二)

work nal nta 多個 包括 catch web 應用 自動 選項卡 本節學習如何執行基本的 CRUD (創建、 讀取、 更新、 刪除) 操作。 自定義“詳細信息”頁 學生索引頁的基架代碼省略了 Enrollments 屬性,因為該屬性包含一個集合。 在“詳細信息”

用ASP.NET Core MVC 和 EF Core 構建Web應用 (九)

fix pro school time lap namespace 繼承映射 數據庫表 eas 在上一節中,已經處理了並發異常。 本節將演示如何在數據模型中實現繼承。 在面向對象的編程中,可以使用繼承以便於重用代碼。 在本教程中,將更改 Instructor和 Studen

用ASP.NET Core MVC 和 EF Core 構建Web應用 (十)

pan 信息 expr dispose writing AS das ech 任務欄 之前的學習中,已經以每個類一張表的方式實現了繼承。 本節將會介紹在掌握開發基礎 ASP.NET Core web 應用程序之後使用 Entity Framework Core 開發時需要註

SpringBoot學習筆記(11):使用WebSocket構建交互式Web應用程序

-- 文件 基於 ping pan lan tin eas return SpringBoot學習筆記(11):使用WebSocket構建交互式Web應用程序 快速開始   本指南將引導您完成創建“hello world”應用程序的過程,該應用程序在瀏覽器和服務器之間來回發

5分鐘Serverless實踐 | 構建無服務器圖片鑒黃Web應用

dem 結果 資源利用率 url 獲取 點擊 圖片 代碼包 image Serverless是什麽 Serverless中文譯為“無服務器”,最早可以追溯到2012年Ken Fromm發表的《Why The Future Of Software And Apps Is Se

【webpack外掛使用】在開發中快速掌握並使用Webpack構建web應用程式

1.webpack-dev-server外掛的基本使用 入門程式 const path = require('path'); // 匯出一個Webpack的配置物件(通過node中的模組操作,向外暴露了一個配置物件) module.exports = { // 需要在這裡手動指定入口

jsp----前後端分離---框架---web應用構建

java勸退教程-作業系統篇(三) 本篇文章,我們來講講技術,系統演進的過程對我們java開發帶來的影響。本文可能會涉及到一些技術名詞,不懂沒有關係,先混個眼熟,我們後面會一個個詳細介紹。下面會列舉三個不同時期的技術,因為同時期也會有各種各樣的技術,所以我們只介

ASP.NET Core 入門教程 1、使用ASP.NET Core 構建第一個Web應用

一、前言 1、本文主要內容 Visual Studio Code 開發環境配置 使用 ASP.NET Core 構建Web應用 ASP.NET Core Web 應用啟動類說明 ASP.NET Core Web 專案結構說明 2、本教程環境資訊 軟體/環境說明 作業系統 Windows 10