跪拜 Guibai
← Back to the summary

Flutter 3.47 Decouples Material Design and Switches Desktop to Impeller by Default

Hello everyone, I'm Lao Liu

Flutter 3.47 has been released.

Every time a major version comes out, the most common questions in the comments are: What new features are there? How much performance improvement?

This time, Lao Liu wants to remind you to look at it from a different angle. Several changes in 3.47 are not really new features, but more like a move. Material is moving out, the rendering engine is changing shifts, and the iOS lifecycle is changing rules.

New features determine whether you want to upgrade; a move determines whether you have to upgrade.

Today, Lao Liu will take everyone through the points in Flutter 3.47 that truly affect your work, clarifying which ones must be addressed now and which can wait.


1. Core Highlights at a Glance

Official Flutter 3.47 Blog: https://flutter.dev/blog/whats-new-in-flutter-3-47


1. Material and Cupertino Officially Split

Back in 3.44, Lao Liu mentioned that the official team planned to extract Material and Cupertino from the core SDK. At that time, the code was just frozen; this time, they've really moved out: the material_ui and cupertino_ui independent packages have released version 1.0 on pub.dev.

What's the point of the split?

Previously, design components were bundled within the SDK; changing a button required waiting for a Flutter release. Now, as independent packages:

How to Migrate

The official team provided a one-click migration command:

dart fix --apply --code=migrate_design_widgets

It will automatically replace imports of package:flutter/material.dart and package:flutter/cupertino.dart with the new independent packages.

There's a pitfall to mention here: an early bug in the migration tool might fail to update pubspec.yaml. If you encounter this, don't panic; just manually run flutter pub add material_ui (and cupertino_ui), then run dart fix --apply again.

What if dependencies haven't caught up?

The official team also considered the semi-migrated state and provided MaterialUiCompatibilityBridge. Even if some of your dependencies still use the old core SDK imports, your app can switch to the independent packages first:

import 'package:material_ui/material_ui.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF6750A4)),
      ),
      builder: (BuildContext context, Widget? child) {
        return MaterialUiCompatibilityBridge(child: child!);
      },
      home: const HomeScreen(),
    );
  }
}

Localization was also split

flutter_localizations was also split, with Material and Cupertino localization delegates moved into their respective packages.

Before migration:

import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter/material.dart';

localizationsDelegates: const <LocalizationsDelegate<dynamic>>[
  GlobalCupertinoLocalizations.delegate,
  GlobalMaterialLocalizations.delegate,
  GlobalWidgetsLocalizations.delegate,
],

After migration:

import 'package:material_ui/material_ui.dart';

localizationsDelegates: GlobalMaterialLocalizations.delegates,

One line replaces three. GlobalMaterialLocalizations.delegates automatically includes the Cupertino and Widgets delegates, making it even more convenient.

Key timeline to remember

The old design libraries in the core SDK are planned for official deprecation in the autumn stable release in November. If you maintain ecosystem plugins, treat this migration as a major release-level change; don't wait for users to prompt you.

Lao Liu's View

Back in 3.44, I worried about fragmentation, fearing a repeat of the chaos after the Android component library split. Looking at it this time, the official team has at least done their homework upfront.

Last time I said migration tools would be fully equipped when the time came; now that statement has been fulfilled. When the day comes to actually do it, with AI and official tools working together, the thankless task of manual modification will basically be non-existent.


2. Impeller Default on All Desktop Platforms

This is the change with the biggest impact on desktop developers in this update: the default rendering engine for macOS, Windows, and Linux has all been switched to Impeller.

What is Impeller?

It's Flutter's next-generation rendering engine, designed to replace Skia. Its biggest selling point is moving shader compilation to build time. A fixed set of shaders is pre-compiled, eliminating the inexplicable frame drops (shader compilation jank) that occur when an animation plays for the first time.

For platform backends, macOS uses Metal, while Windows and Linux use Vulkan.

Additionally, Impeller uses SDF (Signed Distance Function) to render text on desktop. Desktop text and vector curves will be clearer than before, something developers working on desktop utility apps should notice intuitively.

You can temporarily roll back if needed

If your project encounters issues under Impeller, all three platforms have a backdoor:

Note that these rollback options will be removed in the future. If your project must fall back to Skia to run, please make sure to file a bug with the official team; this is your only window to be heard.

Lao Liu's View

Impeller is essentially a custom rendering engine that directly commands the GPU to draw. The advantage of this path is that the interface is completely consistent on every platform, without the performance overhead of intermediate bridging.

Previously, when we said Flutter had its own rendering engine, we were mostly referring to the Flutter framework, but it wasn't a true rendering layer—it was a UI graphics framework. The actual rendering step was still handed over to each platform's own rendering engine, like Skia. Differences between platforms at the low level still existed.

Now, it's finally unified at this level too.

Impeller has been polished on mobile for a while; the fact that they dare to make it the default on all three desktop platforms this time shows the official team is confident in its quality. For those working on desktop apps, this version is worth a serious round of testing, especially regarding text rendering and animation smoothness.


3. Apple Platforms: Minimum Versions Raised, UIScene Becomes Mandatory

