【文章內容使用 Gemini 1.5 Pro 自動翻譯產生】
大型 Dart 專案的漸進式空安全遷移
對於一個簡單的小套件來說,Dart 空安全遷移 需要 1-2 個小時的工作量,但對於一個大型專案來說,這可能是一場長達數月的馬拉松。理想情況下,您希望逐步遷移您的專案——在馬拉松期間,您希望保持您的專案可擴展、可維護且易於發佈。
我已經將一個大型專案遷移到空安全,並決定整理一些步驟和技巧,以說明如何使遷移過程可靠且高效,希望它能節省您的時間。
步驟 1:轉換為非健全的空安全
首先,將您的專案遷移到非健全的空安全。
首先將您的依賴項升級到空安全版本。非健全的空安全並不要求所有依賴項都是空安全的。但是,強烈建議等到所有上游依賴項都遷移完畢後再進行遷移,因為遷移依賴項可能會迫使您重新審視您自己程式碼中的遷移決策。對於相互依賴的套件,您可能被迫無序遷移,或者同時遷移這些套件(許多相互依賴的套件大多只在測試中相互引用)。請遵循 dart.dev 上的指南 在遷移程式碼之前盡可能升級更多依賴項。
接下來,更新套件的 Dart SDK,並使用以下步驟將每個未遷移的函式庫標記為 legacy:
- 確保您的 IDE(VSCode、IntelliJ / Android Studio)已安裝 Dart 外掛。
- 在 IDE 中打開您的套件,並確保沒有編譯錯誤。
- 更新 pubspec.yaml 檔案中的 dart_sdk 依賴項,以要求版本範圍:
>=2.12.0 <3.0.0
。 - IDE 將突出顯示尚未啟用空安全的函式庫中的空安全相關錯誤。透過在每個受影響檔案的頂部加入註釋
// @dart=2.9
來移除錯誤。即使您的 main.dart 檔案沒有錯誤,也要將註釋加入其中,以保持應用程式以非健全模式運行,直到您準備好切換為止。 - 驗證所有測試是否通過,並將變更提交到您的主分支。如果您的測試已經是空安全的,您將需要命令列標誌
--no-sound-null-safety
來抑制空安全錯誤。
啟動應用程式時,請確保您在控制台中看到「以非健全的空安全模式運行」。
現在您已準備好一次遷移一個函式庫到健全的空安全。
步驟 2:迭代到健全的空安全
選擇一個或一組要遷移的函式庫。
專業提示:如果您選擇的函式庫很大,您可能希望在遷移之前將其分解成較小的函式庫。
使用 dart pub deps
建立專案的依賴圖。最好自下而上地遷移套件;從依賴樹中的葉子開始,然後向上迭代到根。但是,如果您的專案具有依賴循環,這可能是不可能的,而且不遵循此順序也沒關係。
使用 遷移工具 遷移函式庫(或一組函式庫):
- 透過執行
dart migrate --skip-import-check
啟動互動式遷移工具。您可能希望cd
到包含所選函式庫的目錄,以便在樹中更容易導航。 - 透過取消選取左側面板中檔案視圖樹的根來取消選取所有內容。(如有興趣,請投票支持新增 取消選取所有 按鈕。)
- 使用 Control+F 找到您要遷移的檔案。
- 選取檔案,然後點擊 應用遷移。您可以透過兩種方式進行調整:(1) 在應用遷移之前使用註釋來調整工具的選擇,或 (2) 在應用遷移之後使用 IDE 來評估欄位、參數和變數的可空性。
- 在 IDE 中打開套件。修復錯誤,並在檔案中搜尋工具可能不準確的情況(請參見下面的潛在問題列表)。進行更正並使用 lint 警告以互動方式清理上游和下游程式碼。
您將無法修復兩個 lint 錯誤:
import_of_legacy_library_into_null_safe
(在已遷移的函式庫中)avoid_redundant_argument_values
(在 legacy 函式庫中)
現在,使用註釋停用這些錯誤。您將在遷移完成後清理這些錯誤。
需要注意的潛在工具不準確性:
- 加入的類型
dynamic
或num
。您很可能知道應該使用哪種特定類型來代替。 - 在大多數情況下,
bool?
可以透過預設值變為bool
。 - 類型轉換(搜尋
as
)可能意味著該工具沒有加入泛型類型參數。加入之後,lint 會指示轉換已變得不必要,可以移除。 - 在某些情況下,該工具會使泛型參數上的界限可空,而最好將其設為不可空(搜尋
?>
和?,
)。 - 該工具可能會使某些內容可空,而使用
late
或late final
可以更好地表達,或者可以重構以允許在建構函式的初始化列表中進行初始化。(如有興趣,請投票支持新增 lint。) - 使用空斷言運算子
!
而不先檢查空值可能意味著變數或參數實際上應該是非空的。(如有興趣,請投票支持新增 lint。) - 該工具以
collection as Iterable<TheType>
的形式為集合加入轉換。有時,此變更只是使已經隱式的轉換變得明確。但是,在其他情況下,由於泛型引數的可空性不匹配,這些轉換可能會引入 執行時錯誤。如有疑問,請考慮將轉換替換為每個元素的顯式轉換(例如,collection.cast<TheType>()
),或考慮使用 package:collection 中的 whereNotNull 擴展方法。 - 如果變數、欄位或參數是可空的,但可空性僅在測試中使用,則可能應該重構程式碼以移除該標識符的可空性。
(感謝 Kenzie Davisson 幫助我識別出這些情況。)
步驟 3:清理
遷移所有函式庫後,請執行一些最終清理:
- 清理禁用 lint 的註釋。
- 將剩餘的依賴項升級到空安全版本。
- 確保您的應用程式中沒有剩餘的
//@dart = 2.9
註釋。此時,啟動應用程式時,您應該在控制台中看到「以健全的空安全模式運行」。如果您沒有看到此訊息,則可能是您的函式庫尚未遷移(搜尋// @dart = 2.9
),或者依賴項尚未遷移。 - 確保應用程式仍然可以正常運行,並且測試通過。由於健全模式啟用了更強的執行時保證,因此當您啟用健全空安全時,您可能會看到新的執行時錯誤,您需要修復這些錯誤(儘管不太可能)。通常這是將可空集合(例如
List<int?>
)轉換為不可空集合類型(例如List<int>
)的結果。
祝您遷移順利!
大型 Dart 專案的漸進式空安全遷移 最初發佈在 Dart 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。