Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Allowing web apps to delay layout/rendering on startup

362 views
Skip to first unread message

James Burke

unread,
Jul 30, 2015, 4:20:35 PM7/30/15
to dev-pl...@lists.mozilla.org
There are some forces at play in a web app that point to wanting to delay
layout and rendering until a web app gives a signal that it should start:

* ECMAScript modules, and even developer constructed JS module systems
today, rely on async loading of scripts.

* Custom elements need their JS registered with the browser before they are
fully useful.

* Apps can have dependencies on async IDB operations to know what UI to
first show. For instance, if the user does not have a saved account, show
the sign in view instead of the app data view.

* We want fast app startups in B2G/Gaia. Typically we lose
layout/render/paint time while we wait for these async mechanisms to
finish, and the paints are not useful for the user in the meantime.

In addition, there is a possibility that custom elements may take a path of
synchronous construction with no later upgrades, which means the JS for the
custom element needs to be registered before any custom element is used in
the DOM.

A similar case surfaced a while back in the context of B2G, and at the time
I filed bug 863499[2], which focused on a document.mozDelayLoadEvent /
document.mozStopDelayingLoadEvent JS API around controlling the load event
firing.

At that time, the concern was about losing times to wasted renders and the
effects on screen shots.

However, I believe the main concern now is getting enough JS and app data
loaded to allow layout to be effective in fewer passes than strictly about
the final render and load event. So maybe the API should be more about
delaying layout than about the load event?

In talking to Wilson Page, he mentioned something like a
document.pauseLayout() document.resumeLayout(), not sure if there are
existing thoughts around that.

If that seemed workable, maybe also a <html mozPauseLayout> type of
attribute, so the browser knows as soon as possible to pause its work,
instead of relying on a JS API.

For Gaia apps, we use a CSP policy that does not allow inline scripts, so
the attribute on a tag is more appealing for that reason. A nonced script
might be a workable alternative for the CSP case, if an attribute was too
much of a stretch.

Happy to hear about any suggestions for the general goal,
James

[1] Service workers help a bit here, but do not help the other aync forces.
[2] https://bugzilla.mozilla.org/show_bug.cgi?id=863499

Jeff Muizelaar

unread,
Jul 30, 2015, 4:28:07 PM7/30/15
to James Burke, Mozilla
Can't you just make everything display:none until you're ready to show it?

-Jeff
> _______________________________________________
> dev-platform mailing list
> dev-pl...@lists.mozilla.org
> https://lists.mozilla.org/listinfo/dev-platform

David Rajchenbach-Teller

unread,
Jul 30, 2015, 4:30:45 PM7/30/15
to James Burke, dev-pl...@lists.mozilla.org
I can't speak about the validity of the requirement, but in terms of
API, we probably want something more compositional, if several codepaths
need to stop rendering. And then, we end up with the possibility that
someone forgets to enable rendering, with all the ensuing debugging joy.

Since this is exactly the kind of issue we fight with Async Shutdown, I
would suggest an API that looks more like

document.mozLayout.addBlocker("Hey, I need to finish looking at IDB",
somePromise);

This will let the DevTools inspect the state, either to find out which
of the blockers is slow to respond, or to find which of the blockers
doesn't respond at all.

Cheers,
David

On 30/07/15 22:20, James Burke wrote:
> In talking to Wilson Page, he mentioned something like a
> document.pauseLayout() document.resumeLayout(), not sure if there are
> existing thoughts around that.
>
> If that seemed workable, maybe also a <html mozPauseLayout> type of
> attribute, so the browser knows as soon as possible to pause its work,
> instead of relying on a JS API.
>
> For Gaia apps, we use a CSP policy that does not allow inline scripts, so
> the attribute on a tag is more appealing for that reason. A nonced script
> might be a workable alternative for the CSP case, if an attribute was too
> much of a stretch.
>
> Happy to hear about any suggestions for the general goal,
> James
>
> [1] Service workers help a bit here, but do not help the other aync forces.
> [2] https://bugzilla.mozilla.org/show_bug.cgi?id=863499
> _______________________________________________
> dev-platform mailing list
> dev-pl...@lists.mozilla.org
> https://lists.mozilla.org/listinfo/dev-platform
>


--
David Rajchenbach-Teller, PhD
Performance Team, Mozilla

signature.asc

James Burke

unread,
Jul 30, 2015, 7:27:31 PM7/30/15
to Jeff Muizelaar, Mozilla
On Thu, Jul 30, 2015 at 1:28 PM, Jeff Muizelaar <jmuiz...@mozilla.com> wrote:
> Can't you just make everything display:none until you're ready to show it?

Just using display: none seems like it will run into the same problem
that prompted bug 863499, where the browser did some render/paints of
a white page, which took time away from the async work completing.

So maybe I should not frame it as just pausing layout? I was hoping it
would also delay render and maybe paints that happen during startup,
so more time is given up front to the async activities.

James

Karl Tomlinson

unread,
Jul 30, 2015, 8:11:32 PM7/30/15
to
If the window is shown, then something will be rendered.

Perhaps you want to delay showing the window?

Bobby Holley

unread,
Jul 30, 2015, 8:38:05 PM7/30/15
to James Burke, Jeff Muizelaar, Mozilla
On Thu, Jul 30, 2015 at 4:27 PM, James Burke <jbu...@mozilla.com> wrote:

> On Thu, Jul 30, 2015 at 1:28 PM, Jeff Muizelaar <jmuiz...@mozilla.com>
> wrote:
> > Can't you just make everything display:none until you're ready to show
> it?
>
> Just using display: none seems like it will run into the same problem
> that prompted bug 863499, where the browser did some render/paints of
> a white page, which took time away from the async work completing.
>
> So maybe I should not frame it as just pausing layout? I was hoping it
> would also delay render and maybe paints that happen during startup,
> so more time is given up front to the async activities.
>

Painting a document with display:none on the body should be more or less
free, I'd think. If it isn't, please file a bug.

Benoit Girard

unread,
Jul 31, 2015, 5:04:45 PM7/31/15
to Bobby Holley, Jeff Muizelaar, James Burke, Mozilla
It should be represented as a color layer which is very cheap. We should
only composite it once. We will use a bit of memory bandwidth but nothing
major, the main thread impact should be very small.

I agree, we should really have some data to support that drawing something
like a display:none is causing a measurable slow down if this is the road
we're going to go down. If we're just inefficient at it then I agree we
should do better. I'd be surprised if we could not afford the main thread
paint tick of a display:none page assuming we're not just hitting a
performance problem. We'd have a nearly empty displaylist, no rasterization
and it would use an async transaction to the compositor.

Zibi Braniecki

unread,
Aug 1, 2015, 3:30:55 PM8/1/15
to
This is something I've been asking for for quite a while.

We have this state with runtime localization where we have to do backflips in order to win the race with Gecko to firstPaint.

I filed a bug for getting an API to prevent frame creation [0] and got a response that display: none should do this. Because I couldn't verify any gain and I hit the "white page on load" problem I gave up.

My understanding is that we have two topics here:

1) We need a way to inject asynchronous javascript that will take DOM from HTML, modify it and report when done. There may be multiple code pieces that want to do this and it should delay frame creation and layout until this code is done.

That concept that a given app wants to prevent frame creation until its JS reports being done would help a lot of frameworks like react, angular and localization related as well.

The challenge is that ideally we would like to not have to inject synchronous script to enable that. So any form of <meta> tag or manifest entry would be better than DOM API for notifying the platform that this page wants to delay.

We may also want to think about a timeout in case things go south, but I'm not sure if after the timeout we should paint whatever we have (almost certainly a broken and useless UI) or should we paint a user-friendly "This page is broken. Restart? Reinstall? Remove? Report?" dialog.
From the perspective of Gaia UI I'd say the latter.

2) We want to bring app to foreground/paint it only when the app's chrome is visually complete.