This section is the focus for iOS developers and the most non-negotiable part of the entire article.

Minimum System Version Increase

Platform Old Minimum Version New Minimum Version (Flutter 3.47+)
iOS 13 15
macOS 10.15 12

Users on iOS 13 to 14 are truly unreachable now. Remember to evaluate your user distribution before releasing.

Forced UIScene Lifecycle Migration

The iOS 27 SDK mandates that all UIKit apps adopt the UIScene lifecycle. Apps built with Xcode 27 that haven't adapted to UIScene will simply fail to launch.

The good news is that for most apps, the Flutter CLI handles the migration automatically at build time.

The bad news is that if your AppDelegate contains custom native code, or if you use plugins that depend on the old lifecycle, this part needs to be handled manually.

Lao Liu has been talking about this since July, calling it the September deadline back then. Now that 3.47 has the toolchain ready, things are actually simpler: as long as you still need to publish to the App Store, there's no way around this task; it's just a matter of doing it sooner or later.


4. Intel Mac Retirement, SwiftPM Sprint Nears Finish

Intel Mac Enters Phase-Out Countdown

The official team has stopped running automated tests on Intel hardware. Building on an Intel host, or building a dual-architecture package, will cause the CLI to print a warning. In a future version, the warning will escalate to an error.

For those still using an Intel Mac as their main machine, it's time to put a replacement plan on the agenda.

Speaking of which, this is an excellent reason to ask your boss for a new computer.

SwiftPM Migration Progress: 92/100

Among the top 100 iOS plugins, 92 have already completed the Swift Package Manager migration. CocoaPods has officially entered maintenance mode; plugins that haven't migrated will eventually stop working.

Additionally, community contributor @lukemmtt optimized the build pipeline by pre-filtering unnecessary SwiftPM schemes, resulting in a tangible improvement in build speed.

Lao Liu's View

Lao Liu has repeatedly warned before: don't rush to adopt AGP 9 and SPM for old projects; wait for the ecosystem to catch up.

Now the situation is starting to change. The adaptation rate for the top 100 plugins has reached 92%, and CocoaPods has entered maintenance mode. The direction is set in stone; it's just a matter of time.

My advice adjusts accordingly: for new projects, go straight to SwiftPM; for old projects, you can now pull out your plugin list, go through it to see which ones haven't adapted yet, and file issues with the authors in advance. If you wait until the day CocoaPods support is removed to act, you'll be in a passive position.


5. Wasm Continues to Advance, Widget Previews Promoted to Stable

Wasm Defaultization

Flutter is pushing for WebAssembly to be enabled by default for web applications.

There's a pitfall to mention upfront: Wasm does not support the old dart:html library; you must migrate to the new JS interop package (package:web). The good news is that upgrading project dependencies usually resolves most legacy interop issues automatically.

An experimental capability has also landed on the main channel: Wasm lazy loading. This splits the Wasm application into smaller, lazily-loaded modules to optimize initial screen load time.

For those working on web, this is worth keeping an eye on; first-screen speed is extremely important for web applications.

Widget Previews Promoted to Stable

Flutter Widget Preview has officially entered the stable channel. You can instantly render and inspect individual UI components without building and launching the entire application.

The stable version brings three improvements:

This feature is a real boon for component library authors and UI-intensive enterprise projects; changing a button no longer requires waiting for a full build.

As a side note, the GenUI package has also been updated to 0.10.0, adding the a2ui_core package to centrally manage protocol-related classes, and supporting A2UI client functions, allowing agents to instruct the client to perform small tasks like validation and deriving values, saving round-trip communication. The official team has been quietly doubling down on the AI-generated UI track.


6. Platform Detail Polishing, A Quick Run-Through

This section won't be expanded upon; just listing the key points. If any of these hit your pain points, go check the changelog yourself.

Android

iOS / macOS

Desktop

Framework Polish


Summary

Flutter 3.47 is not a version with major functional updates, but rather one that mainly turns previous plans into an official roadmap.

Design system decoupling, rendering engine replacement, and keeping up with Apple platform rules—any one of these three things is a major project on its own. The official team chose to serve them all up in a single version.

Lao Liu's Upgrade Advice

Our strategy has never changed: observe a new version for two months first, wait for core features to stabilize and the third-party ecosystem to catch up, then start upgrading.

Rather than spending time filling potholes in a new version, focus on your business logic.

Which part of this Flutter 3.47 update are you most concerned about? When do you plan to migrate for the Material split?

Feel free to leave a comment; let's chat.


🤝 If you've read this far and are interested in client-side or Flutter development, feel free to contact Lao Liu; let's learn from each other.

🎁 DM to get Lao Liu's compiled "Flutter Development Handbook" for free, covering 90% of application development scenarios. It can serve as a knowledge map for learning Flutter.

💬 : laoliu_dev

📂 Lao Liu has also organized his historical articles in a GitHub repository for easy reference.

🔗 https://github.com/lzt-code/blog

Comments

Top 1 from juejin.cn, machine-translated. The original thread is authoritative.

KazuhaKwan

Feels like I haven't seen Flutter in ages 🤣 The Xianyu experience is just hard to describe in a few words