I'm using Flutter 2.5.2. I have a project which is to be used for both web and mobile (Android / iOS).
There is one particular widget where I need to use one version of the widget when deploying for web, which uses the JS and HTML packages. When deploying for mobile, I need to use a different version which just uses standard Flutter widgets. (The reasons for this are complex - I'm embedding Unity inside flutter).
So for example, I have this web_player.dart version for web:
import 'dart:html' as html;
import 'package:js/js.dart';
import 'package:flutter/material.dart';
@JS('loadPlayer')
external String loadPlayer();
class WebVersion extends StatelessWidget {
const WebVersion({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// Use the HTML package and return an HtmlElementView
}
}
And this mobile_player.dart version for mobile:
class MobileVersion extends StatelessWidget {
const MobileVersion({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text("Mobile version")
}
}
Building for web is fine. The problem is that when I build for mobile, the build breaks with:
Error: Not found: 'dart:js'
and
Error: Not found: 'dart:html'
I'm aware that these packages do not exist in the mobile platform, and I'm trying to find a workaround. I initially tried to conditionally use the WebPlayer or MobilePlayer widgets depending on the kIsWeb flag, but this didn't make any difference (I guess because kIsWeb is not a complile-time constant?)
So then I attempted to work around this using conditional imports. So, I created a stub player_stub.dart:
import 'package:flutter/material.dart';
Widget getPlayer() => throw UnsupportedError("This is a stub");
I import this stub in a wrapper Player widget:
import 'package:mypackage/player_stub.dart'
if (dart.library.io) 'package:mypackage/mobile_player.dart'
if (dart.library.js) 'package:mypackage/web_player.dart';
class Player extends StatelessWidget {
const Player ();
@override
Widget build(BuildContext context) {
return getPlayer();
}
}
And then added stub implementations in my mobile_player.dart:
Widget getPlayer() => MobilePlayer();
and in my web_player.dart:
Widget getPlayer() => WebPlayer();
I was hoping this would resolve the build error by compile time tree shaking or something, but it doesn't.
How do I solve this? I'm totally stumped.
Just to answer my own question for others looking for an answer: the solution was moving the stub, the mobile widget and the web widget to a separate dart library.
The library uses conditional exports like this in it's root my_player_package.dart file:
export 'src/player_stub.dart'
if (dart.library.js) 'src/web_player.dart'
if (dart.library.io) 'src/mobile_player.dart';
So now I reference my separate library in my pubspec.yaml:
dependencies:
...
my_player_package:
path: ../my_player_package
And I can now import 'package:my_player_package/my_player_package.dart' and build for both web and mobile.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With