This is easier since we now have the performance marks and they nicely correspond to when the UI of the app is meaningful. The only challenge here is that the marks from the website are representing app code state and intention. "navigationLoaded" which indicates that chrome code is ready will overlap with "start frame creation" from 1) but doesn't mean that frame/layout/firstPaint happened.

So on one hand we could tie Gaia system to bring app to foreground on this even, on the other hand, ideally we'd like to tie that event to gecko's frame/layout and then bring the app to foreground on firstPaint.

------------------------------------

So if the display:none strategy does prevent frame/layout, I see the solution as such:

1) We add <body style="display:none"> to our apps
2) We switch body.style.display = 'block'; on navigationLoaded
3) We need an event from Gecko when *after* step (2) it painted the document
4) We need to switch in the system to only bring apps to foreground in reaction to step (3)

That should solve it?

On top of that we could achieve two more features:

a) Look from System into app's document's DOM on DOMContentLoaded and if <body> has display='none' wait with bringing it to the foreground for navigationLoaded

b) If document's body has display='none' and doesn't fire up navigationLoaded in a certain amount of time, stop script execution of that document and display "Unfortunately this app failed to load" user-friendly dialog.

What do you think?

zb.

[0] https://bugzilla.mozilla.org/show_bug.cgi?id=1176924

Jonas Sicking

unread,
Aug 1, 2015, 6:01:39 PM8/1/15
to Zibi Braniecki, dev-platform
On Sat, Aug 1, 2015 at 12:30 PM, Zibi Braniecki
<zbigniew....@gmail.com> wrote:
> 2) We want to bring app to foreground/paint it only when the app's chrome is visually complete.

I would very much want this. Right now, during a navigation from page
A to page B I believe that we render A until we've parsed B's opening
<body> tag. It would be great if we enabled pages to communicate to
the browser when they are actually ready to render.

/ Jonas

Zibi Braniecki

unread,
Aug 1, 2015, 7:58:41 PM8/1/15
to
On Saturday, August 1, 2015 at 3:01:39 PM UTC-7, Jonas Sicking wrote:
> On Sat, Aug 1, 2015 at 12:30 PM, Zibi Braniecki wrote:
> > 2) We want to bring app to foreground/paint it only when the app's chrome is visually complete.
>
> I would very much want this. Right now, during a navigation from page
> A to page B I believe that we render A until we've parsed B's opening
> <body> tag. It would be great if we enabled pages to communicate to
> the browser when they are actually ready to render.

Agree.

Working on the performance.mark events (Eli may have more insight) made me realize that we generally have two types of apps:

1) Apps that have a defined and useful chrome. Example is SMS app. When it's chrome is ready, we should paint and show it to the user, and only then work on loading the content (list of text messages). We should also take a screenshot with the chrome only (to prevent data leaking) and possibly cache chrome for quick-display.

2) Apps that are useless without content. Example is Settings app where chrome is literally just the top header. For those, the firstPaint/foreground should happen only on visuallyLoaded - when the visible portion of content is loaded because displaying it without doesn't make sense.

So maybe we would need another event that the website fires to indicate when it for paint/cache/screenshot.

zb.

Robert O'Callahan

unread,
Aug 2, 2015, 5:03:28 AM8/2/15
to Zibi Braniecki, dev-pl...@lists.mozilla.org
On Sun, Aug 2, 2015 at 11:58 AM, Zibi Braniecki <
zbigniew....@gmail.com> wrote:

> So maybe we would need another event that the website fires to indicate
> when it for paint/cache/screenshot.
>

Assuming pages have an easy way to block the 'load' event until they're
ready, can this just be the 'load' event?

Rob
--
lbir ye,ea yer.tnietoehr rdn rdsme,anea lurpr edna e hnysnenh hhe uresyf
toD
selthor stor edna siewaoeodm or v sstvr esBa kbvted,t
rdsme,aoreseoouoto
o l euetiuruewFa kbn e hnystoivateweh uresyf tulsa rehr rdm or rnea
lurpr
.a war hsrer holsa rodvted,t nenh hneireseoouot.tniesiewaoeivatewt sstvr
esn

Zibi Braniecki

unread,
Aug 2, 2015, 6:06:17 AM8/2/15
to
On Sunday, August 2, 2015 at 2:03:28 AM UTC-7, Robert O'Callahan wrote:
> On Sun, Aug 2, 2015 at 11:58 AM, Zibi Braniecki wrote:
>
> > So maybe we would need another event that the website fires to indicate
> > when it for paint/cache/screenshot.
> >
>
> Assuming pages have an easy way to block the 'load' event until they're
> ready, can this just be the 'load' event?

you mean window.load or performance.mark fullyLoaded?

If the former, I'm not sure how a page can control when the loaded is fired.

If the latter, then it's not a good one. fullyLoaded is supposed to be fired when the page finished loading background data needed for operation.


zb.

Jonas Sicking

unread,
Aug 2, 2015, 4:15:47 PM8/2/15
to Robert O'Callahan, dev-pl...@lists.mozilla.org, Zibi Braniecki
On Sun, Aug 2, 2015 at 2:03 AM, Robert O'Callahan <rob...@ocallahan.org> wrote:
> On Sun, Aug 2, 2015 at 11:58 AM, Zibi Braniecki <
> zbigniew....@gmail.com> wrote:
>
>> So maybe we would need another event that the website fires to indicate
>> when it for paint/cache/screenshot.
>
> Assuming pages have an easy way to block the 'load' event until they're
> ready, can this just be the 'load' event?

I think that's too late in many cases.

Often times the "chrome" of a webapp is ready before various other
things that are loaded during initial page load is loaded.

/ Jonas

Robert O'Callahan

unread,
Aug 2, 2015, 5:41:33 PM8/2/15
to Jonas Sicking, dev-pl...@lists.mozilla.org, Zibi Braniecki
On Mon, Aug 3, 2015 at 8:15 AM, Jonas Sicking <jo...@sicking.cc> wrote:

> Often times the "chrome" of a webapp is ready before various other
> things that are loaded during initial page load is loaded.
>

OK then, I guess a new event is needed.

Jonas Sicking

unread,
Aug 3, 2015, 12:54:16 AM8/3/15
to Robert O'Callahan, dev-pl...@lists.mozilla.org, Zibi Braniecki
On Sun, Aug 2, 2015 at 2:41 PM, Robert O'Callahan <rob...@ocallahan.org> wrote:
> On Mon, Aug 3, 2015 at 8:15 AM, Jonas Sicking <jo...@sicking.cc> wrote:
>>
>> Often times the "chrome" of a webapp is ready before various other
>> things that are loaded during initial page load is loaded.
>
> OK then, I guess a new event is needed.

The need is not for an event, no? But rather for an API which allows
the page to tell the browser that it's ready for initial rendering?

/ Jonas

Robert O'Callahan

unread,
Aug 3, 2015, 1:28:53 AM8/3/15
to Jonas Sicking, dev-pl...@lists.mozilla.org, Zibi Braniecki
On Mon, Aug 3, 2015 at 4:53 PM, Jonas Sicking <jo...@sicking.cc> wrote:

> The need is not for an event, no? But rather for an API which allows
> the page to tell the browser that it's ready for initial rendering?
>
Right. Which gets turned into an event that's sent to the browser.

Wilson Page

unread,
Aug 3, 2015, 1:47:26 AM8/3/15
to Robert O'Callahan, Zibi Braniecki, dev-pl...@lists.mozilla.org, Jonas Sicking
Are we expecting that this will reduce unwanted layout/paint cycles on the
critical path and thus minimise the 'white flash of doom'? If not what are
the options for killing this?

If the user has to see anything before the new 'please-draw-me' event, we'd
probably like to see the app's background painted with the primary theme
color, or some kind of splash-screen image. Anything but the signature 'I'm
a clunky old website' white flash :)

*W I L S O N P A G E*

Front-end Developer
Firefox OS (Gaia)
London Office

Twitter: @wilsonpage
IRC: wilsonpage

