
Мы рады объявить о выходе Dart 3.13!
В этом релизе мы отмечаем тему, которую любят все разработчики: чистый и легковесный код. Dart 3.13 фокусируется на этом аспекте на каждом уровне работы разработчика. Что касается языка, то первичные конструкторы устраняют повторяющийся шаблонный код, позволяя определять классы в одной строке кода. В инструментах разработчика внесены улучшения, позволяющие dart formatподдерживать аккуратность кода в соответствии с правилами стиля Effective Dart , а также dart pubвведены новые команды рабочей области для поддержания порядка в монорепозиториях. На pub.dev расширенные функции документации, такие как <callout-box>теги и {@example}директивы, делают документацию пакетов более понятной. Внутри системы, оптимизация кода нативных библиотек (tree-shaking @RecordUse) и отложенная загрузка WebAssembly помогают сделать скомпилированные бинарные файлы приложений максимально компактными.
Так что обновите Dart или запустите программу flutter upgrade и следите за обновлениями, пока мы будем изучать новинки Dart 3.13!
Обновления языка
Основные конструкторы
После экспериментальной предварительной версии в Dart 3.12, основные конструкторы теперь официально стабильны в Dart 3.13!
Первичные конструкторы представляют собой значительный шаг вперед в плане лаконичности классов. Мы слышали от разработчиков, что повторение имен полей и типов в телах классов и списках параметров может показаться утомительным. Первичные конструкторы устраняют это повторение, позволяя, например, определить класс Pointс двумя полями и конструктором в одной строке кода:
class Point(final int x, final int y);
Эта функция также включает в себя лаконичный синтаксис для конструкторов, использующих ключевые слова new or factory, позволяющий пустым телам объявлений заканчиваться символом . ;.
Чтобы помочь вам внедрить основные конструкторы и поддерживать единообразный стиль во всем коде, мы ввели несколько новых проверок кода с автоматическим исправлением ошибок:
empty_container_bodiesСпособствует краткости, используя;вместо{}в объявлениях, подобных классам.initialize_in_field_declaration: Способствует большей ясности, перенося инициализацию поля из основного конструктора в объявление поля.unnecessary_const_in_enum_constructorСпособствует краткости, удаляя этот параметрconstиз конструкторов перечислений.unnecessary_primary_constructor_bodyСпособствует краткости, удаляя ненужные тела основных конструкторов.unnecessary_type_name_in_constructorСпособствует краткости, заменяя имя типаnewв объявлениях конструкторов.use_declaring_parametersСпособствует краткости, используя объявление параметров там, где это возможно.
Помимо этих проверок кода, мы также добавили новые функции рефакторинга IDE для автоматизации миграции кода:
Преобразовать в основной конструктор : Преобразует подходящий конструктор внутри объекта в основной конструктор.
Преобразовать в конструктор внутри тела кода : Преобразует основной конструктор в конструктор внутри тела кода.
Преобразовать в объявляемый параметр : Преобразует необъявляемый параметр в основном конструкторе в объявляемый параметр.
Переместить инициализацию в объявление поля : Перемещает инициализацию поля из списка инициализаторов конструктора в объявление поля.
Подробнее: Документация по основным конструкторам
Обновления веб-платформы
Предварительный просмотр отложенной загрузки WebAssembly
Мы усердно работали над расширением возможностей WebAssembly для Dart в веб-разработке. В Dart 3.13 мы рады представить предварительную версию поддержки отложенной загрузки при компиляции с использованием WebAssembly dart2wasm. Вы можете включить её уже сегодня, используя экспериментальный флаг компилятора:
dart compile wasm -O2 --enable-deferred-loading
Примечание
Для отложенной загрузки ваш встраиваемый модуль приложения должен предоставить функцию обратного вызова, отвечающую за загрузку байтов модуля Wasm. Подробности см. CompiledApp.instantiateв документации в сгенерированном файле вашего приложения <app>.mjs.
В крупных приложениях, использующих отложенную загрузку, dart2wasmобеспечивается значительное сокращение времени первоначальной загрузки страницы (IPL) по сравнению с dart2js, что выгодно как для веб-приложений Flutter, так и для веб-приложений на основе DOM.
Напоминаем, что устаревшие веб-библиотеки, такие как <b> dart:html и <b>, package:js не поддерживаются в dart2wasmDart 3.7 и были объявлены устаревшими в Dart 3.7 (и перестанут работать dart2jsв будущем). Многие пакеты уже перенесены, поэтому обновление зависимостей пакетов часто автоматически решает проблемы. Однако, если ваш код напрямую использует эти устаревшие библиотеки, ознакомьтесь с нашими руководствами по миграции, чтобы уже сегодня перейти на поддерживаемые библиотеки <b> dart:js_interop и package:web <b>.
Подробнее: документация WebAssembly
Обновления основного движка и среды выполнения
Основные инженерные решения
Наряду с развитием нашей веб-платформы, наша команда постоянно совершенствует основу языка Dart. Вот несколько основных моментов из того, над чем мы работали за кулисами в течение последних трех месяцев:
Исправлена ошибка корректности преобразования типов : Исправлена редкая ошибка корректности преобразования типов, связанная с вложенными функциями.
Общая рефакторизация фронтенда : Внутренние общие компоненты фронтенда были переработаны для обеспечения более эффективного взаимодействия кода с анализатором Dart.
Унификация модульной системы DDC : Продолжение удаления устаревших модульных систем из компилятора разработки Dart (DDC) во всех инструментах для создания единой, унифицированной модульной системы.
Безопасность памяти во время выполнения : Повышена безопасность памяти во время выполнения за счет введения «корзины памяти» вокруг кучи Dart.
Динамическая модульная компоновка : начаты эксперименты с динамическими модулями для обеспечения динамической компоновки кода, что открывает путь к улучшению рабочих процессов разработки, таких как быстрая передача прототипов внутри команды.
Обновления инструментов
Форматировщик Dart
Поддержание чистоты и читаемости кодовой базы является для нас первостепенной задачей dart format. В Dart 3.13 мы внесли ряд изменений в стиль, чтобы сделать отформатированный код еще чище. Хотя большинство изменений незначительны, несколько ключевых обновлений заметно упростят чтение вашего повседневного кода:
Исправлена ошибка форматирования при вызове метода : мы исправили ошибку, из-за которой оптимизация иногда ошибочно срабатывала и форматировала код. Чаще всего это происходило при вызовах методов, содержащих большие литералы коллекций:
// Before: await MethodChannelContainer() .onMethodChannelInvoke('reportCrash', <String, Object?>{ 'time': nowTime, 'errorValue': errorName, 'reason': reason, 'stacktrace': stacktrace, }); // After: await MethodChannelContainer().onMethodChannelInvoke( 'reportCrash', <String, Object?>{ 'time': nowTime, 'errorValue': errorName, 'reason': reason, 'stacktrace': stacktrace, }, );Эвристика разделения цепочки методов : Мы изменили эвристику, определяющую, следует ли форматировщику разделять цепочку вызовов методов в самом конце
.или внутри одного из списков аргументов. Если целью цепочки методов является литерал коллекции или вызов функции с одним элементом или аргументом, теперь он предпочитает разделять цепочку вызовов, а не цель:// Before, split the target: function( argument, ).method().another(); // After, split the chain: function(argument) .method() .another();Разделение разделов импорта : Теперь форматтер вставляет пустую строку между различными «разделами» внутри серии импортов. Форматтер не сортирует импорты, но теперь разделяет их в соответствии с правилами, описанными в Effective Dart :
// Before: import 'dart:io'; import 'dart:math'; import 'package:args/args.dart'; import 'package:test/test.dart'; import 'my_library.dart'; // After: import 'dart:io'; import 'dart:math'; import 'package:args/args.dart'; import 'package:test/test.dart'; import 'my_library.dart';
dart_style В списке изменений описаны и другие корректировки стиля , но эти — наиболее заметные. Мы знаем, что изменения форматирования могут вызывать досадные проблемы, поэтому стараемся быть осторожными при изменении стиля. В то же время, улучшение стиля может сделать код более читабельным, что является ценным преимуществом в эпоху, когда мы все проверяем больше кода, чем когда-либо, благодаря генеративному ИИ. Помимо исправления ошибки оптимизации, эти изменения стиля версионируются в зависимости от языка . Вы увидите их только после обновления вашего кода до Dart 3.13.
Подробнее: Документация по форматтеру Dart
Обновления паба
Обновления документации пакета
Четкая и хорошо структурированная документация пакетов необходима для здоровой экосистемы. Чтобы помочь авторам пакетов создавать более чистую и поддерживаемую документацию, pub.dev теперь поддерживает <callout-box>теги и {@example}директивы от начала до конца. Вы можете извлекать фрагменты кода непосредственно из примеров файлов и вносить их в документацию API, скрывая при этом ненужный шаблонный код.
Например, определите область фрагмента текста в example/foo.dart:
// example/foo.dart void main() { // #region abc // Included in documentation foo(); assert(false); // #hide // #endregion }
Затем укажите ссылку на этот регион в комментариях к документации Dart:
/// This is a great function. /// /// Example usage: /// {@example /example/foo.dart#abc} void foo() {}
pub.dev отображает указанный фрагмент кода непосредственно в сгенерированной документации.

