Created
July 6, 2012 08:01
-
-
Save igrigorik/3058839 to your computer and use it in GitHub Desktop.
Example of early head flush on load time
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset=utf-8 /> | |
<title>Hello</title> | |
<link rel="stylesheet" href="styles.css"> | |
</head> | |
<body> | |
Hello World | |
</body> | |
</html> | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'goliath' | |
class Delay < Goliath::API | |
def response(env) | |
case env['REQUEST_PATH'] | |
when /css$/ then | |
# simulate slow (1s delay) stylesheet | |
EM::Synchrony.sleep(1) | |
return [200, {'Content-Type' => 'text/css'}, 'body { color: red }'] | |
else | |
data = File.open('file.html') | |
# flush the HTML head (140 bytes) immediately after the headers | |
# this will allow the preloader to request the stylesheet before | |
# the rest of the page completes | |
EM.add_timer(0.01) do | |
env.chunked_stream_send(data.read(140)) | |
end | |
# flush remainder of document after 1.5s | |
EM.add_timer(1.5) do | |
env.chunked_stream_send(data.read.to_s) | |
env.chunked_stream_close | |
end | |
# flush 200 response immediately | |
chunked_streaming_response(200, {'Content-Type' => 'text/html'}) | |
end | |
end | |
end |
Hi there, in terms of the Jekyll site, wondering if is there an equivalent way to do the flush after the header tag as well, something like Flush the Buffer Early. Thank you.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Yes, it is automatic. The layout gets chunked, and the template main content goes in one single chunk. Basically, each time you switch from hard-coded content to dynamic content in ERB you get a chunk. In a template you can still use a kind of
content_for
helper calledprovide
(the layout communicates with the template via fibers in this case).Server-side support is also interesting. You need a 1.1 proxy, Rails disables streaming if the client sends a 1.0 request because chunked responses are a 1.1 feature. Also, you obviously do not want your reverse proxy to buffer the response as nginx does by default, at the price of... well not having the response rapidly consumed.
Then, the reverse proxy should be able to compress, since you want compression in a production environment. In order to compress, the reverse proxy must dechunk, compress, and chunk again, on the fly.
It is a very interesting topic with many practical gotchas in production environments. When I researched, from the setups I tested this the only combo that worked was Apache + Unicorn, a combo that is indeed not recommended by Unicorn. By "worked" I mean it didn't buffer and was able to compress on the fly.