On Mon, Aug 3, 2015 at 6:28 AM, Robert O'Callahan <rob...@ocallahan.org>
wrote:

Jonas Sicking

unread,
Aug 3, 2015, 2:00:22 AM8/3/15
to Robert O'Callahan, dev-pl...@lists.mozilla.org, Zibi Braniecki
On Sun, Aug 2, 2015 at 10:28 PM, Robert O'Callahan <rob...@ocallahan.org> wrote:
> On Mon, Aug 3, 2015 at 4:53 PM, Jonas Sicking <jo...@sicking.cc> wrote:
>>
>> The need is not for an event, no? But rather for an API which allows
>> the page to tell the browser that it's ready for initial rendering?
>
> Right. Which gets turned into an event that's sent to the browser.

Ah, yes, that makes sense.

/ Jonas

Anne van Kesteren

unread,
Aug 3, 2015, 2:13:08 AM8/3/15
to Jonas Sicking, Zibi Braniecki, dev-pl...@lists.mozilla.org, Robert O'Callahan
On Mon, Aug 3, 2015 at 7:59 AM, Jonas Sicking <jo...@sicking.cc> wrote:
> Ah, yes, that makes sense.

Is this yet another API where we want to basically have an internal
list of promises?

someInstance.doNotRenderUntil(promise)


--
https://annevankesteren.nl/

Zibi Braniecki

unread,
Aug 3, 2015, 2:52:43 AM8/3/15
to
On Sunday, August 2, 2015 at 10:47:26 PM UTC-7, Wilson Page wrote:
> Are we expecting that this will reduce unwanted layout/paint cycles on the
> critical path and thus minimise the 'white flash of doom'?

Absolutely.

I believe that that's the primary goal, to replace the current race condition between app's JS and the engine to firstPaint.

> If the user has to see anything before the new 'please-draw-me' event, we'd
> probably like to see the app's background painted with the primary theme
> color, or some kind of splash-screen image. Anything but the signature 'I'm
> a clunky old website' white flash :)

That's a cool idea. I'd suggest that for Gaia we'd prefer not to move the app to foreground at all, or do some smart calculations to know that the app starts on average in 600ms, so start the 200ms transition animation after 400ms.

But for web apps in the browser that would make a lot of sense.

zb.

Jonas Sicking

unread,
Aug 3, 2015, 3:23:53 AM8/3/15
to Anne van Kesteren, Zibi Braniecki, dev-pl...@lists.mozilla.org, Robert O'Callahan
On Sun, Aug 2, 2015 at 11:12 PM, Anne van Kesteren <ann...@annevk.nl> wrote:
> On Mon, Aug 3, 2015 at 7:59 AM, Jonas Sicking <jo...@sicking.cc> wrote:
>> Ah, yes, that makes sense.
>
> Is this yet another API where we want to basically have an internal
> list of promises?
>
> someInstance.doNotRenderUntil(promise)

I don't have a strong opinion on syntax.

Though for the above to be reliable you'd want to make sure that all
.doNotRenderUntil() calls happen in blocking <script>s in the <head>.
Promises that are registered later would race with the other tasks
finishing before the registration.

And I think we generally want to avoid blocking <script>s in the <head>.

I think something like a <meta name="do-not-render"> might be a
simpler solution here. Coupled with either simply removing the <meta>
from the DOM, or having a function which indicates that rendering is
ok.

/ Jonas

Anne van Kesteren

unread,
Aug 3, 2015, 3:33:30 AM8/3/15
to Jonas Sicking, Zibi Braniecki, dev-pl...@lists.mozilla.org, Robert O'Callahan
On Mon, Aug 3, 2015 at 9:23 AM, Jonas Sicking <jo...@sicking.cc> wrote:
> I think something like a <meta name="do-not-render"> might be a
> simpler solution here. Coupled with either simply removing the <meta>
> from the DOM, or having a function which indicates that rendering is
> ok.

Neither of those deal well with multiple libraries being included in
the page, which is likely going forward with custom elements et al.


--
https://annevankesteren.nl/

Jonas Sicking

unread,
Aug 3, 2015, 3:38:12 AM8/3/15
to Anne van Kesteren, Zibi Braniecki, dev-pl...@lists.mozilla.org, Robert O'Callahan
I suspect it's better for the various components to indicate when they
are done loading and let the page indicate which components are
critical, and which ones aren't.

Loading all those libraries in the <head> also doesn't seem like a
good solution.

/ Jonas

Bobby Holley

unread,
Aug 3, 2015, 11:47:10 AM8/3/15
to Jonas Sicking, dev-pl...@lists.mozilla.org, Zibi Braniecki, Robert O'Callahan
On Mon, Aug 3, 2015 at 12:37 AM, Jonas Sicking <jo...@sicking.cc> wrote:

> On Mon, Aug 3, 2015 at 12:32 AM, Anne van Kesteren <ann...@annevk.nl>
> wrote:
> > On Mon, Aug 3, 2015 at 9:23 AM, Jonas Sicking <jo...@sicking.cc> wrote:
> >> I think something like a <meta name="do-not-render"> might be a
> >> simpler solution here. Coupled with either simply removing the <meta>
> >> from the DOM, or having a function which indicates that rendering is
> >> ok.
> >
> > Neither of those deal well with multiple libraries being included in
> > the page, which is likely going forward with custom elements et al.
>
> I suspect it's better for the various components to indicate when they
> are done loading and let the page indicate which components are
> critical, and which ones aren't.
>

Agreed. I think it would be very strange for a library to block all
rendering. The <meta> tag (with removal to indicate readiness) sounds good
to me - then we don't even need a separate event.

James Graham

unread,
Aug 4, 2015, 5:07:57 AM8/4/15
to dev-pl...@lists.mozilla.org
I am extremely wary of designing a solution like this where there's a
single master switch that any code can unilaterally flip; if the
assumption that libraries will never want to delay rendering turns out
to be false it will force page authors to deal with N library-specific
protocols to indicate that they are no longer blocking rendering, and
give any one component that ability to override all others.

Unrelatedly, I assume that people are thinking of this as a hint to the
UA rather than an absolute requirement. I would certainly expect the UA
to render in any case after some timeout so that sites with some mild
brokenness that causes them not to unset the no-render flag for whatever
reason (e.g. browser-specific codepaths and insufficient testing) are
still actually usable.

Julien Wajsberg

unread,
Aug 4, 2015, 5:51:24 AM8/4/15
to dev-pl...@lists.mozilla.org
Le 30/07/2015 22:28, Jeff Muizelaar a écrit :
> Can't you just make everything display:none until you're ready to show it?

Note that even with "display: none" we run refreshStyles everytime an
element is added to the page. I don't know if this is fast when the
whole document.body is hidden though.

signature.asc

Anne van Kesteren

unread,
Aug 4, 2015, 5:56:00 AM8/4/15
to James Graham, dev-pl...@lists.mozilla.org
On Tue, Aug 4, 2015 at 11:07 AM, James Graham <ja...@hoppipolla.co.uk> wrote:
> I am extremely wary of designing a solution like this where there's a single
> master switch that any code can unilaterally flip; if the assumption that
> libraries will never want to delay rendering turns out to be false it will
> force page authors to deal with N library-specific protocols to indicate
> that they are no longer blocking rendering, and give any one component that
> ability to override all others.

Agreed, I also don't want us to repeat a <meta name=viewport>-style
design. I thought it was agreed that was unfortunate last time around.


--
https://annevankesteren.nl/

Jonas Sicking

unread,
Aug 4, 2015, 12:00:53 PM8/4/15
to Anne van Kesteren, James Graham, dev-pl...@lists.mozilla.org
I'm open to counter proposals. But blocking scripts are also bad. As
is requiring inline scripts since they don't work with websites that
want to use CSP.

/ Jonas

Bobby Holley

