-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commands isolate
The isolate command enables targeted profiling. It extracts specific rebuild scopes
(such as a Flutter State class or a BlocBuilder) from a complex application and transplants
them into standalone, compilable Dart files. This lets you profile and optimize specific UI
segments in isolation, removing the noise and overhead of the rest of the app.
spm isolate --output-dir ./isolated_widgets /path/to/project
spm isolate -o ./isolation-output -j map.jsonl /path/to/project| Flag / Option | Short | Description |
|---|---|---|
--output-dir <path> |
-o |
Required. Directory where the isolated files are saved. |
--jsonl <path> |
-j |
Output JSONL mapping original source paths → isolated file paths. |
--verbose |
-v |
Enable verbose logging of the isolation process. |
<dir> [dir…] |
One or more directories to scan for rebuild scopes. |
The isolation process runs several stages of static analysis and code transformation.
An AST visitor scans the target directories for rebuild boundaries:
-
Classes: subclasses of
State,ConsumerWidget, orHookConsumerWidget. -
Builder patterns: the anonymous builder functions of
BlocBuilder,Consumer,Selector,Obx,GetX,Observer,StreamBuilder, and similar widgets.
The TransplantExtractor converts a discovered scope into a new, self-contained StatefulWidget
(GeneratedWidget).
- For a State class, SPM also finds its companion
StatefulWidgetto extract fields and constructors. - For a builder function, SPM extracts its parameters (e.g.
state,model) and converts them into fields on the new state.
To keep the generated file compilable, SPM recursively crawls the code for every referenced symbol:
- Internal dependencies: methods, fields, and getters used within the same class/file are moved into the new file.
- External dependencies: a custom Widget, Enum, or Painter from another file is resolved, extracted, and its own dependencies followed recursively.
- UI-only filtering: SPM only follows dependencies for UI elements (Widgets, Enums, Painters, Routes). It intentionally skips business logic, models, and services, assuming they will be mocked or provided.
-
Smart imports: the necessary
package:flutteranddart:imports are collected automatically.
Isolated widgets often lack the original project's assets. The Skeletonizer:
- Identifies widgets like
Image.network,AssetImage, orSvgPicture. - Replaces them with lightweight placeholders.
- Ensures the widget can still lay out and render without crashing on missing files.
output/
├── State/
│ ├── login_form_state.dart
│ └── product_list_state.dart
├── BlocBuilder/
│ └── user_profile_builder.dart
└── mapping.jsonl
Links each isolated file back to its original source. One JSON object per line:
{
"originalPath": "/abs/path/to/project/lib/ui/login_form.dart",
"nodeType": "State",
"isolatedPath": "/abs/path/to/output/State/login_form_state.dart",
"name": "LoginFormState"
}| Field | Description |
|---|---|
originalPath |
Absolute path of the source file the scope was extracted from. |
nodeType |
Scope kind, which is also the output subdirectory name (State, BlocBuilder, Consumer, …). |
isolatedPath |
Absolute path of the generated standalone file. |
name |
Name of the extracted class or builder-owning widget. |
- Reduced noise. Frame timings aren't affected by unrelated background tasks or complex trees.
- Speed. Hot reload is much faster on a single-widget file.
-
Targeted benchmarking. Wrap the
GeneratedWidgetin a benchmark loop to measure the exact cost of a specific rebuild. - Environment control. With dependencies minimized, mocking the state or data passed in is easy.
- Logic stripping. Because SPM skips non-UI dependencies, logic involving complex models or services may need manual adjustment or mocking in the generated file.
- Asset dependencies. The Skeletonizer handles images, but custom fonts or localized strings may still need manual setup if critical to the widget.
Commands
Reference
Internals
Contributing