Skip to content

Instantly share code, notes, and snippets.

@jezell
Created December 13, 2024 16:52
Show Gist options
  • Save jezell/8a56f7d484cf0535863ccb0a7e00ea4e to your computer and use it in GitHub Desktop.
Save jezell/8a56f7d484cf0535863ccb0a7e00ea4e to your computer and use it in GitHub Desktop.
Flutter Widget Preview.md

Why this approach is problematic

  1. Over-Complex Architecture:
    The proposed solution sets up a multi-stage pipeline:

    • Generating and maintaining a separate “preview scaffold” project in .dart_tool.
    • Using that separate project as a specialized Flutter Desktop application.
    • Streaming rendered frames and user interactions over WebSockets to a web-based viewer.

    This layering of multiple components (desktop environment, web viewer, frame streaming, custom asset bundle, etc.) makes the system unusually complex. Complexity increases the risk of bugs, maintenance overhead, and reduces the predictability of future compatibility. Each added layer—especially streaming pixels and events across processes—introduces new potential points of failure and performance bottlenecks.

  2. Platform and Rendering Constraints:

    • Desktop Dependencies: The approach relies on generating and running a desktop Flutter application. This forces developers on platforms that don’t fully support Flutter Desktop or are constrained by IT policies to jump through hoops (e.g., enabling Desktop support just to use previews).
    • Software Rendering and Performance Issues: Using flutter_tester or relying on software rendering can lead to low frame rates and poor developer experience. Relying on a custom pipeline for rendering frames may also limit or complicate future integration with accelerated rendering, debugging, or GPU-accelerated previews.
  3. Limited Feature Parity (Accessibility, Platform Views, Plugins):
    By creating a minimalistic “emulated” environment that just streams pixels and pointer events, the tool paints itself into a corner. Many Flutter features—such as platform views, plugin integrations, and accessibility—are left out. Over time, it may be challenging to extend the previews to handle these features without significantly re-architecting the setup.

    While the initial scope is just UI previews, developers quickly come to expect the ability to preview richer interactions and platform integrations. Without a more direct approach, future extensibility becomes difficult or requires substantial rework.

  4. Heavy Reliance on Code Generation and Injection: The approach requires scanning the user’s codebase with the analyzer, generating lib/generated_preview.dart, and injecting code into a separate preview scaffold. While this is technically feasible, it adds cognitive load and complexity:

    • What if the developer’s project structure changes?
    • How stable is the code generation layer against future framework changes?
    • How do we ensure the analyzer-based approach doesn’t break on newer language or framework features?
  5. Fragile External Dependencies: Relying on external packages like device_frame at the core of the solution poses a risk if those packages become outdated, are abandoned, or break compatibility with future versions of Flutter. This introduces a maintenance and upgrade burden that may hinder long-term stability.

Suggested Alternative Approaches

  1. Direct Web-based Previews (Flutter Web Integration):
    Instead of streaming pixels from a desktop runner, consider using Flutter Web directly.

    • In-IDE Web Views: Modern IDEs (like VSCode) can embed web views. Running a headless Flutter Web preview in-process (or via a lightweight dev server) would allow the IDE to display the rendered widget previews directly.
    • No Pixel Streaming: Rather than sending raw pixel data, run Flutter directly in a web environment. The IDE extension can load that URL in a webview. Hot reload can be achieved via the same mechanisms the Flutter web dev tools use.
    • Inspector Integration: With a Flutter web environment, the inspector and widget tree inspection tools can work more naturally without requiring a separate pixel streaming and event-forwarding solution. Future enhancements like proper debugger integration or direct widget inspection via DWDS (Dart Web Debugging) become more straightforward.
  2. Integrated Preview Mode in the Flutter Tool: Instead of a separate scaffold application, Flutter’s run command could gain a “preview mode” flag:

    • This mode would run a minimal version of the developer’s app in a special configuration that supports:
      • Live hot reload on code changes.
      • An environment to inject preview configurations (devices, layouts, locales) directly into the running web or desktop environment.
    • The IDE plugin would merely interact with this “preview mode” via stable, documented Flutter tool commands, removing the need to generate complex scaffolding or handle a two-way frame streaming process.
  3. Leverage Existing Inspector Protocols: Consider extending the existing Flutter DevTools protocol rather than creating a new interaction protocol. DevTools already supports interactions, layout inspection, and frame rendering on the web:

    • Integrate previews as a special mode in DevTools or a DevTools plugin.
    • The IDE then merely needs to open DevTools (or a DevTools extension) in a pane, reducing the complexity of managing separate servers and WebSocket connections.
  4. Hybrid Approach with Compilation Flags or Conditional Imports: If direct web support isn't feasible immediately, a hybrid approach could:

    • Build a special preview target (like flutter run --preview) that generates an embedded web server or uses flutter_tester with hardware acceleration in the future.
    • Keep the pipeline simple: run the code directly, serve frames and debugging info via DevTools protocol, and let the IDE load a minimal viewer that leverages existing web-based tooling.

In summary, the major issues with the current approach are its complexity, reliance on multiple indirect layers for rendering and input handling, platform-specific dependencies, and difficulty in extending features. A simpler, more direct integration with Flutter Web or a known stable Flutter preview environment (like DevTools) would reduce complexity, improve performance, and make the system more maintainable and future-proof.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment