Consider using Service Workers for faster page loads #69

Closed
stapelberg opened this Issue Jun 28, 2016 · 1 comment

Comments

Projects
None yet
1 participant
@stapelberg
Contributor

stapelberg commented Jun 28, 2016

This is especially relevant when using DCS directly from the address bar. A typical such invocation looks like this:

2016-06-28-083904_2504x1115_scrot

We should be able to directly do the javascript redirect in the Service Worker, hence shaving 0.5s of wall-clock time off.

@stapelberg stapelberg self-assigned this Jul 2, 2016

stapelberg added a commit that referenced this issue Jul 2, 2016

Make dcs-web listen with TLS optionally
This can be used through dcs-localdcs by specifying e.g.
-listen_web_tls=localhost:8443

Having localdcs listen on TLS is useful for testing changes which
require a secure origin (e.g. Service Workers).

related to #69

stapelberg added a commit that referenced this issue Jul 5, 2016

big client refactoring for faster page loads
There are a couple of high-level changes which all contribute to
decreasing the page load time, both for initial page loads and for any
subsequent page loads (with cached assets):

1. Instead of having the /search?q=query endpoint serve a non-javascript
   version with javascript that redirects to /results/query/page_0, the
   response now is used for both non-javascript and javascript: all
   javascript-specific elements are hidden, all non-javascript elements
   are wrapped in <noscript>. This eliminates an entire round-trip for
   all requests that did not use the search form (e.g. requests from the
   URL bar, or people following links).

   The old URL patterns are redirected server-side, i.e. a request to
   /results/query/page_0 results in an HTTP 302 to /search?q=query. This
   keeps old URLs working.

2. All CSS which is required for the initial page rendering is now
   inlined in the responses (see static/critical.css). Previously we
   used to ship both debian.css and debcodesearch.css and let the
   browser apply the directives. critical.css however contains no
   ignored/superseded directives, bringing down the size of the
   stylesheet even more.

3. All further CSS has been moved to non-critical.css, which is loaded
   in a non-blocking way.

4. We are now using the EventSource API¹ instead of WebSockets (for
   browsers which don’t support EventSource, there is a fallback to
   WebSockets). The original motivation to use WebSockets was to
   eliminate the round-trip for submitting the search form. Structuring
   our application like that implied a single-page app.

   With the EventSource API, we no longer use a single-page app design,
   i.e. when submitting the search form, the browser actually navigates
   to /search?q=query. This simplifies the JavaScript code (we no longer
   need to do auto-complete state handling, for example) and makes the
   javascript/non-javascript serving in point 1 easier.

   Conceptually, EventSource and WebSocket are much alike, but
   EventSource is uni-directional. This suits us well, as the only
   message we sent to the server was the search query. With EventSource,
   we just include the query in the EventSource request (e.g.
   /events/query).

   An advantage of the EventSource API is that it supports HTTP2 (which
   WebSockets don’t!). This effectively eliminates the round trip which
   we used to eliminate using WebSockets in HTTP1.

5. The progress bar animation has been changed to not animate the
   background-position property anymore, but rather use the translate
   directive which can be offloaded to the GPU entirely. This results in
   smooth animations which do not slow down the rest of the page while
   scrolling or loading results.

Step 1-3 mean that with the first response being loaded, we immediately
render the progress bar. This typically happens within about 100ms
(excluding network latency), resulting in feedback that feels instant.

In my measurements (with a 100ms latency, 6Mbit/s down, 1Mbit/s up
throttling profile in Chrome), the time to first paint is reduced from
800ms to 30ms when loading a /search?q=query URL (e.g. via the address
bar).

Sending a search query via the query form on the index page is a bit
slower with the new architecture because of the additional round trip
(the request for /search?q=query and then /events/query). This will be
addressed by service workers (see issue #69) which can handle
/search?q=query locally. Let’s be prudent and implement service workers
after the new architecture has been rolled out, though.

We use 2 Polyfills (JavaScript code which backports new functionality to
browsers which don’t support it yet):
• URLSearchParams (for Microsoft Edge):
  https://github.com/WebReflection/url-search-params
• loadCSS (for non-chrome):
  https://github.com/filamentgroup/loadCSS

We had to use 2 workarounds for issues in the minify tooling:
• rspivak/slimit#52yui/yuicompressor#59https://developer.mozilla.org/en-US/docs/Web/API/EventSource
  (which is available in all major browsers except for IE/Edge, see
   http://caniuse.com/#feat=eventsource)

related to #69

@stapelberg stapelberg closed this in 7f31aef Jul 7, 2016

@stapelberg

This comment has been minimized.

Show comment
Hide comment
@stapelberg

stapelberg Jul 7, 2016

Contributor

The time to first paint is now well below 100ms, and the first request that is sent to the network (when Service Workers are active) is to actually fetch the search results — in the ideal case, the results are fetched within the first round trip, making total rendering times of < 200ms a reality:

2016-07-07-094558_1887x1335_scrot

(I’m not sure why the webfont requests are displayed as pending in the above image, the fonts are displayed correctly and should be available locally.)

Contributor

stapelberg commented Jul 7, 2016

The time to first paint is now well below 100ms, and the first request that is sent to the network (when Service Workers are active) is to actually fetch the search results — in the ideal case, the results are fetched within the first round trip, making total rendering times of < 200ms a reality:

2016-07-07-094558_1887x1335_scrot

(I’m not sure why the webfont requests are displayed as pending in the above image, the fonts are displayed correctly and should be available locally.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment