DISCLAIMER:
This project is just a temporary workaround for sharing more code between platforms. At one point, Flutter Web will be merged into the main repository and you will be able to generate a web app from an existing mobile app (more info here and here). Obviously, it is recommended to wait for the merge (though the code produced with
flutter_cross
will be updated to work also with end configuration).
Today, flutter and flutter_web are two distinct frameworks, so user intefaces can't be shared between a mobile and a web app.
This project demonstrates a principle for sharing UI code between flutter and flutter_web based on conditional imports.
To create your cross-platform UI project, you must use the flutter_cross
package instead of the platform specific framework.
The pubspec.yaml
file of your shared package should have those dependencies :
name: flutter_cross_example
environment:
sdk: '>=2.2.0 <3.0.0'
dependencies:
flutter_cross: any
# flutter_cross package is not published to pub.dartlang.org
# These overrides tell the package tools to get them from GitHub
dependency_overrides:
flutter_cross:
git:
url: https://github.com/aloisdeniel/flutter_shared_ui_poc
path: packages/flutter_cross
Code your flutter app like you would have with Flutter, except :
package:flutter
(or package:flutter_web
) to package:flutter_cross
throughout your application code.dart:ui
(or package:flutter_web_ui
) to package:flutter_cross/ui.dart
.You can share 100% of your app in shared code, or several widgets only.
If you share Widgets and use them in your platform code, you IDE will break because shared Widgets
arent platform ones by default (even if at compile time they are). Simply cast them as dynamic
in such situation.
The interresting parts are in the flutter_cross export files.
export 'package:flutter_stub/material.dart'
// ignore: uri_does_not_exist
if (dart.library.html) 'package:flutter_web/material.dart'
// ignore: uri_does_not_exist
if (dart.library.io) 'package:flutter/material.dart';
This conditional exports tell the compiler that it should override the default stubs for the dedicated platform dependencies.
The project contains three different parts.
A plain dart package that abstracts every common Flutter APIs (and depends neither on dart:io
and dart:html
).
To create those packages, I forked flutter/flutter_web
repository and :
flutter_stub/lib
: all code is the same as flutter_web/lib
except that imports have been updated.flutter_stub_ui/lib
: the engine html specific code has been manually updated to throw exceptions instead of actual logic.A generator could be implemented to automate this process.
This package exposes the right API regarding the current target : flutter_web
if dart:html
is available, flutter
if dart:io
is available, else flutter_stub
.
The example project that shows a mobile and a web app that uses a Widget that is declared in a third shared_ui project.
All the application is exactly the same as a Flutter one, except that imports should be :
flutter_cross/<file>.dart
instead of flutter/<file>.dart
(or flutter_web/<file>.dart
)flutter_cross/ui.dart
instead of dart:ui
(or flutter_web_ui/ui.dart
)