unread,
Aug 4, 2015, 1:07:03 PM8/4/15
to Jonas Sicking, James Graham, dev-pl...@lists.mozilla.org
How about a scheme in which there can be N such <meta> elements, and the
painting only happens when all of them are gone (or some timeout occurs)?
That solve the common case that Jonas is talking about, and allows
libraries to insert their own paint blocker into <head> if they really want
to block painting? The a nice side-bonus of this scheme is that the
existence of blockers is clearly visible in the DOM, so that a buggy
library that leaves a paint blocker active is more noticeable.

Bobby Holley

unread,
Aug 4, 2015, 1:11:10 PM8/4/15
to Jonas Sicking, James Graham, dev-pl...@lists.mozilla.org
(And note that it would be trivial to implement a programmatic promise-y
API on top of this as a library, if people want that).

Jonas Sicking

unread,
Aug 4, 2015, 3:09:28 PM8/4/15
to Bobby Holley, James Graham, dev-pl...@lists.mozilla.org
On Tue, Aug 4, 2015 at 10:06 AM, Bobby Holley <bobby...@gmail.com> wrote:
> How about a scheme in which there can be N such <meta> elements, and the
> painting only happens when all of them are gone (or some timeout occurs)?
> That solve the common case that Jonas is talking about, and allows libraries
> to insert their own paint blocker into <head> if they really want to block
> painting? The a nice side-bonus of this scheme is that the existence of
> blockers is clearly visible in the DOM, so that a buggy library that leaves
> a paint blocker active is more noticeable.

Sold!

/ Jonas

James Burke

unread,
Aug 4, 2015, 3:10:11 PM8/4/15
to Bobby Holley, James Graham, dev-pl...@lists.mozilla.org, Jonas Sicking
If the meta tag, or whatever the toggle becomes, is set, then I expect
if the page's JS asks for a DOM element's box properties, it will get
values like 0 for sizes, since I believe the goal is to avoid the
browser doing extra work until the page's JS got everything set up.

If that is the case, should there be a promise API for knowing when
the first layout and rendering has occurred so that the page's JS can
then ask for element box properties to get accurate values?

James

Bobby Holley

unread,
Aug 4, 2015, 4:53:01 PM8/4/15
to James Burke, James Graham, dev-pl...@lists.mozilla.org, Jonas Sicking
We could fire an event if that seems necessary. A Promise API is overkill
and inconsistent with the way other stuff like this works.

James Burke

unread,
Aug 4, 2015, 6:35:46 PM8/4/15
to Bobby Holley, James Graham, dev-pl...@lists.mozilla.org, Jonas Sicking
An event implies the page's JS to scan to see if there are any meta
tag toggles in play, to make sure the code did not miss the event.

At some point APIs that are just about one and done async operations,
like DOMContentLoaded and this one, seem to make sense to expose via a
promise API[1] to avoid the "did I miss the one event that ever fires
for this condition, check a property and if not set, bind an event
listener" pattern.

But if an event is better in this case to leverage existing code
paths/idioms, so be it.

James

[1] https://www.w3.org/2001/tag/doc/promises-guide

Zibi Braniecki

unread,
Aug 4, 2015, 6:51:54 PM8/4/15
to
I'm not sure if the multiple-<meta> solution is going to be really working well.

From the perspective of a gaia app developer that means that he has to inject manually a new <meta> for every library he wants to use.

That feels weird. I would rather expect a single <meta> that app controls fully, sort of a master light switch.

Then, each library would report to the app when they're done. It could look like this:

var readyPromises = [
L10n.init(),
Battery.init(),
Wifi.init(),
MainUI.init()
];

Promise.all(readyPromises).then(() => {
document.head.removeChild(lightSwitchElement);
});

This way library is not deciding if it's blocking displaying, it's the app author who decides if he wants to prevent displaying until some meta is done.

===

Wrt. events, I'm on the Promise side over one-time events because the scenario James described as "did I miss?".
So I'd love to have sth like:

document.mozFirstPaint.then();

if we're ok making this meta delay firstPaint.

===

As Wilson suggested, we may also want to add some information on what to display until the page is painted for browser scenarios (like background color etc.) - for gaia scenario I think we'll delay moving the window to foreground until the promise is fulfilled.

zb.

Bobby Holley

unread,
Aug 4, 2015, 7:03:04 PM8/4/15
to Zibi Braniecki, dev-pl...@lists.mozilla.org
On Tue, Aug 4, 2015 at 3:51 PM, Zibi Braniecki <zbigniew....@gmail.com
> wrote:

> I'm not sure if the multiple-<meta> solution is going to be really working
> well.
>
> From the perspective of a gaia app developer that means that he has to
> inject manually a new <meta> for every library he wants to use.
>

No, the developer merely has the _option_ to. The pattern you describe also
works just fine.

Wrt. events, I'm on the Promise side over one-time events because the
> scenario James described as "did I miss?".
>

I'll defer to Anne et al on this one, but I think adding a second pattern
for delivering load notifications is worse than the inconvenience of the
existing pattern.

Anne van Kesteren

unread,
Aug 6, 2015, 3:54:35 AM8/6/15
to James Burke, James Graham, dev-pl...@lists.mozilla.org, Bobby Holley, Jonas Sicking
On Tue, Aug 4, 2015 at 9:10 PM, James Burke <jbu...@mozilla.com> wrote:
> If the meta tag, or whatever the toggle becomes, is set, then I expect
> if the page's JS asks for a DOM element's box properties, it will get
> values like 0 for sizes, since I believe the goal is to avoid the
> browser doing extra work until the page's JS got everything set up.
>
> If that is the case, should there be a promise API for knowing when
> the first layout and rendering has occurred so that the page's JS can
> then ask for element box properties to get accurate values?

That is an interesting point. We haven't really defined in standards
which features force layout. We'd have to do that so we can make them
behave conditionally as we try to provide some control over (first)
layout.


--
https://annevankesteren.nl/

Anne van Kesteren

unread,
Aug 6, 2015, 3:58:06 AM8/6/15
to Bobby Holley, dev-pl...@lists.mozilla.org, Zibi Braniecki
On Wed, Aug 5, 2015 at 1:02 AM, Bobby Holley <bobby...@gmail.com> wrote:
> I'll defer to Anne et al on this one, but I think adding a second pattern
> for delivering load notifications is worse than the inconvenience of the
> existing pattern.

We will be adding document.loaded, <script>.loaded, and such somewhat
soonish to HTML so you can inspect states with promises rather than
having to register events. Promises are a much more robust and simpler
way to convey this kind of thing.


--
https://annevankesteren.nl/

Jonas Sicking

unread,
Aug 6, 2015, 3:59:19 AM8/6/15
to Anne van Kesteren, James Graham, James Burke, dev-pl...@lists.mozilla.org, Bobby Holley
Lots of features force layout. Accessing any layout related properties
like .offsetTop or .getComputedStyle() force a layout.

Having an API which provides a callback when layout happens would be
nice, but given how long that has been debated with little progress,
we shouldn't block on that.

A simple solution here would be to simply use MutationObservers to
detect when the last <meta> is removed. Any time that layout
properties are queried after that they could behave like they
currently do, i.e. force a synchronous layout.

If we want to we can provide syntax sugar which makes it easier to
detect when the last <meta> is removed. But we should relate that to
when the DOM mutation happens and not when screen rendering or layout
happens.

/ Jonas

Anne van Kesteren

unread,
Aug 6, 2015, 4:07:48 AM8/6/15
to Jonas Sicking, James Graham, James Burke, dev-pl...@lists.mozilla.org, Bobby Holley
On Thu, Aug 6, 2015 at 9:58 AM, Jonas Sicking <jo...@sicking.cc> wrote:
> Lots of features force layout. Accessing any layout related properties
> like .offsetTop or .getComputedStyle() force a layout.

Yes. dglazkov has a library that enumerates the full set. CSSOM should
just define it.


> Having an API which provides a callback when layout happens would be
> nice, but given how long that has been debated with little progress,
> we shouldn't block on that.

Has it? Hmm.


