Skip to content

[flutter_tools] register service worker after first frame event - #66082

Merged
jonahwilliams merged 7 commits into
flutter:masterfrom
jonahwilliams:dispatch_sw_event
Sep 24, 2020
Merged

jonahwilliams merged 7 commits into
flutter:masterfrom
jonahwilliams:dispatch_sw_event

Conversation

@jonahwilliams

@jonahwilliams jonahwilliams commented Sep 18, 2020 •

Copy link
Copy Markdown
Contributor

Description

Registering the service worker immediately after the documented has loaded may cause SW initialization to compete with framework initialization. It was recommended to us that we defer the service worker setup until after the framework is done with setup, which should be sometime after the first frame.

To implement this, I augmented the binding setup to dispatch an event on the document after the binding has initialized. I don't see any obvious risks with this setup.

Fixes #66066

@flutter-dashboard flutter-dashboard Bot added framework flutter/packages/flutter repository. See also f: labels. c: contributor-productivity Team-specific productivity, code health, technical debt. tool Affects the "flutter" command-line tool. See also t: labels. work in progress; do not review labels Sep 18, 2020
@jonahwilliams

Copy link
Copy Markdown
Contributor Author

I think my changes to the binding should be reasonable... :)

<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
window.addEventListener('flutter-first-frame', function () {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this event is dispatched by the flutter binding

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's probably some people with the old addEventListener('load'...), how do we normally communicate this type of changes to users? A tweet/blog post/something else?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm, its not really a breaking change. Probably the changelog?

}

List<void Function(Duration)> postFrameCallbacks;
List<void Function(Duration)> postFrameCallbacks = <void Function(Duration)>[];

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this needs to be initialized to a non-null value.

Comment thread packages/flutter/lib/src/rendering/_first_frame_web.dart Outdated

@ditman ditman left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me, I left a few comments but I don't think they're blocking at all.

(I don't push much to flutter/flutter, so you're probably more familiar than I am with the severity of the broken CI checks, though!)

Comment thread packages/flutter/lib/src/rendering/binding.dart
Comment thread packages/flutter/test/rendering/first_frame_test.dart Outdated
@jonahwilliams

Copy link
Copy Markdown
Contributor Author

Friendly ping @ditman :)

assert(renderView != null);
addPersistentFrameCallback(_handlePersistentFrameCallback);
initMouseTracker();
if (kIsWeb) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this behave with hot restart? Does it get called again?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it does get called again, but now (thanks to @yjbanov ) in run mode we definitely do not create a real service worker so it would only reload an empty script.

void _handleWebFirstFrame(Duration _) {
assert(kIsWeb);
const MethodChannel methodChannel = MethodChannel('flutter/service_worker');
methodChannel.invokeMethod<void>('first-frame');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw, you are not checking for the method name in the engine.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it is important unless we expand the number of actions here. i.e. building in service worker auto-update dialog or something.

@ditman ditman left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@jonahwilliams
jonahwilliams merged commit 90d83e3 into flutter:master Sep 24, 2020
@jonahwilliams
jonahwilliams deleted the dispatch_sw_event branch September 24, 2020 01:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c: contributor-productivity Team-specific productivity, code health, technical debt. framework flutter/packages/flutter repository. See also f: labels. tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use a first-frame event to signal that it is safe for the service worker to activate

4 participants