FLutter web

Flutter Web Useful Tools

Quan Ngo

--

Flutter 2.0 now officially support Web, below is some common situations when developing Flutter web and solutions:

Routing

  • Use getx with named route
  • Define route like this:
GetMaterialApp(
initialRoute: '/',
getPages: [
GetPage(
name: '/',
page: () => MyHomePage(),
),
GetPage(
name: '/profile/',
page: () => Profiles(),
),
GetPage(
name: '/profile/user',
page: () => UserProfile.newInstance(),
)
],
)
  • Then navigate like this:
Get.toNamed("/profile/user?name=quan&age=18");
  • Then navigate like this:
Get.parameters['name']
  • To safe to get param: create extension on Object like below:
extension CastTypeObjectExtension on Object {
int get castToInt {
if (this is int) {
return this;
}
return null;
}

double get castToDouble {
if (this is double) {
return this;
}
return null;
}

String get castToString {
if (this is String) {
return this;
}
return null;
}

bool get castToBool {
if (this is bool) {
return this;
}
return null;
}
}
  • Usage
String name = Get.parameters['name'].castToString

Provider and Param when navigate

  • Create a factory for widget to get param as well as pass provider
class UserProfile extends StatefulWidget {
static Widget newInstance() {
//pass provider here
//get param from path here
return
BlocProvider(
create: (context) {
return UserBloc();
},
child: UserProfile._(
name: Get.parameters['name'].castToString,
age: Get.parameters['age'].castToString,
));
}
final String name;
final String age;
UserProfile._({this.name, this.age});
@override
_UserProfileState createState() => _UserProfileState();
}

Cache libs: get_storage, or hive

  • init
void main() async {   await GetStorage.init();  ... }
  • get
currentCounter = GetStorage().read<int>('counter') ?? 0;
  • set
GetStorage().write('counter', currentCounter);

HTML renderer and CanvasKit renderer

  • More info
  • HTML renderer: smaller download size, suitable for mobile
flutter build web --web-renderer html
  • CanvasKit renderer: larger download size (+2MB), but faster performance, suitable for desktop
flutter build web --web-renderer canvaskit
  • Suggest to choose the auto option (default) if you are optimizing for download size on mobile browsers and optimizing for performance on desktop browsers.
flutter build web --web-renderer auto

Cookie, session

  • Local storage is enough to save data
  • Cookie will be automatically managed by browser
  • Use Dio package with option withCredential = true to send cookie in the request

Responsive

// return appropriate widgets base on screen type
ScreenTypeLayout.builder(
mobile: (BuildContext context) => Container(color:Colors.blue),
tablet: (BuildContext context) => Container(color:Colors.yellow),
desktop: (BuildContext context) => Container(color:Colors.red),
watch: (BuildContext context) => Container(color:Colors.purple),
);
// return appropriate value base on screen type
getValueForScreenType<double>(
context: context,
mobile: 10,
tablet: 30,
desktop: 60,
)
// Return a widget function per orientation
OrientationLayoutBuilder(
portrait: (context) => Container(color: Colors.green),
landscape: (context) => Container(color: Colors.pink),
),

Permission

  • Use html.window.navigator.permissions.query
final perm = await html.window.navigator.permissions.query({"name": "camera"});
if (perm.state == "denied") {
Scaffold.of(context).showSnackBar(SnackBar(
content: Text("Oops! Camera access denied!"),
backgroundColor: Colors.orangeAccent,
));
return;
}
final stream = await html.window.navigator.getUserMedia(video: true);

Select, drag file to upload

var picked = await FilePicker.platform.pickFiles();if (picked != null) {
print(picked.files.first.name);
}
Widget buildZone1(BuildContext context) => Builder(
builder: (context) => DropzoneView(
operation: DragOperation.copy,
cursor: CursorType.grab,
onHover: () {
setState(() => highlighted1 = true);
print('Zone 1 hovered');
},
onLeave: () {
setState(() => highlighted1 = false);
print('Zone 1 left');
},
onDrop: (file) {
setState(() {
message1 = '${file.name} dropped';
highlighted1 = false;
});
},
),
);

Embed JS code, communicate between dart and js

  • Create a file app.js under web folder with this content
function alertMessage(text) {
alert(text)
return 'from js with love';
}
  • Modify the index.html file under web folder
<head>
<script src="app.js" defer></script>
...
  • In dart side
import 'dart:js' as js;final value = js.context.callMethod('alertMessage', ['From flutter with love']);
print("result is $value"); //will print 'result is from js with love'

SEO

  • As Flutter render on the canvas instead of using html tags, so currently Flutter is not SEO-friendly

Some demo code

--

--