> A simple solution here would be to simply use MutationObservers to
> detect when the last <meta> is removed. Any time that layout
> properties are queried after that they could behave like they
> currently do, i.e. force a synchronous layout.

Right, but we also need to define how they behave otherwise.


> If we want to we can provide syntax sugar which makes it easier to
> detect when the last <meta> is removed. But we should relate that to
> when the DOM mutation happens and not when screen rendering or layout
> happens.

Sure.

I think at this point it would be nice if we reached out to other
browsers to see if they have any thoughts on this kind of API. James,
would you be willing to email either public-...@w3.org or
wha...@whatwg.org?


--
https://annevankesteren.nl/

Jonas Sicking

unread,
Aug 6, 2015, 4:10:06 AM8/6/15
to Anne van Kesteren, James Graham, James Burke, dev-pl...@lists.mozilla.org, Bobby Holley
On Thu, Aug 6, 2015 at 1:07 AM, Anne van Kesteren <ann...@annevk.nl> wrote:
>> A simple solution here would be to simply use MutationObservers to
>> detect when the last <meta> is removed. Any time that layout
>> properties are queried after that they could behave like they
>> currently do, i.e. force a synchronous layout.
>
> Right, but we also need to define how they behave otherwise.

Agreed. Would it work to define that they behave like inside of a
display:none layout tree? Or will that still force some cascade
calculations to happen?

/ Jonas

Anne van Kesteren

unread,
Aug 6, 2015, 5:12:13 AM8/6/15
to Jonas Sicking, James Graham, James Burke, dev-pl...@lists.mozilla.org, Bobby Holley
On Thu, Aug 6, 2015 at 10:09 AM, Jonas Sicking <jo...@sicking.cc> wrote:
> Agreed. Would it work to define that they behave like inside of a
> display:none layout tree? Or will that still force some cascade
> calculations to happen?

That might actually be sufficient for now, yes.


--
https://annevankesteren.nl/

James Burke

unread,
Aug 11, 2015, 8:17:22 PM8/11/15
to Anne van Kesteren, James Graham, dev-pl...@lists.mozilla.org, Jonas Sicking, Bobby Holley
On Thu, Aug 6, 2015 at 1:07 AM, Anne van Kesteren <ann...@annevk.nl> wrote:
> I think at this point it would be nice if we reached out to other
> browsers to see if they have any thoughts on this kind of API. James,
> would you be willing to email either public-...@w3.org or
> wha...@whatwg.org?

First, given a suggestion earlier in the thread, I tried an app
experiment and did some profile.sh captures to make sure we can
identify how much work could be saved, if any, with a new API.

I used this sample app:

https://github.com/jrburke/fxos-startup-test

There are three variations mentioned in the README, each with a
profile.sh capture "Profile" link:

1) The content in a template tag that is only shown once the view JS is ready.
2) Builds on the first one, but uses a CSS class that has display:
none on the <body> tag.
3) Builds on the first one, but uses display:none on the <html> tag.

More details in the README.

The way the app is set up mirrors the general style I can see working
with a custom element-backed view approach for an app, so hopefully
close to a real world test.

It does not include l10n.js localization work, but I was hoping that
could be done on the view after the template importNode but before it
is placed in the document. Maybe the document mutation observeration
that l10n.js does could cause another layout pass, but if no extra
layout gains with these captures can be found, maybe we look at an
approach with the l10n.js where the mutation observers would only be
activated after the initial async view insertion.

I am still very slow at analyzing the profile captures, so I do not
have any conclusions to draw yet. I appreciate it if others more
conversant with those kind of captures could point out things that are
weird in them, if it even makes sense to pursue new APIs at this
point, or if one of the above approaches is enough.

If there are other variations I should try, let me know and I will add them.

James

Julien Wajsberg

unread,
Aug 12, 2015, 11:48:03 AM8/12/15
to dev-pl...@lists.mozilla.org
Le 04/08/2015 21:10, James Burke a écrit :
> On Tue, Aug 4, 2015 at 10:06 AM, Bobby Holley <bobby...@gmail.com> wrote:
>> How about a scheme in which there can be N such <meta> elements, and the
>> painting only happens when all of them are gone (or some timeout occurs)?
>> That solve the common case that Jonas is talking about, and allows
>> libraries to insert their own paint blocker into <head> if they really want
>> to block painting? The a nice side-bonus of this scheme is that the
>> existence of blockers is clearly visible in the DOM, so that a buggy
>> library that leaves a paint blocker active is more noticeable.
> If the meta tag, or whatever the toggle becomes, is set, then I expect
> if the page's JS asks for a DOM element's box properties, it will get
> values like 0 for sizes, since I believe the goal is to avoid the
> browser doing extra work until the page's JS got everything set up.
>
> If that is the case, should there be a promise API for knowing when
> the first layout and rendering has occurred so that the page's JS can
> then ask for element box properties to get accurate values?
>



