New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider using Service Workers for faster page loads #69
Comments
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
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#52 • yui/yuicompressor#59 ① https://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
|
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: (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.) |

This is especially relevant when using DCS directly from the address bar. A typical such invocation looks like this:
We should be able to directly do the javascript redirect in the Service Worker, hence shaving 0.5s of wall-clock time off.
The text was updated successfully, but these errors were encountered: