整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          僅僅過去 4 年,微軟最終放棄了 Electron

          僅僅過去 4 年,微軟最終放棄了 Electron

          軟近期宣布,旗下 Teams 應用活躍用戶已經達到驚人的 2.5 億。這讓 Teams 成了繼 Word 和 Excel 之后,微軟 Office 生產力套件中的又一位當紅明星。然而,Teams 一直受到性能問題的困擾,瘋狂吞噬系統資源,用戶們對此吐槽不斷。

          前不久,微軟 Teams 高級副總裁宣布,Teams 將放棄 Electron,轉而匹配微軟自己的 Edge WebView2 渲染引擎以尋求性能提升。官方聲稱,調整之后 Teams 的內存消耗量將直接減半,并有望以 Teams 2.0 的形象隨 2022 年末上市的 Windows 11 一同亮相。

          據悉,在 Windows 11 中,用戶可以通過文字、聊天、語音或視頻與聯系人即時連接,無論他們使用的是 Windows、Android 還是 iOS。對方即使沒有下載 Teams 應用程序,雙方也可以通過雙向短信聯系。Windows 11 還支持立即靜音和取消靜音,或者直接從任務欄開始呈現 Teams。

          追求更低的內存占用

          對于已經嘗試了許多不同技術來減少桌面客戶端所需內存的微軟來說,這似乎是邁出的很大一步了。有很多網友表示很開心看到這一變化。

          “Angular 也不見了。我們現在 100% 使用 reactjs。”Teams 工程師 Rish Tandon 在推特上表示。“這些變化聽起來很棒!”有人留言道,但對于網友提出的“Win10 和 MacOs 也會有嗎?”Tandon 沒有回答。

          根據 Tandon 的說法,這項工作大概花費了 Teams 團隊 6 個月的時間,優化后的 Teams 2.0 消耗的內存將只有 Teams 1.0 上相同帳戶的一半。

          時至今日,仍有眾多知名應用都選用 Electron 來提供支持。Electron 框架能夠幫助 Web 開發者將自己的 Web 應用發布至桌面平臺,且不受任何特定平臺的復雜性影響。但由于一切 Electron 應用程序后端都要運行只屬于自己的 Chrome OS 實例,所以同時運行兩個以上此類應用就會瘋狂消耗主機資源。

          于是,在 Electron 之上執行大量處理操作的 Teams 也無法避免地瘋狂占用內存、拖慢計算機速度。微軟甚至專門發布了文檔頁面,解釋為什么 Teams 的內存占用量如此之高。

          與 Electron 不同,WebView2 會監控 Chromium 的行為、檢測還有多少系統內存可用,從而更有效地利用內存資源優化渲染體驗。如果其他應用程序或服務需要系統內存,Chromium 就會將空間移交給這些進程。如此一來,內存容量較小的低端計算機也能帶來不錯的性能表現。

          WebView2 更像是一種類似于應用窗口的控件,專門用于渲染 Web 頁面。事實上,WebView2 控件還允許在原生應用程序中嵌入 Web 技術(包括 HTML、CSS 與 JavaScript)。所以要想將 Teams 規模的應用程序過渡至 WebView2,開發團隊需要對大量由 Electron 提供的抽象進行重寫。因此,Teams 在本質上將變得更接近于原生 Windows 應用程序。

          目前,WebView2 已經被 Outlook 作為微軟“One Outlook”項目的組成部分。

          為什么選 Webview2 ?

          Teams 需要處理大量音頻與視頻內容,所以微軟認為最好能把一部分工作負載轉移給 WebView2 更擅長的原生形式。事實也證明,Electron 抽象并不能有效完成這些處理任務。但從嚴格意義上來說,Webview2 并不屬于 Electron 的替代方案。

          Webview2 并不是 Electron 那樣可以在桌面平臺上快速發布 Web 應用的打包器。Electron 與 WebView2 都是以 Chromium 為基礎構建而成,但更嚴格地說,WebView2 繼承的是 Edge 源代碼,而 Edge 又用到了 Chromium 源代碼的一個分支。Electron 則不與 Chrome 共享任何 DLL。WebView2 二進制文件硬鏈接至 Edge(截至 Edge 90 的 Stable 版本),所以二者使用著相同的磁盤及其他一些工作集機制。

          Electron 應用會始終捆綁并分發其開發過程中所使用的特定 Electron 版本。相比之下,WebView2 在發布方面則提供兩個選項:可以直接捆綁應用開發時所使用的特定 WebView2 庫,也可以使用系統上已經存在的共享運行時版本。WebView2 為這兩種方法分別提供工具,包括一個防止共享運行時丟失的引導安裝程序。而且從 Windows 11 版本開始,操作系統已經內置有 WebView2 運行時。

          捆綁二者框架的應用程序負責保持框架更新,包括更新各次要安全增強版本。而對于使用共享 WebView2 運行時的應用程序,版本維護則依靠 WebView2 自己的更新程序,會以類似 Chrome 或 Edge 的方式獨立于應用程序之外運行。WebView2 更新應用程序的代碼或任何其他依賴項仍由開發者負責管理,這一點與 Electron 相同。值得注意的是,Windows 更新管理功能并未覆蓋到 Electron 與 WebView2。

          Electron 與 WebView2 都繼承了 Chromium 的多進程架構——即由單一主進程同一個或多個渲染器進程通信。這些進程同系統上正在運行的其他應用程序完全分離,每個 Electron 應用程序都擁有一個獨立的進程樹,其中包含一個根瀏覽器進程、部分實用程序進程外加一定數量的渲染進程。與應用套件類似,使用相同用戶數據文件夾的各 WebView2 應用程序之間會共享非渲染器進程,但使用不同數據文件夾的 WebView2 應用程序之間則不共享任何進程。

          ElectronJS 流程模型:

          基于 WebView2 的應用程序流程模型:

          Electron 能夠為各類常見桌面應用需求提供 API,例如菜單、文件系統訪問、通知等等。WebView2 則能以組件的形式集成到 WinForms、WPF、WinUI 或者 Win32 等應用程序框架當中。另外,WebView2 僅通過 JavaScript 提供符合 Web 標準的操作系統 API。

          Electron 當中集成有 Node.js,因此 Electron 應用程序可以使用來自渲染器及主進程的任何 Node.js API、模塊或者 node-native-addon。WebView2 應用程序則不會對應用程序各個部分所使用的編程語言或框架做任何預設,JavaScript 代碼必須通過 application-host 進程代理才能訪問操作系統。

          Electron 提供可配置的 Web 內容安全模型,配置范圍涵蓋完全開放訪問到完全沙箱模式。WebView2 內容則始終保持沙箱化。Electron 還提供關于如何選擇安全模式的詳盡說明文檔,而 WebView2 則提供豐富的安全最佳實踐。

          Electron 源代碼在 GitHub 上進行維護與交付,各應用程序能夠修改并構建屬于自己的 Electron 品牌。WebView2 源代碼則并未登陸 GitHub。

          具體差異總結如下:

          Electron

          WebView2

          構建基礎

          Chromium

          Edge

          源代碼是否登陸GitHub

          是否共享Edge/Chrome DLL

          是(截至Edge 90)

          不同應用程序間是否共享運行時

          可選

          應用程序API

          Node.js

          沙箱

          可選

          始終

          需要應用程序框架

          所支持平臺

          Mac, Win, Linux

          Win (Mac/Linux正在籌備)

          不同應用間是否共享進程

          從不

          可選

          框架更新由誰管理

          應用程序

          WebView2

          性能差異有多大?

          需要強調一點區別,這也是 Electron 應用程序中的一項重要性能考量因素。

          在 Chromium 當中,瀏覽器進程負責充當沙箱渲染器與系統其余部分之間的 IPC 代理。雖然 Electron 支持非沙箱渲染進程,但也有不少應用會選擇啟用沙箱以提升安全水平。WebView2 則始終啟用沙箱,所以對于大多數 Electron 及 WebView2 應用程序而言,IPC 確實會影響到整體性能。

          雖然 Electron 與 WebView2 的流程模型基本相似,但底層 IPC 卻有所不同。JavaScript 與 C++或 C#之間的通信需要經過編組,而且最常見的方法是編組為 JSON 字符串。請注意,JSON 序列化/解析操作的資源成本極高,因此 IPC 瓶頸必然會對性能產生負面影響。因此從 Edge 93 開始,WebView2 將對網絡事件使用 CBOR。

          Electron 則通過 MessagePorts API 支持任意兩個進程之間的直接 IPC,其中使用到了結構化克隆算法。利用這項功能,應用程序就能避免在不同進程間發送對象時執行資源成本高昂的 JSON 序列化操作。

          Electron 與 WebView2 雖然有著不少差異之處,但二者在渲染 Webn 內容方面卻高度一致。最核心的影響還是來自應用程序架構與 JavaScript 庫/框架在內存與性能層面的影響,畢竟同樣師出 Chromium。

          2017 年時,Electron 可以說是 Web 應用在桌面平臺發布的最佳、甚至是唯一選項,但如今它卻成了需要被優化淘汰的對象。這可能代表著跨平臺框架格局中的一大關鍵里程碑,也可能僅僅是微軟 Teams 做出的一項小小調整。但具體如何,還有待時間的檢驗。

          相關鏈接:

          https://www.electronjs.org/blog/webview2

          https://blog.devgenius.io/microsoft-is-finally-ditching-electron-9e081757f9db

          每一個特定或者特殊的日子里,幾乎所有的網站都變成了灰色,那么這種效果是怎么實現的呢?

          今天就來簡單的實現一下這樣的效果。



          添加以下全局CSS樣式,可以實現此效果:

          代碼一:

          html {
            -webkit-filter: grayscale(100%);filter:progid:DXImageTransform.Microsoft.BasicImage(graysale=1);
          } 
          <!-- 可以是整個網站變成灰色的  -->


          實現網頁顏色變灰這個效果,非常簡單:

          filter: grayscale(100%);
          

          這樣一段代碼即可實現,放在html和body的css屬性里即可實現。

          意思是修改所有的顏色為黑白 (100% 灰度):

          灰色網站會加入這段代碼,你可以按F12,把這段源碼刪除,即可變成彩色


          代碼二:

          html { 
             filter:progidXImageTransform.Microsoft.BasicImage(grayscale=1); 
          }

          使用方法:這段代碼可以變網頁為黑白,將代碼加到CSS最頂端就可以實現素裝。建議全國站長動起來。為在地震中遇難的同胞哀悼。

          如果網站沒有使用CSS,可以在網頁/模板的HTML代碼<head>和</head> 之間插入:

          <style>
             html{
               filter:progidXImageTransform.Microsoft.BasicImage(grayscale=1);
            }
          </style>

          有一些站長的網站可能使用這個css 不能生效,是因為網站沒有使用最新的網頁標準協議:

          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
          <html xmlns="http://www.w3.org/1999/xhtml">

          請將網頁最頭部的<html>替換為以上代碼。

          有一些網站FLASH動畫的顏色不能被CSS濾鏡控制,可以在FLASH代碼的<object …>和</object>之間插入:

          <param value="false" name="menu"/>
          <param value="opaque" name="wmode"/>

          最簡單的把頁面變成灰色的代碼是在head 之間加

          <style type="text/css"> 
          html {
             FILTER: gray
          }
          </style>


          代碼三:

          html{ 
          filter: grayscale(100%); 
          -webkit-filter: grayscale(100%); 
          -moz-filter: grayscale(100%);
          -ms-filter: grayscale(100%); 
          -o-filter: grayscale(100%); 
          filter: url("data:image/svg+xml;utf8,#grayscale"); 
          filter:progid:DXImageTransform.Microsoft.BasicImage(grayscale=1); 
          -webkit-filter: grayscale(1);
          }


          總結:

          以上幾種代碼(方法),都是通過CSS的濾鏡來控制頁面的顯示而已,唯一不同的就CSS代碼及調用的方式。在css的修飾時還有權重問題,所以有時候css代碼不生效的時候可以考慮一下代碼的權重問題。

          歡迎關注第一山,今后將有更多前端開發技術與大家共同交流學習。

          作者 | Lew C 譯者 | 彎月

          出品 | CSDN(ID:CSDNnews)

          以下為譯文:

          現如今的各個網站,包括你現在正在使用的這個網站,都是通過HTML、JavaScript和CSS編寫的。如果要求在創建網站的時候,不要使用這三種技術中的任何一種,你可能就會問為什么。

          然而,縱觀整個Web開發的發展歷史,我們就會發現該領域涌現了很多技術,比如曾經的Flash、Silverlight等,所有具備競爭力的技術都曾嘗試在瀏覽器的市場中分一杯羹,希望開發人員使用不同的技術來創建網站。然而,它們最后的結局大多雷同:出師未捷身先死。而我又憑什么告訴你這片廣闊天地中又多了一位競爭對手呢?尤其是該領域的眾多技術在經過數年的努力之后,無一能夠找到出路。

          別著急,我們先來分析一下過去這些技術的共同點:

          1. 這些技術都需要瀏覽器插件才能運行。通常它們都需要平臺特有的瀏覽器插件才能在目標平臺上運行。Silverlight就是一個很好的例子,當時使用Linux的人無法觀看Netflix,因為該網站采用了Silverlight(Linux不支持Silverlight)。當然,我們有開源的替代方案,但沒有官方解決方案。

          2. 它們引入了安全漏洞。Flash就有此惡名(已知漏洞超過1000個)。瀏覽器必須加載插件才能顯示內容,此時瀏覽器的安全保護措施不再有效,因為該插件擁有計算機上的所有權限。

          3. 性能比不上純HTML。就加載插件和顯示文本的速度而言,僅使用HTML和CSS的速度肯定超過了加載插件。

          4. HTML 5問世,CSS得到了提升。突然之間,無需大費周折也可以建立美麗又愉悅的體驗感。有些瀏覽器討厭標準,而且還使用了特別手法或使用了特定于供應商的實現,雖然它們更好用,但是最終還是被干掉了。

          如此種種跡象表明,選擇原生HTML創建新Web應用更加容易。畢竟,如果創建Web體驗所采用的技術被棄用,而且收不到安全修復程序,那么你將別無選擇,只能另選一種新的支持語言重新編寫應用。但是,為什么如今會是這樣一種局面呢?為何HTML成為了蓬勃發展的互聯網的支柱呢?


          新時代的曙光


          1991年8月6日,互聯網誕生。隨后我們又經歷了互聯網泡沫。我們來想一想,1991年互聯網問世,9年后互聯網泡沫破滅,造成了1.7萬億美元的驚人損失。這意味著互聯網泡沫造成的損失相當于當年美國GDP的15%。

          我們經歷了這段歷史,因為當時互聯網越來越流行,而我們編寫網站的方式也越來越標準。隨著時間的流逝,我們建立了HTML 4等標準,這些標準可以確保我們編寫的HTML可以在絕大多數HTML解釋器上運行。級聯樣式表(Cascading Style Sheets,CSS)也于1996年問世,而在此之前的一年,JavaScript也進入了市場。你見過沒有JavaScript或CSS的網站嗎?我敢肯定,你的體驗一定不怎么愉快。

          但是,縱觀整個歷史,網絡的某些方面并沒有發生變化。平心而論,很多時候互聯網也是迫不得已:如果沒有迫不得已的原因,你肯定不想對HTML標準進行重大修改,所以對互聯網的工作原理進行大范圍修改的事情可能永遠都不會發生。于是互聯網就成了今天的樣子。

          文檔

          當互聯網剛問世的時候,人們并不能像如今一樣使用應用。可能有人還記得通過瘦客戶端,連接到另一端的大型機上。當時的“應用”僅僅是屏幕上的幾行文字。人們習慣了將一切都當作文檔處理,就像手頭可以閱讀的紙張一樣。因此,HTML頁面最初的目的就是生成HTML文檔,這一點毫不令人奇怪。如果你曾用過JavaScript,那么肯定對document.getElementById()等函數并不陌生。你在網頁上所做的一切操作都是為了生成文檔,然后轉換文檔。

          大多數網頁都太高,無法容納到一個窗口中。因此,用戶不得不用手指滑動頁面,或滾動鼠標。我想不出如今哪個網站可以正好顯示在一頁之內,因此開發人員必須要處理位于當前可見部分之上或之下的頁面。

          但是,你仍然希望網頁的某些部分保持在特定的位置或以特定的方式對齊,那么就需要使用CSS中的position等來控制元素的布局。CSS有數不盡的屬性(確切地說是520個),顧名思義,這些樣式會層疊到其子元素中。如果你試圖將文章的特定部分顯示成特定的樣子,那么就會變得非常混亂。如果使用現有的樣式框架(比如Angular Material),那么情況也好不了多少,因為你需要覆蓋框架自帶的CSS,才能實現你想要的布局。當然你可以使用!override來覆蓋CSS,但是如此做法不過是引鴆止渴罷了。讀到此處,你可能會想,“這個家伙似乎對CSS毫不報希望啊。”沒關系,我不會在這一點上與你爭論。但是,如果你的設計師對網頁外觀有一定的要求,那么CSS就會變得非常復雜。

          學習語言

          為了創建一個簡單的網站,你需要使用三種不同的語言,即HTML、JavaScript和CSS,而且這只是針對網站本身的。網頁必須美觀,但如果你不知道如何編寫高效的JavaScript或CSS的樣式不好的話,恐怕就很難了。

          如果你希望網站執行任何操作,則可以使用Angular或React之類的框架。隨著你通過npm引入軟件包,應用的規模也會增大,所以你還需要使用打包工具(比如Webpack等),將所有軟件包都打包到一起,并適當地縮小規模。Webpack本身就是一個主題(而且還是一個大主題),但它是一個值得考慮的主題,而且相當一部分Web應用都是用它構建的。

          打包與轉譯

          在建立網站,并擁有了自己的軟件包后,你需要使用打包工具來打包客戶端應用,還需要確保能夠在瀏覽器中正常工作。根據使用的瀏覽器,你還需要添加一些功能,以便用戶的瀏覽器可以使用你的網站。如果你使用的是TypeScript之類的語言,則Webpack還可以將其轉譯為JavaScript。雖然這沒有什么不好,但是這個過程非常復雜,而且還有很多可變因素。如果你的網站崩潰了,那么究竟是哪里出了問題?是代碼出了問題,還是在壓縮代碼的過程中出了問題?是Webpack沒有正確打包代碼,還是轉譯的過程出現了問題?這些復雜的流水線會加劇調試或查找根本原因的難度。


          Flutter好在哪里?


          即便你聽說過Flutter,可能也是在移動應用開發的語境下。究竟如何將Flutter應用到Web開發呢?對于普通的HTML網頁,你可以將頁面作為文檔來處理。但在Flutter中,“頁面”(或用戶與之交互的內容)實際上是繪制到HTML畫布上的。Flutter控制著繪制到屏幕上的每一個像素,而且它不使用HTML、JavaScript或CSS來定義外觀或邏輯。(從技術的角度來看,原生Dart代碼通過dart2js轉換成了JavaScript,但業務邏輯實際上并不是用JavaScript編寫的。)

          這句話讓你吃驚的地方可能有兩個:首先,沒有HTML;其次,所有的內容都是繪制到畫布上的。我能理解,這話聽起來有點奇怪,至少直接繪制到畫布上的性能可不好。下面,讓我們進一步研究一下。

          繪制到畫布而不是文檔

          首先,我們不使用HTML編寫網頁,也不會將內容寫入文檔。初聽之下,感覺很奇怪。但是,使用HTML開發網頁時,你究竟做了哪些工作?我們在前面就討論過了,你創建的文檔對于用戶設備的窗口來說太大了,你需要滾動。你正在閱讀的這篇文章,頁面的高度就超過了窗口大小,你需要不斷向上滾動。

          仔細想一想,我們設計的用戶界面超過了窗口的縱向大小,用戶必須滾動頁面才能瀏覽全部內容,這不是很奇怪嗎?如果你希望用戶從左到右(不是從上到下)滾動窗口,該怎么辦?恐怕在普通網頁上可不容易實現。

          在Flutter中,如果想讓某一部分內容水平滾動,就只需要將小部件包裝到SingleChildScrollView。你也可以指定滾動條的方向,無論滾動條是在垂直方向還是水平方向上滾動。

          因為Flutter的基本概念是,在單獨的小部件中繪制文檔,而不是將文檔繪制到屏幕上,所以開發人員完全可以控制如何布局應用程序。

          只使用一種語言

          如前所述,為了創建一個出色的網站,你必須掌握HTML、JavaScript和CSS。這也意味著,你所需的知識無法在這些語言之間融會貫通,例如,你不能在HTML中使用任何JavaScript的知識。HTML純粹是標記語言,CSS純粹是樣式語法,而JavaScript純粹是編程語言。這些語言都不包含類型檢查等功能,所以雖然CSS看似很完整,但在用戶使用頁面的時候,就會悄無聲息地出問題。

          Flutter采用了Dart語言,并使用Dart編寫了應用程序的所有外觀和業務邏輯。Dart具有靜態類型檢查,而且即將推出安全性,因此應用程序中的每一行代碼,無論是描述應用的外觀,提供樣式,還是控制業務邏輯,都是類型安全的。

          輕松布局

          一般來說,網站顯示的數據來自其他源頭:無論是數據庫、API還是其他來源,我們都希望數據能夠按照預期顯示出來。想象一下,我們有一組從API返回的對象,而你使用了Angular的對象來顯示它們。通常,你需要將這些對象加載到支持組件中,然后使用*ngFor迭代所有對象。你需要添加div。但是,這些沒有樣式的div看起來會過于蒼白。如果你希望列表中的各項顯示在列或行中,則必須使用CSS或flexbox來實現。

          而在Flutter中,你可以使用Column或Row來布局這些數據,Column或Row的children屬性可以接受對象數組。仔細想一想,在大多數情況下,你可能會希望對象列顯示成一排或一列。在Flutter的幫助下,你可以快速完成視覺上的布局,然后再為列表中的各項設置樣式。根據我的經驗,你可以更快地完成腳手架和原型制作,同時不影響最終結果。

          控制窗口中的每個像素

          由于Flutter會將每個像素渲染到屏幕上,因此設計人員和開發人員可以完整地控制自己想要的應用或體驗。渲染屏幕上的每個像素聽起來會造成巨大的性能損失,但請不要誤會我的意思,這種做法當然不如渲染HTML的速度快,但是在GPU的加速下,性能也得到了提升。根據傳統的做法,設計HTML的網頁意味著,你必須考慮不同的瀏覽器。然而,在Flutter中,給Text小部件設置的字體無論在何處顯示,最后的效果都一樣,因為Flutter可以控制每個像素的外觀。

          再見,Webpack!

          由于Flutter使用了Dart,因此在針對目標平臺編譯Flutter應用時,它會把所有相關的軟件包(也是用Dart編寫的)都轉換成JavaScript。Dart是一種類型安全的語言,不支持反射,因此編譯器可以更好地了解應用需要調用什么以及不需要調用什么。這有助于我們進一步將應用的規模降到最小。在Web上構建Flutter應用不需要使用Webpack,因為它不需要Webpack,這是Flutter本身的一大優勢(至少在我看來是優勢)。并不是說Webpack有問題,Webpack是一款高質量的軟件。只不過它是復雜的流水線中的一款復雜的工具。


          但是我們的目標還沒有實現


          Flutter不僅可以提供新潮的網頁,引人入勝的動畫和精美的體驗,而且還可以更進一步。我們需要服務器端渲染(server-side rendering,SSR),以便我們的網頁可以被搜索引擎抓取,然后執行搜索引擎優化(SEO)。目前Flutter網站只面向人類用戶,不能被搜索引擎解讀,因此會對網站搜索和查找信息的方式產生巨大影響。(人們正在就此問題進行討論,近期內還沒有解決方案)。

          此外,將所有內容繪制到畫布上確實對性能有影響,但沒有那么糟糕。我構建了一個測試應用,使用了大量視覺效果,在MacBook上能夠以接近60fps的速度運行。在沒有經過任何優化的情況下,即使拖動屏幕,也仍然可以正常工作,在性能不足時會逐步降低背后的圖像的清晰度。

          在被視為Web開發的主流技術之前,Flutter還需要改進幾個關鍵領域。話雖如此,畢竟Flutter誕生才兩年,其性能和功能集已經達到了令人驚嘆的水平。

          如果可以創建一個性能卓越的網站,而且只需一種語言就可以設計、樣式化和編寫完成Web應用的業務邏輯,你感覺怎樣?如果開發流水線無需再使用Webpack呢?如果你能及時獲得服務器端渲染,而且基于HTML的傳統網站所擁有的SEO優勢也統統沒落下呢?你會動心嗎?

          如果所有這些都成為現實,那么Flutter就會贏得整個Web。

          原文鏈接:https://betterprogramming.pub/flutter-is-about-to-win-over-the-web-be0a205af03d

          聲明:本文由CSDN翻譯,轉載請說明來源。


          主站蜘蛛池模板: 在线视频一区二区三区| 国产手机精品一区二区| 相泽南亚洲一区二区在线播放| 精品一区二区三区高清免费观看 | 无码av中文一区二区三区桃花岛 | 亚洲国产一区在线| 国产精品一区二区久久不卡| 国产一区二区三区免费观看在线| 一区二区精品久久| 无码毛片视频一区二区本码| 无码人妻品一区二区三区精99| 日韩精品无码一区二区三区不卡| 亚洲综合一区二区精品导航| 乱子伦一区二区三区| 性色AV一区二区三区天美传媒| 在线欧美精品一区二区三区| 精品国产一区二区三区久久影院 | 精品国产一区二区三区免费| 久久久精品一区二区三区| 亚洲一区二区三区深夜天堂| 在线观看精品一区| 国产激情з∠视频一区二区| 97精品一区二区视频在线观看| 免费一区二区视频| 亚洲综合色一区二区三区小说 | 久久se精品动漫一区二区三区| 国产日韩精品视频一区二区三区| 影院无码人妻精品一区二区| 91一区二区在线观看精品| 精品一区二区三区免费视频| 精品国产伦一区二区三区在线观看| 无码精品久久一区二区三区| 亚洲无圣光一区二区| 日本高清不卡一区| 日韩一区二区免费视频| 亚洲视频一区二区在线观看| 国产vr一区二区在线观看| 成人区人妻精品一区二区不卡| 国产福利视频一区二区| 春暖花开亚洲性无区一区二区| 无码人妻精品一区二区三区蜜桃 |