天天日夜夜添_精品国产99久久久久久人裸体 _成人app在线观看_日韩色网站

新聞資訊

    作者 / Mariam Hasnany, Product Manager, Flutter


    我們對 Flutter 的愿景是成為一個可移植的 UI 框架,在全平臺上構建精美的應用體驗。做為Flutter 2 發布內容的一部分,Flutter 的 web 支持已經抵達穩定版里程碑。


    Flutter 的首個版本支持 iOS 和 Android,開發者們已經用它在移動應用商店發布了超過 15 萬個應用。現在,隨著 web 支持的加入,這些應用可以觸達更廣泛的受眾,同時也開辟了在 web 上建立交互體驗的新途徑。


    在此次初始版本的 web 支持中,我們主要關注三個應用場景:

    • 漸進式 web 應用 (Progressive web apps, PWA),兼具 web 的高覆蓋面與桌面應用的強大功能。
    • 單頁應用 (Single page apps, SPA),只需一次加載,并與互聯網服務動態互傳數據。
    • 將現有 Flutter 移動應用拓展到 web,在兩個平臺共享代碼。


    這篇文章介紹了我們迄今為止的工作成果,并分享了幾個案例,意在幫助開發者在自己的應用中活用 Flutter 對 web 的支持。

    △ iRobot Education 使用 Flutter 開發了 iRobot Coding 應用,通過此 web 應用向大眾提供編程學習體驗

    • iRobot Educationhttps://edu.irobot.com/the-latest/building-a-coding-experience-for-all
    • iRobot Coding 應用https://code.irobot.com/


    Web 之旅


    如今的 web 平臺比以往任何時候都要豐富多彩,開發者可以使用的工具包括: 硬件加速的 2D 和 3D 圖形離線功能和安裝體驗,以及對底層操作系統和硬件的訪問等。在 web 這個底層平臺上已經建立起了種類繁多的框架,因此,開發者在創建 web 應用時擁有極大的靈活性。


    • WebGL: 用于 web 的 2D 和 3D 圖形https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API
    • PWAhttps://web.dev/progressive-web-apps/
    • 對底層操作系統和硬件的訪問https://web.dev/fugu-status/
    • 種類繁多的框架https://vuejs.org/https://angular.io/https://flask.palletsprojects.com/https://reactjs.org/


    Flutter 是用 Dart 編寫的,而 Dart 能編譯成 JavaScript,所以我們的下一步自然就是要探討支持 web 平臺的可能性。這符合我們的愿景,也就是提供一個可移植的框架,方便您在任何能描繪像素的地方構建出精美的 UI。


    • Darthttps://dart.cn/

    我們的方法是,建立一個在所有平臺上都能使用的一致的工具包 (而不是建立兩個有著各種微妙差異的獨立框架),以確保開發者的代碼運行時不會出現意外。

    Flutter 框架由一系列層結構組成,其中包含:

    • 框架,用于為 widget、動畫和手勢等常見的習慣用法提供抽象
    • 引擎,使用公開的系統 API 在目標設備上進行渲染


    • 技術概覽: 層結構https://flutter.cn/docs/resources/technical-overview#layer-cakes-are-delicious


    框架本身采用 Dart 編寫,大約 70 萬行 Flutter 框架核心代碼在所有平臺上相同: 包括移動端、桌面端和現在的 web 端。對于您的代碼來說也是這樣,我們使用 Dart 開發編譯器 (dartdevc) 或 Dart 部署編譯器 (dart2js) 將您的代碼編譯成 JavaScript,這些 JavaScript 代碼可以托管在服務器上。


    • dartdevc 命令https://dart.cn/tools/dartdevc
    • dart2js 命令https://dart.cn/tools/dart2js


    由于 Dart 擁有將 Flutter 框架 (以及開發者的應用代碼) 編譯成 JavaScript 的能力,我們對 web 的支持工作就變成了用映射 web 平臺 API 的代碼來取代移動應用所使用的底層 C++ 渲染引擎。Flutter 并不會簡單地將 widget 移植為 HTML 里的等價組件,Flutter 的 web 引擎為開發者提供了兩種渲染器: 一個是針對尺寸和兼容性進行優化的 HTML 渲染器,另一個則是使用 WebAssembly 和 WebGL 通過 Skia 繪圖命令向瀏覽器畫布進行渲染的 CanvasKit 渲染器。


    我們對 Flutter 的要求是,提供一種針對 web 平臺進行開發的新方式,在現有基礎上提供新見解,為所有人提供更棒的 web 體驗。


    發布生產環境可用的穩定版本


    自從 web 支持的測試版在一年前發布以來,我們已經了解了很多早期采用者的使用情況,并已與部分客戶合作,他們現在已經將自己的 Flutter web 應用投入生產。


    在此期間,我們對架構進行了重大改進,增加了一些功能,以便擴展和優化 Flutter 的 web 支持,新增內容主要集中在四個方面: 性能web 專屬功能桌面硬件適配,以及插件


    性能

    自推出早期版本至今,性能是提升最顯著的。在開發過程中,我們對 web 上各種渲染技術的性能和準確性特征有了更深入的了解。


    我們最早的工作是基于 DOM 的 HTML。在這種渲染模式中,Flutter 的 web 引擎會將每個生成的 Flutter 場景轉換為 HTML、CSS 或 Canvas,并以 HTML 元素樹的形式在頁面上渲染為一幀。雖然 HTML 渲染器能夠最大限度地兼容各種瀏覽器,且其代碼體積較小,但 HTML 渲染器的重繪性能不太適合 Rive (使用 Flutter 構建而成,用于創建動態圖像的協作工具) 這種圖形密集型應用。

    △ Rive 是一款創建自定義動畫的工具,該團隊已使用 web 版 Flutter 重新構建應用,并發布了測試版


    • Rivehttps://rive.app/

    為了提供高效渲染密集圖形所需的保真度,我們開始嘗試使用 CanvasKit,它可使用WebAssemblyWebGL 通過 Skia 繪制命令在瀏覽器中進行渲染。我們發現 CanvasKit 渲染器的性能、保真度和準確度都更加理想,請看 Flutter 社區中才華橫溢的德國開發者 Felix BlaschkeFlutter Plasma 演示——用 CanvasKit 創造的驚艷特效。

    △ Flutter Plasma 是由 Felix Blaschke 創建的演示,可在 Safari、Firefox、Edge 和 Chrome 上運行


    • CanvasKithttps://skia.org/user/modules/canvaskit
    • WebAssemblyhttps://webassembly.org/
    • WebGLhttps://www.khronos.org/webgl/
    • Felix Blaschkehttps://github.com/felixblaschke
    • Flutter Plasmahttps://flutterplasma.dev/


    不同的渲染器在不同場景下各有優勢,因此 Flutter 同時支持以下兩種渲染模式:

    • HTML 渲染器: 結合了 HTML 元素、CSS、Canvas 和 SVG。該渲染模式的下載文件體積較小。
    • CanvasKit 渲染器: 渲染效果與 Flutter 移動和桌面端完全一致,性能更好,widget 密度更高,但增加了約 2MB 的下載文件體積。


    為了針對每個設備的特性優化您的 Flutter web 應用,渲染模式默認設置為自動。這意味著您的應用將在移動瀏覽器上使用 HTML 渲染器運行,在桌面瀏覽器上使用 CanvasKit 渲染器運行。


    您還可以使用 --web-renderer html--web-renderer canvaskit 來明確選擇使用何種渲染器。如需了解詳細信息,請參閱官方文檔


    • 官方文檔: Web 渲染器https://flutter.cn/docs/development/tools/web-renderers


    Web 專屬功能

    在瀏覽器中運行的 Flutter 應用給人的感覺應該像 web 應用一樣。所以我們為 Flutter 添加了一些功能,幫助您發揮 web 的優勢。


    Web 有很多優勢,尤其是在全球的覆蓋率。將您現有的 Flutter 應用帶到 web 上的原因之一就是接觸應用商店以外的用戶。為了做到這一點,我們添加了自定義 URL 策略,以確保您的用戶只需點擊 URL,就可以從任何地方訪問您的應用。有了這個功能,您就可以控制地址欄中顯示的 URL,以及您的應用在 web 上的路由。


    • 在 web 上自定義 URLhttps://flutter.cn/docs/development/ui/navigation/url-strategies

    △ Flutter Plasma 演示的Showroom頁面,實際上就是一個基于Flutter自定義 URL 策略的url_strategy插件示例


    • url_stategyhttps://pub.flutter-io.cn/packages/url_strategy


    當用戶在 web 上導航時,超鏈接也至關重要。url_launcher package 中的一個新的 link widget 使用戶能夠通過深鏈接直達您應用內的錨點或外部網站。您可以在相關的 widget 上使用 link,包括按鈕、內聯文本、圖像,并指定鏈接是在同一個標簽頁還是新標簽頁中打開。


    • Linkhttps://pub.flutter-io.cn/documentation/url_launcher/latest/link/Link-class.html


    對于任何應用來說,文本渲染都是不可或缺的。開發文本布局系統,是構建 Flutter web 支持所面臨的重大挑戰之一。由于 web 缺乏直接文本布局 API,Flutter 必須通過觸發 layout() 來對Parapraph 執行各種測量操作。有時,這些測量的代價相當高昂,所以我們添加了基于 Canvas 的文本測量,此測量方式可同時支持純文本與富文本。現在,Flutter 可以在 web 上高效地完成精細測量,進而完成正確的繪制任務,比如正確地高亮顯示所選文本。


    • layout()https://api.flutter.cn/flutter/dart-ui/Paragraph/layout.html
    • Paragraphhttps://api.flutter.cn/flutter/dart-ui/Paragraph-class.html
    • 基于 Canvas 的文本測量https://github.com/flutter/flutter/issues/33523


    與文本進行交互同樣重要,其重要性不亞于快速準確地渲染文本。通過 SelectableTextEditableText widget,您不僅可以選中 Flutter web 應用中的文本,還可以執行復制粘貼操作。此外,表單文本字段現已支持自動填充,瀏覽器能夠存儲數據以便將來填充使用。


    • 自動填充 AutofillGrouphttps://api.flutter.cn/flutter/widgets/AutofillGroup-class.html


    Flutter 2 特別適合實現漸進式 web 應用 (PWA)。我們建議開發者使用 PWA,通過 Chrome 的 Project Fugu,以安全和可信的方式,彌合移動端和 web 端應用之間的差異。


    • Project Fuguhttps://web.dev/fugu-status/

    △ 發票管理應用 Invoice Ninja 推出的 PWA 應用與他們現有的 Flutter 移動應用使用相同的代碼庫

    • Invoice Ninjahttps://www.invoiceninja.com/


    在創建 Flutter Web 應用時,我們會提供 PWA web 清單文件,以及用來設置 service worker (工作線程) 的代碼。清單文件提供了關于應用應該如何運行的元數據,包括圖標和應用標題等信息。Service workers 可以實現資源的緩存和應用的離線運行。當您在瀏覽器中以 PWA 的形式運行 Flutter 應用時,您可以將其作為移動或桌面應用安裝到您的設備上。


    • 清單文件https://developer.mozilla.org/en-US/docs/Web/Manifest
    • Service workershttps://developers.google.cn/web/ilt/pwa/introduction-to-service-worker


    適配各類桌面設備

    盡管瀏覽器的形態大小各異,我們都希望提供美好的 Flutter web 體驗。由于 Flutter 最初是為移動應用設計而成,因此 Flutter web 應用已經對移動瀏覽器的手勢和滾動物理效果提供了很好的支持。但桌面瀏覽器 UI 的呈現和使用有所不同,所以我們對 Flutter 進行了相應的更新。


    比如,用戶希望應用在桌面瀏覽器中運行時能夠顯示滾動條,以便通過鼠標或鍵盤進行控制。我們為桌面設備添加了可自定義的交互式滾動條,這意味著我們可為滾動條使用主題,顯示滾動條軌道,而且還可以拖動滑塊。我們還擴展了 PrimaryScrollController,便于用戶使用鍵盤快捷鍵進行滾動,也省去了您使用自定義滾動視圖的工作。


    • 滾動條更新https://files.flutter-io.cn/sources/flutter-design-docs/Updating_Scrollbars_(PUBLICLY_SHARED).docx
    • 主題https://api.flutter.cn/flutter/material/ScrollbarTheme-class.html
    • PrimaryScrollControllerhttps://api.flutter.cn/flutter/widgets/PrimaryScrollController-class.html
    • 滾動方式https://files.flutter-io.cn/sources/flutter-design-docs/Fallback_ScrollAction_(PUBLICLY_SHARED).docx

    △ Spica Technologies 為 Zurich Insurance 構建的物業管理解決方案,這是用 Flutter web 為商務和桌面設備用戶構建應用的杰出示例

    • Spica Technologieshttps://spicatech.co.uk/
    • Zurich Insurancehttps://www.zurich.com/


    此外,由于鼠標指針能進行互動的內容密度大于觸摸設備,我們提升了默認內容密度。我們還在框架中添加了支持各種平臺的系統鼠標光標合集。


    • 默認內容密度https://github.com/flutter/flutter/issues/43350
    • 系統鼠標光標https://github.com/flutter/flutter/issues/60641


    最后,為讓 Flutter web 支持所有用戶,我們還擴展了 Flutter 的 web 語義功能來支持 Windows、macOS 和 chromeOS 系統上的無障礙功能。為了在 web 上實現無障礙體驗,我們在 RenderObject DOM 樹之外平行生成了一個類似的 DOM 樹,叫 SemanticsNode樹。SemanticsNode 樹可將標記、操作、標簽和其他語義屬性轉換成 ARIA 屬性。現在,您可以通過 NarratorVoiceOverTalkBackChromeVox 屏幕閱讀器來使用 Flutter web 應用。


    • RenderObjecthttps://api.flutter.dev/flutter/rendering/RenderObject-class.html
    • SemanticNodehttps://api.flutter.dev/flutter/semantics/SemanticsNode-class.html
    • ARIA 屬性https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA
    • Narratorhttps://support.microsoft.com/en-us/windows/complete-guide-to-narrator-e4397a0d-ef4f-b386-d8ae-c172f109bdb1
    • VoiceOverhttps://www.apple.com/accessibility/vision/
    • TalkBackhttps://support.google.com/accessibility/android/answer/6007100?hl=en
    • ChromeVoxhttps://support.google.com/chromebook/answer/7031755?hl=en#:~:text=You%20can%20turn%20ChromeVox%20on,then%20ChromeVox%20will%20start%20speaking.


    Flutter web 對插件的支持

    最后,我們為那些最常用的插件帶來了 web 支持,使您能夠將自己的 Flutter 應用帶到 web 平臺。借助 Flutter 插件,您的代碼可與所運行平臺的原生開發庫進行互操作。在 web 上運行 Flutter 應用時,您可以通過插件訪問現有的 JavaScript 庫。


    • Flutter 插件https://pub.flutter-io.cn/


    自測試版發布以來,我們在社區的幫助下為以下插件添加了 web 支持:

    • image_pickerhttps://pub.flutter-io.cn/packages/image_picker_for_web
    • google_mapshttps://pub.flutter-io.cn/packages/google_maps
    • firebase_analyticshttps://pub.flutter-io.cn/packages/firebase_analytics
    • firebase_storagehttps://pub.flutter-io.cn/packages/firebase_storage
    • connectivityhttps://pub.flutter-io.cn/packages/experimental_connectivity_web
    • cloud_firestorehttps://pub.flutter-io.cn/packages/cloud_firestore
    • cloud_functionshttps://pub.flutter-io.cn/packages/cloud_functions
    • cross_filehttps://pub.flutter-io.cn/packages/cross_file


    展望未來


    幾年前,我們還沒辦法在 web 上以可接受的質量和性能提供 Flutter。然而,web 新技術的出現和平臺的不斷進步,使我們得以盡情釋放底層設備的潛力。在支持 web 之后,Flutter 得以涵蓋互聯網上的每一臺設備,讓用戶在所有現代瀏覽器和設備上都能獲得一致的體驗。


    這個版本的相當一部分內容來自早期 web 用戶的反饋信息和社區提交的 issue,這里我們要再次感謝大家的貢獻!今后,我們的首要目標是快速處理大家的反饋,并及時解決 issue,以便大家專注于在所有目標平臺上發布高質量的 Flutter 應用。

    △ Moi Mobiili 是一家現代移動虛擬網絡運營商,最近使用 Flutter 推出了他們的 web 應用


    • Moi Mobiilihttps://www.moi.fi/


    性能的提升永無止境。我們的目標是減少代碼體積,提高幀率表現 (fps)。如今,每個 Flutter web 應用都只會下載它必需的引擎代碼。我們正在研究緩存部分邏輯的可能性,以減少啟動時間和下載文件體積。我們最近在 Flutter Gallery 演示應用中嘗試使用延遲庫來減少代碼體積,相信很快就能同大家分享我們的進展。


    在未來幾個月內,我們還準備繼續完善下列領域:

    • 雖然 CanvasKit 很穩定,但還有一些邊界用例存在問題,比如特殊字符的字體回退,以及對跨域資源共享 (CORS) 圖像的相應支持等。
    • PWA 目前只緩存了資源的一個子集,完全的離線支持仍然需要額外的手動步驟,才能正常適配 CanvasKit。
    • 文本渲染和功能,比如對樣式設置較為復雜的文本的選取,仍是我們要繼續努力解決的功能之一。
    • 我們也會繼續努力改善插件生態系統,讓 Google 發布的 package 在移動端和 web 端更加統一。


    • 字體回退https://github.com/flutter/flutter/issues/74741
    • 跨域資源共享 (CORS)https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
    • 緩存資源https://github.com/flutter/flutter/issues/75861
    • 額外的步驟https://github.com/flutter/flutter/issues/70101

    △ Simplebet 通過 Flutter 的 web 支持,在 Fanduel 現有的移動應用套件中構建了高度互動的嵌入式 NFL 和 NBA 投注體驗

    • Simplebethttps://simplebet.io/


    即刻開始使用 Flutter web


    借助 Dart 的可移植性、Web 平臺的強大功能,以及 Flutter 框架的靈活性,您現在可以用同一套代碼庫,構建用于 iOS、Android 以及瀏覽器的應用。


    如果您已經開發了 Flutter web 應用,現在就可以在穩定渠道中進行構建。如果您剛開始學習構建 Flutter web 應用,請移步官方文檔訪問我們的入門 codelab 課程,以及 Flutter Engage 上的web 演講。構建 web 應用時,如果您發現了任何問題,請隨時前往 GitHub 提交給我們


    • 穩定渠道https://github.com/flutter/flutter/wiki/Flutter-build-release-channels#stable
    • 編寫您的第一個 Flutter web 應用https://flutter.cn/docs/get-started/codelab-web
    • web 演講https://www.bilibili.com/video/BV1Jv411h7x6
    • 提交 issuehttps://goo.gle/flutter_web_issue


    我們非常期待看到您使用 Flutter web 所構建的精彩應用!


    轉載自:谷歌開發者原創文章

    Flutter Web 作為 Flutter 框架中最特殊的平臺,由于 Web 平臺的特殊性,它默認就具備了兩種不同的渲染引擎:

    • html : 通過平臺的 canvas 和 Element 完成布局繪制;
    • canvaskit : 通過 Webassembly + Skia 繪制控件;

    雖然都知道 canvavskit 更接近 Flutter 的設計理念,但是由于它構建的 wasm 文件大小和字體加載等問題帶來的成本考慮,業界一般會選用更輕量化的 html 引擎,而今天的問題也是基于 html 引擎來展開。

    一、deferred-components

    我們都知道 Flutter Web 打包構建后的 main.dart.js 文件會很大,所以**一般都會采用一些方法來對包大小進行優化,而其中最常用的方式之一就是使用 deferred-components **。

    對于 deferred-components 官方起初主要是用于支持 Android App Bundle 上的動態發布,而經過適配后這項能力被很好地拓展到了 Web 上,通過 deferred-components 可以方便地根據需求來拆分 main.dart.js 文件的大小。

    當然這里并不是介紹如何使用 deferred-components ,而是在使用 deferred-components 時,遇到了一個關于 Flutter Web 在打包構建上的神奇問題

    首先,代碼如下圖所示,可以看到,這里主要是通過 deferred as 關鍵字將一個普通頁面變成 deferred-components ,然后在路由打開時通過 libraryFuture 加載后渲染頁面

    這里省略了無關的 yaml 文件代碼,那么上述簡略的代碼,大家覺得有沒有什么問題

    一開始我也覺得沒什么問題, 通過 flutter run -d chrome --web-renderer html 運行到瀏覽器調試也沒問題,頁面都可以正常加載打開,但是當我通過 flutter build web --release --web-renderer html 打包部署到服務器后,打開時卻遇到了這個問題

    Deferred library scroll_listener_demo_page was not loaded.
    main.dart.js:16911     at Object.d (http://localhost:64553/main.dart.js:3532:3)
    main.dart.js:16911     at Object.aL (http://localhost:64553/main.dart.js:3690:34)
    main.dart.js:16911     at asV.$1 (http://localhost:64553/main.dart.js:54352:3)
    main.dart.js:16911     at pB.BE (http://localhost:64553/main.dart.js:36580:23)
    main.dart.js:16911     at akx.$1 (http://localhost:64553/main.dart.js:51891:10)
    main.dart.js:16911     at eT.t (http://localhost:64553/main.dart.js:47281:22)
    main.dart.js:16911     at Cw.bp (http://localhost:64553/main.dart.js:48714:51)
    main.dart.js:16911     at Cw.ih (http://localhost:64553/main.dart.js:48691:9)
    main.dart.js:16911     at Cw.rz (http://localhost:64553/main.dart.js:48659:6)
    main.dart.js:16911     at Cw.zk (http://localhost:64553/main.dart.js:48689:11)
    復制代碼

    這就很奇怪了,明明 debug 運行時沒有問題,為什么 release 發布就會 not loaded 了?

    經過簡單調試和打印發現,在出錯時代碼時根本進入不到 ContainerAsyncRouterPage 這個容器里,也就是在外部就出現了 not loaded異常,但是明明 widget 是在 ContainerAsyncRouterPage 容器內才調用,為什么會在外部就拋出 not loaded 的異常?

    通過異常信息比對源碼發現,編譯時在對于 deferred as 進行處理時,會插入一段 checkDeferredIsLoaded 的檢查邏輯,所以拋出異常的代碼是在編譯期時處理 import * deferred as 時添加

    通過查看打包后的文件,可以看到如果在 checkDeferredIsLoaded 之前沒有完成加載,也就是對應 importPrefix 沒有被添加到 set 里,就會拋出異常。

    所以初步推斷,問題應該是出現在 debug 和 release 時,對于 import * deferred as 的編譯處理有不同之處。

    二、構建區別

    通過資料可以發現,Flutter Web 在不同編譯期間會使用 dartdevcdart2js 兩個不同的編譯器,而如下圖所示,默認 debug 運行到 chrome 時采用的是 dartdevc ,因為 dartdevc 支持增量編譯,所以可以很方便用 hot reload 來調試,通過這種方式運行的 Flutter Web 并不會在 build 目錄下生成 web 目錄,而是會在 build 目錄下生成一個臨時的 *.cache.dill.track.dill 用于加載和更新。

    .dill 屬于 Flutter 編譯過程的中間文件,該文件一般是二進制的編碼,如果想要查看它的內容,可以在完整版 dart-sdk/Users/xxxxx/workspace/dart-sdk/pkg/vm/bin 目錄下)執行 dart dump_kernel.dart xxx.dill output.dill.txt 查看,注意是完整版 dart-sdk 。

    而 Flutter Web 在 release 編譯時,如下圖所示,會經過 flutter_toolsweb.dart 內的對應配置邏輯進行打包,使用的是 dart2js 的命令,打包后會在 build 下生成包含 main.dart.js 等產物的 web目錄,而打包過程中的產物,例如 app.dill 則是存在 .dart_tool/flutter_build/一串特別編碼/ 目錄下。

    .dart_tool/flutter_build/ 目錄下根據編譯平臺會輸出不同的編譯過程目錄,點開可以看到是帶 armeabi-v7a 之類的一般是 Android 、帶有 *.framework 的一般是 iOS ,帶有 main.dart.js 的一般是 Web 。

    而打開 web.dart 文件可以看到很多可配置參數,其中關鍵的比如:

    • --no-source-maps : 是否需要生成 source-maps ;
    • -O4 :代表著優化等級,默認就是 -O4,dart2js 支持 O0-O4,其中 0 表示不做任何優化,4 表示優化開到最大;
    • --no-minify : 表示是否混淆壓縮 js 代碼,默認 build web --profile 就可以關閉混淆;

    所以到這里,我初步懷疑是不是優化等級 -O4 帶來的問題,但是正常情況下,Flutter 打包時的 flutter_tools 并不是使用源碼路徑,而是使用以下兩個文件:

    /Users/xxxx/workspace/flutter/bin/cache/flutter_tools.stamp

    /Users/xxxx/workspace/flutter/bin/cache/flutter_tools.snapshot

    難道就為了改個參數就去編譯整個 engine ?這樣肯定是不值得的,所幸的是官方提供了使用源碼 flutter_tools 編譯的方式,同樣是在項目目錄下,通過一下方式就可以用 flutter_tools 源碼的形式進行編譯:

    dart ~/workspace/flutter/packages/flutter_tools/bin/flutter_tools.dart build web --release --web-renderer html

    而在源碼里直接將 -O4 調整了 -O0 之后,我發現編譯后的 web 居然無法正常運行,但是基于編譯后的產物,我可以直接比對它們的差異,如下圖所示,左邊是 O0,右邊是O4:

    -O0 之后為什么會無法運行有誰知道嗎?

    首先可以看到, O4 確實做了不少優化從而精簡了它們的體積,但是在關鍵的 loadDeferredLibrary 部分基本一樣,所以問題并不是出現在這里。

    但是到這里可以發現另外一個問題,因為 loadDeferredLibrary 方法是異步的,而從編譯后的 js 代碼上看,在執行完 loadDeferredLibrary 之后馬上就進入到了 checkDeferredIsLoaded ,這顯然存在問題。

    那為什么 debug 可以正常執行呢? 通過查看 debug 運行時的 js 代碼,我發現同樣的執行邏輯,在 dartdevc 構建出來后居然完全不一樣。

    可以看到 checkDeferredIsLoaded 函數和對應的 Widget 是被一起放在逗號表達式里,所以從執行時序上會是和 Widget 在調用時被一起被執行,也就是在 loadDeferredLibrary 之后,所以代碼可以正常運行。

    通過斷點調試也驗證了這個時序問題,在 debug 下會先走完 loadDeferredLibrary 的全部邏輯,之后再進入 checkDeferredIsLoaded

    而在 release 模式下,代碼雖然也會先進入 loadDeferredLibrary , 但是會在 checkDeferredIsLoaded 執行之后才進入到 add(0.this.loadId) ,從而導致前面的異常被拋出。

    那到這里問題基本就很清楚了,前面的代碼寫法在當前(2.10.3)的 Flutter Web 上,經過 dart2js 的 release 編譯后會出現某些時序不一致的問題,知道了問題也很好解決,如下代碼所示,只需要把原先代碼里的 Widget 變成 WidgetBuilder 就可以了。

    我們再去看 release 編譯后的 js 文件,可以看到此時的因為多了 WidgetBuilder ,傳入的內容變成了 closure69 ,這樣就可以保證在調用到 call 之后才觸發 checkDeferredIsLoaded

    三、最后

    雖然這個問題不難解決,但是通過這個問題去了解 dart2js 的編譯和構建過程,可以看到很多平時不會接觸的內容

    最后

    如果你覺得此文對你有一丁點幫助,點個贊。或者可以加入我的開發交流群:1025263163相互學習,我們會有專業的技術答疑解惑

    如果你覺得這篇文章對你有點用的話,麻煩請給我們的開源項目點點star:http://github.crmeb.net/u/defu不勝感激 !

    完整源碼下載地址:https://market.cloud.tencent.com/products/33276

    PHP學習手冊:https://doc.crmeb.com
    技術交流論壇:https://q.crmeb.com

網站首頁   |    關于我們   |    公司新聞   |    產品方案   |    用戶案例   |    售后服務   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權所有