How to detect Flutter web CanvasKit or HTML renderer?

Viewed 2205

There are two backends for Flutter Web currently, namely HTML and CanvasKit. As a library author, for performance reasons, I would like to identify which backend the app is currently running on. Is there anyway to detect that in code?

3 Answers

Flutter 2.0 Update (Mar 2021)

Now that there is a new "auto" mode to choose web renderers. The correct way to check is described in https://github.com/flutter/flutter/issues/73369#issuecomment-760543461

import 'dart:js' as js;
final isCanvasKit = js.context['flutterCanvasKit'] != null;

(Credit: github.com/slavap)


After digging into issues in the Flutter repository, I found the answer myself

As of Aug 2020, you can detect whether the backend is CanvasKit by

const bool.fromEnvironment('FLUTTER_WEB_USE_SKIA', defaultValue: false)

On web, a flutterCanvasKit property will be added to the window when running with CanvasKit. This means that we can use dart:js to access the window via context and retrieve the property from there.

Boolean getter

To have a full example here, I want to expand on the GitHub comments and add a complete function with conditional support. The easiest way to set up the function is as a boolean getter:

import 'dart:js';

/// Whether the CanvasKit renderer is being used on web.
///
/// Always returns `false` on non-web.
bool get isCanvasKit => context['flutterCanvasKit'] != null;

This getter works only on web and will return whether you are running on CavasKit, according to @yjbanov.

Conditional logic

In order to make your app compile on non-web (mobile and desktop), you need to make sure to not import this file when not running on web.
The easiest way to do this is using conditional exports:

export 'canvas_kit_stub.dart' if (dart.library.html) 'canvas_kit_web.dart';

You store the line above in a file called canvas_kit.dart. Then, you store the getter from above in a file called canvas_kit_web.dart in the same directory. The last step is creating the stub file (canvas_kit_stub.dart) with the following contents:

/// Whether the CanvasKit renderer is being used on web.
///
/// Always returns `false` on non-web.
bool get isCanvasKit => false;

Importing

Now, you can simply import 'canvas_kit.dart'; (with the path pointing to the file you created) and this will work on both mobile, desktop, and web. You need to make sure to not import either the _stub or _web version.

So I finally found it. I noticed that the HTML body contains a property called "fit-renderer" that specifies the renderer used. So you can use the following code

import 'dart:html' as HTML;

bool get usingHtmlRenderer =>
    html.document.body.getAttribute("flt-renderer").contains("html");

which returns "true" if you are using HTML renderer and "false" if you are using canvaskit.

Related