If I can add a little more bit of information: in the gaia-header
component we use in Gaia, we need to query measurements so that we know
how much space we have to display the title, and size its font
appropriately. We had to add some code so that an app can give the
measurement (when it's static) instead of querying them so that we don't
do sync reflows at app startup (that was bug 1112131).

For sure having a promise API for this would have been really helpful.

--
Julien

signature.asc

James Burke

unread,
Aug 14, 2015, 6:59:23 PM8/14/15
to Anne van Kesteren, James Graham, dev-pl...@lists.mozilla.org, Jonas Sicking, Bobby Holley
On Tue, Aug 11, 2015 at 5:17 PM, James Burke <jbu...@mozilla.com> wrote:
> https://github.com/jrburke/fxos-startup-test
>
> There are three variations mentioned in the README, each with a
> profile.sh capture "Profile" link:

I did a pass at the "Regular" profile and put the notes here:
https://github.com/jrburke/fxos-startup-test#profile-notes

and duplicated below for ease of reference.

In short, it seems like an approach like the one used in the test app,
with a transparent background and a template element for the body
content, seemed to avoid any sizable layout or rendering work during
initial page loading and the point where the app JS constructs the
view.

So, seems like we can hold off on any new browser APIs for now, and
use app-level constructs to group changes that might trigger layout
before insertion in the DOM. I welcome other people's inspection of
the profile though. Perhaps I did not capture all the relevant info.

The b2g/gaia code around launching an app has changed since last doing
a profile like this (at least a year ago), so those changes and using
the app approach in the test app seem to be sufficient for now. It
might be nice to reduce some other startup costs but those seem to be
more in the realm of gaia's control.

---

208030ms is the firstLoadURI marker, so going from that marker as the
start point. Dropping the **208** prefix for the numbers to help make
it easier to see the relative differences.

* **Start**: 030 - firstLoadURI
* **End**: 434 - The JS in startup.js that sets up the view. Layouts
after this point are expected, not part of this test. The goal is to
find savings between firstLoadURI and the startup.js point.

Timeline:

* 034-045 - 11ms: getAppInfo @ AppsService.js:110
* 058-223 - 165ms: epoll_wait on Content row, the GPU row has around
notable 8 notable Composite entries, each around 4ms, some very small
(less than 1ms) Composite entries too. Hypothesis: related to the app
icon zoom in effect when tapping on an app icon from the home screen.
* 239-284 - 45ms: Some script work relatied to user customizations and CSP:
* this.UserCustomizations.observe() @ UserCustomizations.jsm:297
* getCSPBYLocalId() and getAppBYLocalId(), both in AppsService.js
* 297-362 - 65ms: nsInputStreamPump:OnStateStop: some sort of IO?
* 366-389 - 23ms: RunScript related to
BrowserElementChild.prototype._metaChangedHandler @
BrowserElementChildPreload.js:562.
* 389-433 - some IO work/evaluation of cards-message-list.js, a script
in the page, and 7ms spent in nsStyleSet:FileRules.
* 434: Start of startup.js view work.

A quicker evaluation of the "display none body" and "display none
html" profiles show they do not perform any faster than the "regular"
one, and have a similar shape between the firstLoadURI and the
startup.js work.

Looking at that profile does not seem to indicate sizable wait time
related to layouts or renders before the app JS constructs the view.

There does not seem to be a need for extra APIs in the browser for
controlling layouts or paints using this approach:

* Set the background-color for the body to be transparent.
* The body content consists of a `<template>` element with the initial
content. It can include custom elements, but they are inert given the
`<template>` usage.
* Async load the scripts that will provide the implementation of the
custom elements.
* Once all the elements have been registered, document.importNode the
body template's content, and append to the body.

At this point the content becomes visible, and layouts and reflows
occur. It might be possible to optimize some of that layout work,
although this test is fairly straightforward: some innerHTMLs done in
some custom element createdCallback steps, and no other dynamic JS
work done after that.

---

James

Ehsan Akhgari

unread,
Aug 18, 2015, 9:57:46 AM8/18/15
to Jonas Sicking, Bobby Holley, James Graham, dev-pl...@lists.mozilla.org
On 2015-08-04 3:08 PM, Jonas Sicking wrote:
> On Tue, Aug 4, 2015 at 10:06 AM, Bobby Holley <bobby...@gmail.com> wrote:
>> How about a scheme in which there can be N such <meta> elements, and the
>> painting only happens when all of them are gone (or some timeout occurs)?
>> That solve the common case that Jonas is talking about, and allows libraries
>> to insert their own paint blocker into <head> if they really want to block
>> painting? The a nice side-bonus of this scheme is that the existence of
>> blockers is clearly visible in the DOM, so that a buggy library that leaves
>> a paint blocker active is more noticeable.
>
> Sold!

Sorry for the late response. It seems like we decided to not do
anything here for now, but for future reference, the idea above would be
impossible to feature detect, which may not be ideal. If we decide to
propose something for this in the future, we may want to have a story
for feature detection too.

Cheers,
Ehsan

Bobby Holley

unread,
Aug 18, 2015, 12:36:06 PM8/18/15
to Ehsan Akhgari, James Graham, dev-pl...@lists.mozilla.org, Jonas Sicking
My assumption was that the preferred fallback would be equivalent to the
behavior of the <meta> element were ignored. I guess people might want to
hand-implement their own lazy-loading stuff, but given that the site
"works" without it, most people probably won't.

On Tue, Aug 18, 2015 at 6:57 AM, Ehsan Akhgari <ehsan....@gmail.com>
wrote:

Zibi Braniecki

unread,
Aug 18, 2015, 4:22:03 PM8/18/15
to
On Friday, August 14, 2015 at 3:59:23 PM UTC-7, James Burke wrote:
> There does not seem to be a need for extra APIs in the browser for
> controlling layouts or paints using this approach:

Great work James!

I like that we can play with this approach right now, but I'm wondering if we should still pursue some API to facilitate this behavior for the Web.

My concern here is that if we don't, we're basically saying that the right way to write webapps, is to put their content in a template and then inject the template into body when we're done with startup JS.

That feels like a dirty hack, not sure how accessible it is, and it will literally do nothing in a scenario of any JS error.

The API, even as a sugar coating on top of the heuristic you described, would not only solve the problems but also enable us to provide better UX for error case scenarios (your APP did not load properly, restart?) and open up possibilities for the engine to optimize for it (maybe HTML/CSS parsing should happen in parallel with init JS?).

zb.

James Burke

unread,
Aug 18, 2015, 5:53:51 PM8/18/15
to Zibi Braniecki, Mozilla
On Tue, Aug 18, 2015 at 1:22 PM, Zibi Braniecki
<zbigniew....@gmail.com> wrote:
> My concern here is that if we don't, we're basically saying that the right way to write webapps, is to put their content in a template and then inject the template into body when we're done with startup JS.

There are other approaches too, I expect apps that use an mvc layer
with templating (not the template tag), could decide not to use the
<template> tag approach, just leave the body empty until JS injects
the content.

> That feels like a dirty hack, not sure how accessible it is, and it will literally do nothing in a scenario of any JS error.

With web components, but even with other MVC systems (react or ember
components), or with service workers, we are saying we need app JS to
generate views. When the app gets to handle the views it also needs to
build its own error fallbacks. I think it is just good app practice to
know how to handle errors.

I would not be sure what platform API makes sense to recommend either,
particularly given the performance captures, where it is unclear what
benefit those APIs would provide.

You could say the platform has already provided the API: a template
tag and a way to hopefully avoid extra rendering work (or at least the
annoying initial flash of white) with a transparent background color.

James

Boris Zbarsky

unread,
Aug 27, 2015, 10:04:45 AM8/27/15
to
On 8/6/15 4:09 AM, Jonas Sicking wrote:
> Agreed. Would it work to define that they behave like inside of a
> display:none layout tree? Or will that still force some cascade
> calculations to happen?

If you getComputedStyle then you'll still end up doing style computation
in display:none subtrees. Other APIs will short-circuit pretty quickly.

-Boris

vnic...@mozilla.com

unread,
Oct 7, 2015, 9:07:33 AM10/7/15
to
I'm kind of late on the thread...

While James's solution may work I don't think this is exactly what we want.
My understanding of why the current solution work is:
1. The background-color of the page is retrieved when the load event happens at http://mxr.mozilla.org/mozilla-central/source/dom/browser-element/BrowserElementChildPreload.js#1897 and forwarded to the parent process to use it as a background-color for the <iframe mozbrowser> (otherwise it defaults to a white background).

2. The cover is removed when the load event happens. At the same time the background is set.

My questions with this solution are:
1. Do we really want to allow transparent color for a webpage to show what is displayed underneath by the system app ?
On Firefox there is always a default bgcolor (which is retrieved here afaik: http://mxr.mozilla.org/mozilla-central/source/layout/base/nsPresContext.cpp#623)

2. The background-color is defined when the load event happens:
It likely work for app that loads under the 250ms allowed by nglayout.initialpaint.delay but it may fail if the app takes longer than this to load its dependencies (js, css, locales, images, etc..). So it seems a bit racy to me.
I guess the system app can start the iframe with a transparent background to get rid of the race, but then it may look weird for apps that expect a default background color underneath.

Also I would like to have a more unified solution with what Chromium is doing for webapps. Which is, afaik, removing the cover on the first non-empty paint.
See https://codereview.chromium.org/306823002/ and https://groups.google.com/a/chromium.org/forum/#!msg/apps-dev/y39qqrqoxjs/o6lb7utaEoEJ


So what I would like to do in bug 1211853 is:
1. There is no paint unless there is something to paint. While it can be tricky to know if there is something to paint, a simple such as: does the <html> element has a frame and it is visible (not visibiliy: hidden) ?
If not nothing is painted on the screen until there is something to paint.

This is a pretty simple API. Nothing is painted, because there is nothing to paint.

2. Once painting has happened, dispatch a mozfirstpaint event to the page. This way the page can be optimize to quickly display something to the screen and continue its work once something has been painted (or at least once the platform has tried to paint it).




On Thursday, July 30, 2015 at 10:20:35 PM UTC+2, James Burke wrote:
> There are some forces at play in a web app that point to wanting to delay
> layout and rendering until a web app gives a signal that it should start:
>
> * ECMAScript modules, and even developer constructed JS module systems
> today, rely on async loading of scripts.
>
> * Custom elements need their JS registered with the browser before they are
> fully useful.
>
> * Apps can have dependencies on async IDB operations to know what UI to
> first show. For instance, if the user does not have a saved account, show
> the sign in view instead of the app data view.
>
> * We want fast app startups in B2G/Gaia. Typically we lose
> layout/render/paint time while we wait for these async mechanisms to
> finish, and the paints are not useful for the user in the meantime.
>
> In addition, there is a possibility that custom elements may take a path of
> synchronous construction with no later upgrades, which means the JS for the
> custom element needs to be registered before any custom element is used in
> the DOM.
>
> A similar case surfaced a while back in the context of B2G, and at the time
> I filed bug 863499[2], which focused on a document.mozDelayLoadEvent /
> document.mozStopDelayingLoadEvent JS API around controlling the load event
> firing.
>
> At that time, the concern was about losing times to wasted renders and the
> effects on screen shots.
>
> However, I believe the main concern now is getting enough JS and app data
> loaded to allow layout to be effective in fewer passes than strictly about
> the final render and load event. So maybe the API should be more about
> delaying layout than about the load event?
>
> In talking to Wilson Page, he mentioned something like a
> document.pauseLayout() document.resumeLayout(), not sure if there are
> existing thoughts around that.
>
> If that seemed workable, maybe also a <html mozPauseLayout> type of
> attribute, so the browser knows as soon as possible to pause its work,
> instead of relying on a JS API.
>
> For Gaia apps, we use a CSP policy that does not allow inline scripts, so
> the attribute on a tag is more appealing for that reason. A nonced script
> might be a workable alternative for the CSP case, if an attribute was too
> much of a stretch.
>
> Happy to hear about any suggestions for the general goal,
> James
>
> [1] Service workers help a bit here, but do not help the other aync forces.
> [2] https://bugzilla.mozilla.org/show_bug.cgi?id=863499

vnic...@mozilla.com

unread,
Oct 7, 2015, 9:18:00 AM10/7/15
to
I also forgot to say that the proposed solution does not help for cases like bug 1199674 afaict.

Mounir Lamouri

unread,
Oct 8, 2015, 12:11:35 PM10/8/15
to dev-pl...@lists.mozilla.org
Note that Chrome 46 has a way to work around the white screen while a
page load using a new property in the Manifest. If a website added to
the homescreen on Chrome Android has a background_color information, it
will be used while the page loads. After Chrome gets the first paint
following a non-empty layout, it will remove that plain colour and
switch to whatever the page has ready. It allows websites to be
constructed as websites and not rely on that splashscreen feature that
might or might not be present (given the UA and the current context) and
also keep the principle of quick first paint.

Would using a similar system (ie. background_color from the Manifest)
help you here?

-- Mounir

On Wed, 7 Oct 2015, at 14:17, vnic...@mozilla.com wrote:
> I also forgot to say that the proposed solution does not help for cases
> like bug 1199674 afaict.

James Burke

unread,
Oct 8, 2015, 5:13:25 PM10/8/15
to Mounir Lamouri, Mozilla
On Thu, Oct 8, 2015 at 9:10 AM, Mounir Lamouri <mou...@lamouri.fr> wrote:
> Note that Chrome 46 has a way to work around the white screen while a
> page load using a new property in the Manifest. If a website added to
> the homescreen on Chrome Android has a background_color information, it
> will be used while the page loads. After Chrome gets the first paint
> following a non-empty layout, it will remove that plain colour and
> switch to whatever the page has ready. It allows websites to be
> constructed as websites and not rely on that splashscreen feature that
> might or might not be present (given the UA and the current context) and
> also keep the principle of quick first paint.
>
> Would using a similar system (ie. background_color from the Manifest)
> help you here?

I am unsure of the needs related to bug 1199674, but on the manifest
background color: if it is a color that is set in the manifest, I find
that marginally more useful than a flash of white before painting.

What if the UI has different start colors? It would be a noticeable
abrupt transition. For email, if no accounts configured, the
background is a light gray. If accounts are configured, the header is
an orange but the bulk of the content area uses a white color.

To me, the use of a solid color, particularly if white, just looks
like the typical browser new tab white loading screen. I am purposely
trying to avoid that in email. I liked that Firefox OS uses the icon
as part of the app launch transition, it felt different than a single
color paint. Go from startup animation with the app icon to meaningful
content.

James

Vivien Nicolas

unread,
Oct 9, 2015, 11:28:09 AM10/9/15
to Mounir Lamouri, dev-pl...@lists.mozilla.org
On Thu, Oct 8, 2015 at 6:10 PM, Mounir Lamouri <mou...@lamouri.fr> wrote:

> Note that Chrome 46 has a way to work around the white screen while a
> page load using a new property in the Manifest. If a website added to
> the homescreen on Chrome Android has a background_color information, it
> will be used while the page loads. After Chrome gets the first paint
> following a non-empty layout, it will remove that plain colour and
> switch to whatever the page has ready. It allows websites to be
> constructed as websites and not rely on that splashscreen feature that
> might or might not be present (given the UA and the current context) and
> also keep the principle of quick first paint.
>

> Would using a similar system (ie. background_color from the Manifest)
> help you here?
>


I will be happy to use the background_color field in the manifest. It will
likely help web app pinned to the homescreen.
I also think it will be a great idea to use it to replace the static black
color that is displayed before applications are launched and try to unify
the experience between installed apps and pinned apps.

However while I think background_color is useful, the white flash we are
trying to address here is between the splash screen and the app content
beeing loaded. I think, but I may be wrong, that we don't want to have a 3
steps startup with:
1. Black splashscreen with icon
2. plain background_color instead of a white flash
3. App content beeing displayed when ready.

I guess 1. and 2. can be merged.

Now the issue, if my understanding is correct, Gecko does not have the
notion of firstpaint after a non-empty layout. Which means even if 1. and
2. are merged we can end up in a situation where you have:
1./2. background_color with/without icon
3. white flash
4. App content beeing displayed when ready.

So basically what I want to add in bug 1211853 (first attachement) is (a
very simple) mechanism to not paint until there is something to paint. And
from here provide a mechanism for web app to control when first paint
happens without enforcing them to be built a specific way.

As James mentioned, background_color may also be tricky to used for
applications with dynamic first page. For instance if you want to have a
setup page with a different background color than the rest of your
application. That said I still believe it can be useful for the vast
majority of apps.

An other constraints for application with multi-steps startup is to display
something as quick as possible to the user and continue their execution
after first paint. As of today there is no way (at least in Gecko, dunno
for Chrome) to know when the UA has painted something on the screen. I
would like to introduce a (moz)firstpaint event so app authors can optimize
their app to quicly show something on the screen, then wait for the UA to
paint, and then continue their execution.

Vivien.


>
> -- Mounir
>
> On Wed, 7 Oct 2015, at 14:17, vnic...@mozilla.com wrote:
> > I also forgot to say that the proposed solution does not help for cases
> > like bug 1199674 afaict.

Mounir Lamouri

unread,
Oct 9, 2015, 1:51:54 PM10/9/15
to Vivien Nicolas, dev-pl...@lists.mozilla.org
Sorry for misunderstanding.

> So basically what I want to add in bug 1211853 (first attachement) is (a
> very simple) mechanism to not paint until there is something to paint.
> And
> from here provide a mechanism for web app to control when first paint
> happens without enforcing them to be built a specific way.

Did you look into firing the event after there is a non-empty layout or
does that come to the same thing as what your patch is doing? Also, it
seems unfortunate to have applications hacking around the first paint.
As far as speed feeling goes, they would win to show something as soon
as possible and handle any post-first paint loading themselves.

> An other constraints for application with multi-steps startup is to
> display
> something as quick as possible to the user and continue their execution
> after first paint. As of today there is no way (at least in Gecko, dunno
> for Chrome) to know when the UA has painted something on the screen. I
> would like to introduce a (moz)firstpaint event so app authors can
> optimize
> their app to quicly show something on the screen, then wait for the UA to
> paint, and then continue their execution.

I was talking about a firstpaint even to some Chrome folks earlier this
week and I have a TODO to talk with some other folks next week when they
will be back from their holidays. So far, the feedback on this idea was
fairly positive but I need to make sure there isn't something obvious
I'm missing.

-- Mounir

zbran...@mozilla.com

unread,
Oct 9, 2015, 9:02:09 PM10/9/15
to
On Friday, October 9, 2015 at 10:51:54 AM UTC-7, Mounir Lamouri wrote:
> As far as speed feeling goes, they would win to show something as soon
> as possible and handle any post-first paint loading themselves.

That is unfortunately not consistent with my experience. People tend to perceive visible progressive as much slower than delayed first-paint in most scenarios.

On top of that, it is perceived as a really_bad_ux.

That means that while Gecko is trying to do what you said - paint as soon as possible and handle everything later, Firefox OS apps are trying to to exactly the opposite - squeeze as much startup JS logic as possible before firstPaint.

Because they cannot control it, it is a condition race between two heuristics which includes lots of dirty tricks, unfair punches and other nasty, nasty stuff.

What we are trying to get is control over firstPaint for apps that want to control when first paint is executed. That would remove the condition race and actually free Gecko from the burden of trying to analyze when to start painting.

zb.

Mounir Lamouri

unread,
Oct 10, 2015, 7:28:30 AM10/10/15
to zbran...@mozilla.com, dev-pl...@lists.mozilla.org
On Sat, 10 Oct 2015, at 02:02, zbran...@mozilla.com wrote:
> On Friday, October 9, 2015 at 10:51:54 AM UTC-7, Mounir Lamouri wrote:
> > As far as speed feeling goes, they would win to show something as soon
> > as possible and handle any post-first paint loading themselves.
>
> That is unfortunately not consistent with my experience. People tend to
> perceive visible progressive as much slower than delayed first-paint in
> most scenarios.
>
> On top of that, it is perceived as a really_bad_ux.

I don't think I agree but I don't mean to discuss Firefox OS product
decisions.

-- Mounir

Vivien Nicolas

unread,
Oct 10, 2015, 8:15:05 AM10/10/15
to Mounir Lamouri, zbran...@mozilla.com, dev-pl...@lists.mozilla.org
There should be an answer in the middle. Showing something as soon as
possible is best iif it not a half baked part of the UI.
So for example showing the navigation chrome first is good, if it is not
rebuilding right after. Then showing the app content.

But I'm not convinced any of us is the best to answer this UX question and
this is likely the subject of a separate thread.

On Sat, Oct 10, 2015 at 1:27 PM, Mounir Lamouri <mou...@lamouri.fr> wrote:

> On Sat, 10 Oct 2015, at 02:02, zbran...@mozilla.com wrote:
> > On Friday, October 9, 2015 at 10:51:54 AM UTC-7, Mounir Lamouri wrote:
> > > As far as speed feeling goes, they would win to show something as soon
> > > as possible and handle any post-first paint loading themselves.
> >
> > That is unfortunately not consistent with my experience. People tend to
> > perceive visible progressive as much slower than delayed first-paint in
> > most scenarios.
> >
> > On top of that, it is perceived as a really_bad_ux.
>
> I don't think I agree but I don't mean to discuss Firefox OS product
> decisions.
>
> -- Mounir

zbran...@mozilla.com

unread,
Oct 11, 2015, 12:26:48 AM10/11/15
to
I don't think it's specific to Firefox OS. FOUC is a pretty well researched problem and we have spent a lot of time designing standards to limit the risk of them happening.

The problem is that all we take into account when building anti-FOUC heuristics is HTML+CSS, while in the modern Web Apps, JS is part of the bootstrap process.

Of course a lot of things still apply, and we still aim at minimizing the amount of JS necessary during bootstrap but the state of art is that we do need and we will need some minimal JS executed before firstPaint.

One other reason it is necessary is that compared to web pages, there is no static content in HTML. Hell, there is no content at all.
What is the value for the user to see Music index.html file [0] before JS kicks in?
Literally zero.

And if JS breaks? The app will not work. At all.

While with web pages you can salvage and aim at displaying the content, even without JS, without CSS, because the goal is an article, with Web App, the goal is the "Play" button, the "New SMS" button etc. and those will not work without JS.

So the first valuable thing to see is after HTML+JS provides chrome of the app and CSS provides styling.

And it does not work well if this chrome flashes as it relayouts while JS finalizes it after firstPaint.

As Vivien said, yeah, of course we want to show something as soon as possible, minimal useful Chrome and let above-the-fold content load later - that's precisely how we designed our responsive guidelines [1], and we're incentivizing developers to make bring minimal UI early.

But that still requires JS. And currently we don't take it into account when discussing FOUCs, so platform races to paint while JS races to finish preparing chrome.

The result is two fold - one are FOUCs if we are unsuccessful. The other, if we are successful, is bad code. That's where we get synchronous <script/> tag injected at the end of <body/> to prevent FOUCs. That's where we get "document.write", and synchronous XHRs. All there to win the race with Gecko.

I see a huge value for the quality of the Web App Stack in removing the whole notion of this race. And Vivien's proposal seems to do just that with minimal invasion.

zb.

[0] https://github.com/mozilla-b2g/gaia/blob/master/apps/music/index.html
[1]https://developer.mozilla.org/en-US/Apps/Build/Performance/Firefox_OS_app_responsiveness_guidelines

Jonas Sicking

unread,
Oct 16, 2015, 4:07:59 AM10/16/15
to Zbigniew Braniecki, dev-platform
On Sat, Oct 10, 2015 at 9:26 PM, <zbran...@mozilla.com> wrote:
> On Saturday, October 10, 2015 at 4:28:30 AM UTC-7, Mounir Lamouri wrote:
>> On Sat, 10 Oct 2015, at 02:02, zbran...@mozilla.com wrote:
>> > On Friday, October 9, 2015 at 10:51:54 AM UTC-7, Mounir Lamouri wrote:
>> > > As far as speed feeling goes, they would win to show something as soon
>> > > as possible and handle any post-first paint loading themselves.
>> >
>> > That is unfortunately not consistent with my experience. People tend to
>> > perceive visible progressive as much slower than delayed first-paint in
>> > most scenarios.
>> >
>> > On top of that, it is perceived as a really_bad_ux.
>>
>> I don't think I agree but I don't mean to discuss Firefox OS product
>> decisions.
>
> I don't think it's specific to Firefox OS. FOUC is a pretty well researched problem and we have spent a lot of time designing standards to limit the risk of them happening.
>
> The problem is that all we take into account when building anti-FOUC heuristics is HTML+CSS, while in the modern Web Apps, JS is part of the bootstrap process.

I agree with a lot of the above. I would recommend reaching out to
Martin Best and getting this on his backlog of items that we need in
order to create more beautiful webapps.

/ Jonas

Vivien Nicolas

unread,
Oct 16, 2015, 6:29:34 AM10/16/15
to Mounir Lamouri, dev-pl...@lists.mozilla.org
On Thu, Oct 8, 2015 at 6:10 PM, Mounir Lamouri <mou...@lamouri.fr> wrote:

> Note that Chrome 46 has a way to work around the white screen while a
> page load using a new property in the Manifest. If a website added to
> the homescreen on Chrome Android has a background_color information, it
> will be used while the page loads. After Chrome gets the first paint
> following a non-empty layout, it will remove that plain colour and
> switch to whatever the page has ready. It allows websites to be
> constructed as websites and not rely on that splashscreen feature that
> might or might not be present (given the UA and the current context) and
> also keep the principle of quick first paint.
>
> Would using a similar system (ie. background_color from the Manifest)
> help you here?
>

For what it worth, I have started to play with background_color in bug
1215077.

It looks cool, and I really like it. But because of the FirefoxOS UX which
displays an icon on top of the defined background color, it is not enough
by itself for most apps.

For example with the calendar app, we will end up with:
- Orange background with Calendar icon in the middle
- Orange background from the app without an icon (the app can likely add
that but it starts to become very UA specific)
- App content.

But generally it is nice and I would like to support that on FirefoxOS.

Vivien Nicolas

unread,
Nov 12, 2015, 10:39:25 AM11/12/15
to dev-pl...@lists.mozilla.org
Is there any concerns about the solution I'm proposing or should I move
forward ?

On Fri, Oct 16, 2015 at 12:29 PM, Vivien Nicolas <vnic...@mozilla.com>
wrote:
0 new messages