-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathindex.html
45 lines (42 loc) · 14 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<!doctype html><html lang=en><head><meta charset=UTF-8><title>Troubleshooting HTTP Streams | Marko</title><link rel=icon type=image/png sizes=32x32 href=/assets/d78b83f1.png><meta name=viewport content="width=device-width, initial-scale=1"><meta name=description content="Marko is a friendly (and fast!) UI library that makes building web apps fun."><script>
if (window.self !== window.top) {
document.documentElement.classList.add("iframe");
}
</script><script>
const params = new URL(window.location).searchParams;
const uwu = params.has("uwu")
? params.get("uwu") !== "false"
: localStorage.uwu;
if (uwu) {
localStorage.uwu = true;
document.documentElement.className = "uwu";
document.write(
"<style>@import url('https://fonts.googleapis.com/css2?family=Varela+Round&display=swap');html.uwu body{font-family:'Varela Round',sans-serif;}</style>",
);
} else {
delete localStorage.uwu;
}
</script><script src="/assets/121.8cb2904a.js" async></script><script src="/assets/364.f6733859.js" async></script><script src="/assets/991.5eec5c73.js" async></script><link rel="stylesheet" href="/assets/a50c84bf.css"></head><body class=docs><a href="#main" id=skip-link>Skip to main content</a><!--M#s0-1-0-14--><header data-marko-key="@header s0-1-0-14" class=site-header><div class=content><a href="/"><img src=/assets/91bc26e5.svg alt="Marko Home" class=site-logo><img src=/assets/2371441a.png alt="Marko Home" class=site-logo-uwu></a><div class=stuff><nav class=site-menu><a href=/docs/getting-started>Docs</a><a href=/try-online>Try Online</a><a href=https://github.com/marko-js/marko>GitHub</a><!--M^s0-1-0-14-12 s0-1-0-14 12--><link rel=preconnect href=https://GB0QQV5RQM-dsn.algolia.net crossorigin><div data-marko-key="@container s0-1-0-14-12" class=search></div><!--M/--></nav><button data-marko='{"onclick":"toggleMenu s0-1-0-14 false"}' class=menu>☰</button></div></div></header><!--M/--><!--M#s0-1-0-15--><div data-marko-key="@sidebar s0-1-0-15" class=doc-sidebar><button data-marko='{"onclick":"hide s0-1-0-15 false"}' class=close>✕</button><h1>Marko <!--M^s0-1-0-15-9 s0-1-0-15 9--><select data-marko='{"onchange":"switchVersion s0-1-0-15-9 false"}' data-marko-key="@version s0-1-0-15-9"><option value=/v6/docs/setup>next</option><option value=/docs/getting-started selected>5.37.29</option><option value="http://marko-v4.github.io/docs/">4.x</option><option value="http://v3.markojs.com/docs/">3.x</option><option value="http://marko-v2.github.io/docs/">2.x</option></select><!--M/--></h1><ul class=toc-level0><li class=section><a href="/docs/guides-overview/">GUIDES</a></li><li><a href="/docs/installing/">Installing</a></li><li><a href="/docs/getting-started/">Getting started</a></li><li><a href="/docs/conditionals-and-lists/">Conditionals and lists</a></li><li><a href="/docs/custom-tags/">Custom tags</a></li><li><a href="/docs/state/">State</a></li><li><a href="/docs/styles/">Styles</a></li><li><a href="/docs/events/">Events</a></li><li><a href="/docs/body-content/">Body content</a></li><li><a href="/docs/typescript/">TypeScript</a></li><li><a href="/docs/marko-5-upgrade/">Marko 5 upgrade</a></li><li><a class=selected href="/docs/troubleshooting-streaming/">Troubleshooting Streaming</a></li></ul><ul class=toc-level0><li class=section><a href="/docs/tutorials-overview/">TUTORIALS</a></li><li><a href="/docs/color-picker/">Color Picker</a></li></ul><ul class=toc-level0><li class=section><a href="/docs/reference-overview/">REFERENCE</a></li><li><a href="/docs/rendering/">Rendering</a></li><li><a href="/docs/syntax/">Syntax</a></li><li><a href="/docs/core-tags/">Core tags</a></li><li><a href="/docs/class-components/">Class components</a></li><li><a href="/docs/marko-json/">marko.json</a></li><li><a href="/docs/compiler/">Compiler</a></li></ul><ul class=toc-level0><li class=section><a href="/docs/bundler-integrations-overview/">BUNDLER INTEGRATIONS</a></li><li><a href="/docs/vite/">Vite</a></li><li><a href="/docs/webpack/">Webpack</a></li><li><a href="/docs/rollup/">Rollup</a></li><li><a href="/docs/lasso/">Lasso</a></li></ul><ul class=toc-level0><li class=section><a href="/docs/server-integrations-overview/">SERVER INTEGRATIONS</a></li><li><a href="/docs/cloudflare-workers/">Cloudflare Workers</a></li><li><a href="/docs/express/">Express</a></li><li><a href="/docs/fastify/">Fastify</a></li><li><a href="/docs/koa/">Koa</a></li><li><a href="/docs/http/">HTTP</a></li></ul><ul class=toc-level0><li class=section><a href="/docs/tooling-overview/">TOOLING</a></li><li><a href="/docs/editor-plugins/">Editor plugins</a></li></ul><ul class=toc-level0><li class=section><a href="/docs/articles-overview/">ARTICLES</a></li><li><a href="/docs/marko-vs-react/">Marko vs React</a></li><li><a href="/docs/why-is-marko-fast/">Why is Marko Fast</a></li><li><a href="/docs/10-awesome-marko-features/">10 Awesome Marko Features</a></li></ul></div><!--M/--><main id=main tabindex=-1 class=content><div class=doc-layout><div class=doc-container><div class=doc-content><h1 id=troubleshooting-http-streams><a name=troubleshooting-http-streams class=anchor href=#troubleshooting-http-streams><span class=header-link></span></a>Troubleshooting HTTP Streams</h1><p><a href=https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding>The way Marko streams HTML</a> is old and well-supported, but default configurations and assumptions by other software can foil it. This page describes some known culprits that may buffer your Node server’s output HTTP streams.</p><h2 id=reverse-proxiesload-balancers><a name=reverse-proxiesload-balancers class=anchor href=#reverse-proxiesload-balancers><span class=header-link></span></a>Reverse proxies/load balancers</h2><ul><li><p>Turn off proxy buffering, or if you can’t, set the proxy buffer sizes to be reasonably small.</p></li><li><p>Make sure the “upstream” HTTP version is 1.1 or higher; HTTP/1.0 and lower do not support streaming.</p></li><li><p>Some software doesn’t support HTTP/2 or higher “upstream” connections at all or very well — if your Node server uses HTTP/2, you may need to downgrade.</p></li><li><p>Check if “upstream” connections are <code>keep-alive</code>: overhead from closing and reopening connections may delay responses.</p></li><li><p>For typical modern webpage filesizes, the following bullet points probably won’t matter. But if you want to stream <strong>small chunks of data with the lowest latency</strong>, investigate these sources of buffering:</p><ul><li><p>Automatic gzip/brotli compression may have their buffer sizes set too high; you can tune their buffers to be smaller for faster streaming in exchange for slightly worse compression.</p></li><li><p>You can <a href=https://hpbn.co/transport-layer-security-tls/#optimize-tls-record-size>tune HTTPS record sizes for lower latency, as described in High Performance Browser Networking</a>.</p></li><li><p>Turning off MIME sniffing with <a href=https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options>the <code>X-Content-Type-Options</code></a> header eliminates browser buffering at the very beginning of HTTP responses</p></li></ul></li></ul><h3 id=nginx><a name=nginx class=anchor href=#nginx><span class=header-link></span></a>NGiNX</h3><p>Most of NGiNX’s relevant parameters are inside <a href=https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering>its builtin <code>http_proxy</code> module</a>:</p><script>if(localStorage.getItem('markojs-website:syntax') === 'concise'){document.body.classList.add('concise')}</script><pre class=highlighted style=color:#D0D0E0;background-color:#202034>proxy_http_version 1.1; # 1.0 by default
proxy_buffering off; # on by default
</pre><h3 id=apache><a name=apache class=anchor href=#apache><span class=header-link></span></a>Apache</h3><p>Apache’s default configuration works fine with streaming, but your host may have it configured differently. The relevant Apache configuration is inside <a href=https://httpd.apache.org/docs/2.4/mod/mod_proxy.html>its <code>mod_proxy</code> and <code>mod_proxy_*</code> modules</a> and their <a href=https://httpd.apache.org/docs/2.4/env.html>associated environment variables</a>.</p><h2 id=cdns><a name=cdns class=anchor href=#cdns><span class=header-link></span></a>CDNs</h2><p>Content Delivery Networks (CDNs) consider efficient streaming one of their best features, but it may be off by default or if certain features are enabled.</p><ul><li><p>For Fastly or another provider that uses VCL configuration, check <a href="https://developer.fastly.com/reference/vcl/variables/backend-response/beresp-do-stream/">if backend responses have <code>beresp.do_stream = true</code> set</a>.</p></li><li><p>Some <a href=https://community.akamai.com/customers/s/question/0D50f00006n975d/enabling-chunked-transfer-encoding-responses>Akamai features designed to mitigate slow backends can ironically slow down fast chunked responses</a>. Try toggling off Adaptive Acceleration, Ion, mPulse, Prefetch, and/or similar performance features. Also check for the following in the configuration:</p><pre class=highlighted style=color:#D0D0E0;background-color:#202034><network:http.buffer-response-v2>off</network:http.buffer-response-v2>
</pre></li></ul><h2 id=nodejs-itself><a name=nodejs-itself class=anchor href=#nodejs-itself><span class=header-link></span></a>Node.js itself</h2><p>For extreme cases where <a href=https://github.com/marko-js/marko/pull/1641>Node streams very small HTML chunks with its built-in compression modules</a>, you may need to tweak the compressor stream settings. Here’s an example with <code>createGzip</code> and its <code>Z_PARTIAL_FLUSH</code> flag:</p><pre class=highlighted style=color:#D0D0E0;background-color:#202034><span style=color:#FF4185>import</span> <span style=color:#FFFFFF>http</span> <span style=color:#FF4185>from</span> <span style=color:#FFF066>"http"</span>;
<span style=color:#FF4185>import</span> <span style=color:#FFFFFF>zlib</span> <span style=color:#FF4185>from</span> <span style=color:#FFF066>"zlib"</span>;
<span style=color:#FF4185>import</span> <span style=color:#FFFFFF>MarkoTemplate</span> <span style=color:#FF4185>from</span> <span style=color:#FFF066>"./something.marko"</span>;
<span style=color:#FFFFFF>http</span>
.<span style=color:#A6E22E>createServer</span>(<span style=color:#66D9EF>function</span> (<span style=color:#FFAC4D>request</span>, <span style=color:#FFAC4D>response</span>) {
<span style=color:#FFFFFF>response</span>.<span style=color:#A6E22E>writeHead</span>(<span style=color:#AE81FF>200</span>, { <span style=color:#FFF066>"content-type"</span>: <span style=color:#FFF066>"text/html;charset=utf-8"</span> });
<span style=color:#66D9EF>const</span> <span style=color:#FFFFFF>templateStream</span> <span style=color:#FFFFFF>=</span> <span style=color:#FFFFFF>MarkoTemplate</span>.<span style=color:#A6E22E>stream</span>({});
<span style=color:#66D9EF>const</span> <span style=color:#FFFFFF>gzipStream</span> <span style=color:#FFFFFF>=</span> <span style=color:#FFFFFF>zlib</span>.<span style=color:#A6E22E>createGzip</span>({
flush: <span style=color:#FFFFFF>zlib</span>.<span style=color:#FFFFFF>constants</span>.<span style=color:#FFFFFF>Z_PARTIAL_FLUSH</span>,
});
<span style=color:#FFFFFF>templateStream</span>.<span style=color:#A6E22E>pipe</span>(<span style=color:#FFFFFF>outputStream</span>).<span style=color:#A6E22E>pipe</span>(<span style=color:#FFFFFF>response</span>);
})
.<span style=color:#A6E22E>listen</span>(<span style=color:#AE81FF>80</span>);
</pre><a href="https://github.com/marko-js/marko/blob/main/packages/marko/docs/troubleshooting-streaming.md" class=edit-on-github>EDIT <img alt="on GitHub" src=/assets/0bc571bc.svg></a><h2 id=contributors><a name=contributors class=anchor href=#contributors><span class=header-link></span></a> Contributors</h2><p>Helpful? You can thank these awesome people! You can also <a href=https://github.com/marko-js/marko/blob/main/packages/marko/docs/troubleshooting-streaming.md>edit this doc</a> if you see any issues or want to improve it.</p><div class=contributors><a href=https://github.com/DylanPiercey class=contributor><img src=https://avatars.githubusercontent.com/u/4985201?v=4 alt class=photo><span class=name>DylanPiercey</span></a><a href=https://github.com/mlrawlings class=contributor><img src=https://avatars.githubusercontent.com/u/1958812?v=4 alt class=photo><span class=name>mlrawlings</span></a><a href=https://github.com/tigt class=contributor><img src=https://avatars.githubusercontent.com/u/8072522?v=4 alt class=photo><span class=name>tigt</span></a><a href=https://github.com/marko-js/marko/blob/main/packages/marko/docs/troubleshooting-streaming.md class="contributor you"><div class=photo><span class=icon>+</span></div><span class=name>You?</span></a></div><footer class="site-footer doc-footer"><a href="https://openjsf.org/" class=openjsf><img src=/assets/6876aea9.svg alt> <span><span class=bold>OpenJS</span> <span class=light>Foundation</span></span></a><div class=separator></div><a href=https://github.com/marko-js/marko/blob/main/LICENSE class=osi><img src=/assets/1b70b500.svg alt> MIT License</a><div class=separator></div><a href=https://github.com/eBay class=ebay><img src=/assets/339b8a9e.svg alt=eBay> open source</a></footer></div></div></div></main><script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-66854919-1', 'markojs.com');
ga('send', 'pageview');
</script><a href=https://discord.gg/marko target=_blank class=discord-button><img src=/assets/78800ea4.svg alt="Chat in Marko's Discord Server"></a><script>$MC=(window.$MC||[]).concat({"l":1,"w":[["s0-1-0-14",0,{}],["s0-1-0-14-12",1,{}],["s0-1-0-15",2,{"currentDoc":"troubleshooting-streaming"}],["s0-1-0-15-9",3,{}]],"t":["IZr$9Bl","uja7Vjk","G0dDyNr","wIkyy5p"]})</script></body></html>