<callout-box>с синей рамкой рядом с встроенным {@example}блоком кода.В фоновом режиме pub.dev также внедрил двухуровневый хэш-индекс для поиска файлов dartdoc. Это обновление значительно ускоряет рендеринг документации для больших пакетов, содержащих более 100 000 сгенерированных файлов.

Подробнее: CupertinoActivityIndicatorдокументация класса
Обновления совместимости с нативными системами
Библиотеки с @RecordUse функцией удаления неиспользуемого программного обеспечения (tree-shaking) package: record_use
Наша приверженность эффективности распространяется на все аспекты компиляции ваших приложений. При создании приложений Dart и Flutter, взаимодействующих с нативным кодом C, C++ или Rust с использованием dart:ffiCode Assets, компилятор Dart всегда удалял неиспользуемые функции-обертки Dart, удаляя лишние фрагменты кода. Однако базовые нативные бинарные файлы традиционно оставались полностью включенными в пакет.
Благодаря @RecordUse(в package:meta) и package:record_use, Dart и Flutter теперь могут выполнять оптимизацию кода нативных библиотек вместе с вашим кодом Dart. Это гарантирует, что итоговый пакет вашего приложения будет содержать только тот нативный код, который ваше приложение фактически вызывает.
Как это работает
Аннотируйте собственные привязки FFI с помощью
@RecordUse(): Отметьте ваши собственные привязки FFI (например, сгенерированныеffigen) аннотацией@RecordUse():import 'dart:ffi'; import 'package:meta/meta.dart'; @RecordUse() @Native<Int32 Function(Int32, Int32)>() external int sqlite3_open( Pointer<Utf8> filename, Pointer<Pointer<sqlite3>> ppDb, ); @RecordUse() @Native<Int32 Function(Pointer<sqlite3>)>() external int sqlite3_close(Pointer<sqlite3> db);Отслеживание доступных вызовов во время компиляции : Во время компиляции всей программы и очистки кода (tree-shaking) в сборках Dart AOT компилятор отслеживает, какие привязки, аннотированные с помощью
@RecordUse() tree-shaking, доступны в исполняемом коде. Вызовы, находящиеся в неиспользуемом коде Dart, который очищается в процессе очистки кода, автоматически исключаются.Удалите неиспользуемые нативные символы в вашем хуке компоновки : в хуке компоновки вашего пакета (
hook/link.dart) получитеinput.recordedUses. Используяpackage:record_use, запросите записанные вызовы и дайте указание вашему нативному инструментарию (напримерpackage:native_toolchain_c, или скрипту сборки Rust) сохранять только те символы, которые фактически вызывает Dart:import 'package:hooks/hooks.dart'; import 'package:native_toolchain_c/native_toolchain_c.dart'; import 'package:record_use/record_use.dart'; import 'package:my_package/src/c_library.dart'; import 'package:my_package/src/record_use_mapping.dart'; void main(List<String> arguments) async { await link(arguments, (input, output) async { // Extract symbols for functions called in reachable Dart code: final symbolsToKeep = input.recordedUses?.calls.keys .cast<Method>() .map((method) => recordUseMapping[method.name]!); await cLibrary.link( input: input, output: output, linkerOptions: LinkerOptions.treeshake( symbolsToKeep: symbolsToKeep, ), ); }); }
Почему это важно
Значительно меньший размер исполняемых файлов : Мощные нативные зависимости, такие как SQLite, криптография, декодеры изображений или аудиодвижки, предоставляют доступ к сотням функций. Во время сборки релизной версии компоновщик удаляет неиспользуемый нативный код, неработающие объектные файлы и неиспользуемые экспортируемые функции.
Полное исключение неиспользуемых нативных библиотек : если ваше приложение никогда не вызывает нативные привязки пакета, обработчик компоновки полностью удаляет нативный исполняемый файл из конечного пакета приложения.
Бесшовная интеграция инструментов : такие инструменты, как
ffigenавтоматическое аннотирование сгенерированных привязок,package:native_toolchain_cнапрямую интегрируются с хуками ссылок для сквозного анализа исходного кода нативных приложений.
Подробнее: Документация по встроенным перехватчикам ссылок и документация по использованию записей.
Заключение
Dart 3.13 воплощает в жизнь наше видение более простого и удобного интерфейса для разработчиков. Сочетая выразительные языковые возможности, такие как первичные конструкторы, с более интеллектуальными инструментами, более подробной документацией pub.dev и компактным оптимизацией кода нативных приложений, этот релиз помогает вам сосредоточиться на самом важном: создании отличных приложений.
Все в этом релизе основано на ваших реальных наблюдениях, сообщениях об ошибках и вкладе в создание пакетов. Экосистема Dart процветает благодаря вашему активному участию, и мы глубоко благодарны вам за партнерство в формировании дальнейшего развития языка.
Мы с нетерпением ждём, что вы создадите с Dart 3.13! Найдите минутку, чтобы обновить Dart или запустить его flutter upgrade сегодня, и присоединяйтесь к обсуждению в нашем трекере задач на GitHub . Спасибо вам за то, что вы такое увлечённое сообщество и строите будущее Dart вместе с нами!
Подробнее: Список изменений в Dart SDK

