ember-fastboot / fastboot-app-server

A production-ready app server for running Ember FastBoot apps
140 stars 74 forks source link

HTTP/2 Server push support #91

Open janwerkhoven opened 5 years ago

janwerkhoven commented 5 years ago

I believe Fastboot could be serving assets even faster if it were leverage HTTP/2 sever push.

Background

Server push, which is defined in the HTTP/2 specification, allows a server to pre‑emptively push resources to a remote client, anticipating that the client may soon request those resources.

That's perfect for an Ember app because we always have 4 predictable files that need to be loaded:

ember-app.js ember-app.css vendor.js vendor.css

The idea

The idea is to push these 4 files along with the index.html to the client instead of waiting for index.html to land, then fire 4 request, then wait for those requests to land.

Nginx

In Nginx you can specify files to push with http2_push:

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;

  server_name foo-app.com;

  location / {
    # Pass requests to Fastboot
    proxy_pass http://0.0.0.0:8000;

    # Leverage HTTP/2 server push
    http2_push /assets/lmpa-interflux-com-dd56fc256fbb789e812d33c1ca0a2cdb.css;
    http2_push /assets/outdatedbrowser.min-9131a0c1fc3c983e7770d2a8978ffbb4.css;
    http2_push /assets/lmpa-interflux-com-e99f983e06bc16d6677864b25e1f0e4f.js;
    http2_push /assets/vendor-743626574e3ff471643e8686d1be9635.js;
    http2_push /assets/outdatedbrowser.min-29fcaeff82d07e196a8d053f0601fcc4.js;
    http2_push /assets/fonts/lato/subset-Lato-Regular.woff2;
    http2_push /assets/fonts/lato/subset-Lato-Bold.woff2;
    http2_push /assets/fonts/lato/subset-Lato-Black.woff2;
  }
}

Pre-emptively pushing these files increase my project's load times from:

screen shot 2018-10-27 at 00 30 21 screen shot 2018-10-27 at 00 30 29

To:

screen shot 2018-10-27 at 00 22 27 screen shot 2018-10-27 at 00 22 19

Before:

screen shot 2018-10-27 at 00 33 39

After:

screen shot 2018-10-27 at 00 33 31

That's amazing! 🌮

Do give me more! 🙏

Caveat

The Ember files are fingerprinted... Which is great for busting caches when deploying new fixes, but that also breaks having set static http2_push paths.

Bad solution

Stop fingerprinting files in order to leverage static http2_push. 🔥

Is bad because busting caches is arguably more important.

Beter solution

Since NGINX 1.13.9 support was http2_push_preload on; which automatically HTTP/2 server pushes files marked by the Link header.

That means in Nginx setting:

  location / {
    proxy_pass http://0.0.0.0:8000;
    http2_push_preload on;
  }

And having Fastboot somehow add the following response header when fetching index.html:

Link: "</assets/foo-app-e99f983e06bc16d6677864b25e1f0e4f.js>; as=script; rel=preload, </assets/foo-app-e99f983e06bc16d6677864b25e1f0e4f.css>; as=style; rel=preload"

Would preload this JS and CSS file.

Feature request?

  1. Is there a way to add the Link header to each Fastboot responses?

  2. Does Fastboot have an index of the fingerprinted files we can concatenate into the Link header?

mhluska commented 5 years ago

@janwerkhoven this looks awesome. But this project hasn't had any love in 8 months and I've never gotten a response on any PR in over a year. Maybe fork it?

janwerkhoven commented 5 years ago

@mhluska Thanks, I'd love to contribute.

I think I first will have to learn more about Node, Express and Fastboot internals though... 😅

Was hoping someone with experience would point in the right direction.

rynam0 commented 5 years ago

This would be sweeeeeeet.