Skip to content

Commit

Permalink
Update compositor.json via compositor.io
Browse files Browse the repository at this point in the history
  • Loading branch information
geelen committed Nov 2, 2017
1 parent 2e1c0ec commit 66ee37c
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion compositor.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"metadata": {
"source": "github.readme"
},
"html": "<h1>&#x1F4F8; React Snapshot</h1>\n<p>A zero-configuration static pre-renderer for React apps. Starting by targeting Create React App (because it&apos;s great)</p>\n<h2>The Premise</h2>\n<p>Server-side rendering is a big feature of React, but for most apps it can be more trouble than its worth. Personally, I think the sweet spot is taking static site snapshots of all your publicly-accessible pages &amp; leaving anything requiring authentication as a normal, JS-driven Single Page App.</p>\n<p>This is a project to do that. Automatically, without any configuration, just smart defaults. <strong>Retrospective progressive enhancement.</strong></p>\n<p>The snapshots still have the normal JS bundle included, so once that downloads the site will function exactly as before (i.e. instantaneous page transitions), but you serve real, functional HTML &amp; CSS as soon as possible. It&apos;s good for SEO (yes Google crawls SPAs now but they still reward perf and this perfs like a banshee), it&apos;s good if your JS is broken or something render-blocking has a network fail, it&apos;s good for accessibility, it&apos;s good for Slackbot or Facebook to read your opengraph tags, it&apos;s just good.</p>\n<h2>The How To</h2>\n<ul>\n<li>First, <code>npm i -D react-snapshot</code></li>\n<li>Second, open your package.json and change <code>&quot;scripts&quot;</code> from</li>\n</ul>\n<pre><span class=\"hljs-deletion\">- &quot;build&quot;: &quot;react-scripts build&quot;</span>\n<span class=\"hljs-addition\">+ &quot;build&quot;: &quot;react-scripts build &amp;&amp; react-snapshot&quot;</span></pre><ul>\n<li>Third, change your usage of <code>react-dom</code>:</li>\n</ul>\n<pre><span class=\"hljs-deletion\">- import ReactDOM from &apos;react-dom&apos;;</span>\n<span class=\"hljs-addition\">+ import { render } from &apos;react-snapshot&apos;;</span>\n\n<span class=\"hljs-deletion\">- ReactDOM.render(</span>\n<span class=\"hljs-addition\">+ render(</span>\n &lt;App/&gt;,\n document.getElementById(&apos;root&apos;)\n );</pre><p>This calls <code>ReactDOM.render</code> in development and <code>ReactDOMServer.renderToString</code> when prerendering. If I can make this invisible I will but I can&apos;t think how at the moment.</p>\n<h2>Options</h2>\n<p>You can specify additional paths as entry points for crawling that would otherwise not be found. It&apos;s also possible to exclude particular paths from crawling. Simply add a section called <code>&quot;reactSnapshot&quot;</code> to your package.json.</p>\n<pre> <span class=\"hljs-string\">&quot;reactSnapshot&quot;</span>: {\n <span class=\"hljs-string\">&quot;include&quot;</span>: [\n <span class=\"hljs-string\">&quot;/other-path&quot;</span>,\n <span class=\"hljs-string\">&quot;/another/nested-path&quot;</span>\n ],\n <span class=\"hljs-string\">&quot;exclude&quot;</span>: [\n <span class=\"hljs-string\">&quot;/signup&quot;</span>,\n <span class=\"hljs-string\">&quot;/other-path/exclude-me/**&quot;</span>\n ],\n <span class=\"hljs-string\">&quot;snapshotDelay&quot;</span>: <span class=\"hljs-number\">300</span>\n }</pre><p>Note that exclude can be passed a glob, but include cannot.</p>\n<p>The default snapshot delay is 50ms, and this can be changed to suit your app&apos;s requirements.</p>\n<h2>The Demo</h2>\n<p>Check out <a href=\"https://create-react-app-snapshot.surge.sh\">create-react-app-snapshot.surge.sh</a> for a live version or <a href=\"https://github.com/geelen/create-react-app-snapshot\">geelen/create-react-app-snapshot</a> for how it was built, starting from <a href=\"https://github.com/facebookincubator/create-react-app\">create-react-app</a>&apos;s awesome baseline. No ejecting necessary, either.</p>\n<p>The <a href=\"https://github.com/geelen/create-react-app-snapshot/compare/303f774...master\">diff from the original create-react-app code</a> might be enlightening to you as well.</p>\n<h2>The Implementation</h2>\n<p>It&apos;s pretty simple in principle:</p>\n<ul>\n<li>Fire up the home page in a fake browser and snapshot the HTML once the page is rendered</li>\n<li>Follow every relative URL to crawl the whole site</li>\n<li>Repeat.</li>\n</ul>\n<p>There&apos;s a few more steps to it, but not much.</p>\n<ul>\n<li>We move <code>build/index.html</code> to <code>build/200.html</code> at the beginning, because it&apos;s a nice convention. Hosts like <a href=\"https://surge.sh\">surge.sh</a> understand this, serving <code>200.html</code> if no snapshot exists for a URL. If you use a different host I&apos;m sure you can make it do the same.</li>\n<li><code>pushstate-server</code> is used to serve the <code>build</code> directory &amp; serving <code>200.html</code> by default</li>\n<li>The fake browser is JSDOM, set to execute any local scripts (same origin) in order to actually run your React code, but it&apos;ll ignore any third-party scripts (analytics or social widgets)</li>\n<li>We start a new JSDOM session for each URL to ensure that each page gets the absolute minimum HTML to render it.</li>\n</ul>\n<h2>The Caveats</h2>\n<p>This is a hacky experiment at the moment. I would really like to see how far we can take this approach so things &quot;just work&quot; without ever adding config. Off the top of my head:</p>\n<ul>\n<li>[x] Waiting on <a href=\"https://github.com/scottcorgan/pushstate-server/pull/29\">pushstate-server#29</a>. Right now <code>pushstate-server</code> serves <code>200.html</code> <em>even if</em> a HTML snapshot is present. So once you&apos;ve run <code>react-snapshot</code>, you have to switch to <code>http-server</code> or <code>superstatic</code> to test if it worked. Or you could just push to <a href=\"https://surge.sh\">surge.sh</a> each time, which isn&apos;t too bad.</li>\n<li>[x] Is starting at <code>/</code> and crawling sufficient? Might there be unreachable sections of your site?</li>\n<li>[x] Should we exclude certain URLs? Maybe parse the <code>robots.txt</code> file?</li>\n<li>[ ] What if you don&apos;t want the <code>200.html</code> pushstate fallback? What if you want to remove the bundle (effectively making this a static site generator)?</li>\n<li>[ ] This doesn&apos;t pass down any state except what&apos;s contained in the markup. That feels ok for simple use-cases (you can always roll your own) but if you have a use-case where you need it and want zero-config raise an issue.</li>\n<li>[x] #2 I&apos;m using a regexp to parse URLs out of the HTML because I wrote this on a flight with no wifi and couldn&apos;t NPM install anything. We should use a real parser. You should submit a PR to use a real parser. That would be real swell.</li>\n<li>[ ] Should we clone the <code>build</code> directory to something like <code>snapshot</code> or <code>dist</code> instead of modifying it in-place?</li>\n<li>[ ] There&apos;s virtually no error checking things so will just explode in interesting ways. So yeah that should be fixed.</li>\n<li>[ ] Is JSDOM gonna hold us back at some point?</li>\n<li>[ ] If the React code is changing what it renders based on size of viewport then things may &quot;pop in&quot; once the JS loads. Anything driven by media queries should just work though. So stick to Media Queries, I guess?</li>\n<li>[ ] Does someone else want to take this idea and run with it? I would be 100% happy to not be the maintainer of this project :)</li>\n</ul>\n<h2>The Alternatives</h2>\n<p>This should work for simple cases. For less simple cases, go with:</p>\n<ul>\n<li><a href=\"https://github.com/markdalgleish/static-site-generator-webpack-plugin\">Webpack Static Site Generator Plugin</a></li>\n<li><a href=\"https://github.com/gatsbyjs/gatsby\">Gatsby</a> or <a href=\"https://phenomic.io/\">Phenomic</a> if you&apos;re doing something bigger or more structured. Phenomic has service worker support &amp; minimal bundles and all kinds of things, Gatsby is getting that stuff too.</li>\n<li>Actually run a server-side React node server because you have more complex stuff to do, like pre-rendering stuff behind a login.</li>\n</ul>\n<h2>License</h2>\n<p>MIT</p>\n"
"html": "<h1>&#x1F4F8; React Snapshot</h1>\n<p>A zero-configuration static pre-renderer for React apps. Starting by targeting Create React App (because it&apos;s great)</p>\n<h2>The Premise</h2>\n<p>Server-side rendering is a big feature of React, but for most apps it can be more trouble than its worth. Personally, I think the sweet spot is taking static site snapshots of all your publicly-accessible pages &amp; leaving anything requiring authentication as a normal, JS-driven Single Page App.</p>\n<p>This is a project to do that. Automatically, without any configuration, just smart defaults. <strong>Retrospective progressive enhancement.</strong></p>\n<p>The snapshots still have the normal JS bundle included, so once that downloads the site will function exactly as before (i.e. instantaneous page transitions), but you serve real, functional HTML &amp; CSS as soon as possible. It&apos;s good for SEO (yes Google crawls SPAs now but they still reward perf and this perfs like a banshee), it&apos;s good if your JS is broken or something render-blocking has a network fail, it&apos;s good for accessibility, it&apos;s good for Slackbot or Facebook to read your opengraph tags, it&apos;s just good.</p>\n<h2>The How To</h2>\n<ul>\n<li>First, <code>npm i -D react-snapshot</code></li>\n<li>Second, open your package.json and change <code>&quot;scripts&quot;</code> from</li>\n</ul>\n<pre><span class=\"hljs-deletion\">- &quot;build&quot;: &quot;react-scripts build&quot;</span>\n<span class=\"hljs-addition\">+ &quot;build&quot;: &quot;react-scripts build &amp;&amp; react-snapshot&quot;</span></pre><ul>\n<li>Third, change your usage of <code>react-dom</code>:</li>\n</ul>\n<pre><span class=\"hljs-deletion\">- import ReactDOM from &apos;react-dom&apos;;</span>\n<span class=\"hljs-addition\">+ import { render } from &apos;react-snapshot&apos;;</span>\n\n<span class=\"hljs-deletion\">- ReactDOM.render(</span>\n<span class=\"hljs-addition\">+ render(</span>\n &lt;App/&gt;,\n document.getElementById(&apos;root&apos;)\n );</pre><p>This calls <code>ReactDOM.render</code> in development and <code>ReactDOMServer.renderToString</code> when prerendering. If I can make this invisible I will but I can&apos;t think how at the moment.</p>\n<h2>Options</h2>\n<p>You can specify additional paths as entry points for crawling that would otherwise not be found. It&apos;s also possible to exclude particular paths from crawling. Simply add a section called <code>&quot;reactSnapshot&quot;</code> to your package.json.</p>\n<pre> <span class=\"hljs-string\">&quot;reactSnapshot&quot;</span>: {\n <span class=\"hljs-string\">&quot;include&quot;</span>: [\n <span class=\"hljs-string\">&quot;/other-path&quot;</span>,\n <span class=\"hljs-string\">&quot;/another/nested-path&quot;</span>\n ],\n <span class=\"hljs-string\">&quot;exclude&quot;</span>: [\n <span class=\"hljs-string\">&quot;/signup&quot;</span>,\n <span class=\"hljs-string\">&quot;/other-path/exclude-me/**&quot;</span>\n ],\n <span class=\"hljs-string\">&quot;snapshotDelay&quot;</span>: <span class=\"hljs-number\">300</span>\n }</pre><p>Note that exclude can be passed a glob, but include cannot.</p>\n<p>The default snapshot delay is 50ms, and this can be changed to suit your app&apos;s requirements.</p>\n<h2>The Demo</h2>\n<p>Check out <a href=\"https://create-react-app-snapshot.surge.sh\">create-react-app-snapshot.surge.sh</a> for a live version or <a href=\"https://github.com/geelen/create-react-app-snapshot\">geelen/create-react-app-snapshot</a> for how it was built, starting from <a href=\"https://github.com/facebookincubator/create-react-app\">create-react-app</a>&apos;s awesome baseline. No ejecting necessary, either.</p>\n<p>The <a href=\"https://github.com/geelen/create-react-app-snapshot/compare/303f774...master\">diff from the original create-react-app code</a> might be enlightening to you as well.</p>\n<h2>The Implementation</h2>\n<p>It&apos;s pretty simple in principle:</p>\n<ul>\n<li>Fire up the home page in a fake browser and snapshot the HTML once the page is rendered</li>\n<li>Follow every relative URL to crawl the whole site</li>\n<li>Repeat.</li>\n</ul>\n<p>There&apos;s a few more steps to it, but not much.</p>\n<p>React-snapshot will crawl all links that it finds. You can create &quot;site map&quot; page, which will contain links to all pages.</p>\n<ul>\n<li>We move <code>build/index.html</code> to <code>build/200.html</code> at the beginning, because it&apos;s a nice convention. Hosts like <a href=\"https://surge.sh\">surge.sh</a> understand this, serving <code>200.html</code> if no snapshot exists for a URL. If you use a different host I&apos;m sure you can make it do the same.</li>\n<li><code>pushstate-server</code> is used to serve the <code>build</code> directory &amp; serving <code>200.html</code> by default</li>\n<li>The fake browser is JSDOM, set to execute any local scripts (same origin) in order to actually run your React code, but it&apos;ll ignore any third-party scripts (analytics or social widgets)</li>\n<li>We start a new JSDOM session for each URL to ensure that each page gets the absolute minimum HTML to render it.</li>\n</ul>\n<h2>The Caveats</h2>\n<p>This is a hacky experiment at the moment. I would really like to see how far we can take this approach so things &quot;just work&quot; without ever adding config. Off the top of my head:</p>\n<ul>\n<li>[x] Waiting on <a href=\"https://github.com/scottcorgan/pushstate-server/pull/29\">pushstate-server#29</a>. Right now <code>pushstate-server</code> serves <code>200.html</code> <em>even if</em> a HTML snapshot is present. So once you&apos;ve run <code>react-snapshot</code>, you have to switch to <code>http-server</code> or <code>superstatic</code> to test if it worked. Or you could just push to <a href=\"https://surge.sh\">surge.sh</a> each time, which isn&apos;t too bad.</li>\n<li>[x] Is starting at <code>/</code> and crawling sufficient? Might there be unreachable sections of your site?</li>\n<li>[x] Should we exclude certain URLs? Maybe parse the <code>robots.txt</code> file?</li>\n<li>[ ] What if you don&apos;t want the <code>200.html</code> pushstate fallback? What if you want to remove the bundle (effectively making this a static site generator)?</li>\n<li>[ ] This doesn&apos;t pass down any state except what&apos;s contained in the markup. That feels ok for simple use-cases (you can always roll your own) but if you have a use-case where you need it and want zero-config raise an issue.</li>\n<li>[x] #2 I&apos;m using a regexp to parse URLs out of the HTML because I wrote this on a flight with no wifi and couldn&apos;t NPM install anything. We should use a real parser. You should submit a PR to use a real parser. That would be real swell.</li>\n<li>[ ] Should we clone the <code>build</code> directory to something like <code>snapshot</code> or <code>dist</code> instead of modifying it in-place?</li>\n<li>[ ] There&apos;s virtually no error checking things so will just explode in interesting ways. So yeah that should be fixed.</li>\n<li>[ ] Is JSDOM gonna hold us back at some point?</li>\n<li>[ ] If the React code is changing what it renders based on size of viewport then things may &quot;pop in&quot; once the JS loads. Anything driven by media queries should just work though. So stick to Media Queries, I guess?</li>\n<li>[ ] Does someone else want to take this idea and run with it? I would be 100% happy to not be the maintainer of this project :)</li>\n</ul>\n<h2>The Alternatives</h2>\n<p>This should work for simple cases. For less simple cases, go with:</p>\n<ul>\n<li><a href=\"https://github.com/markdalgleish/static-site-generator-webpack-plugin\">Webpack Static Site Generator Plugin</a></li>\n<li><a href=\"https://github.com/gatsbyjs/gatsby\">Gatsby</a> or <a href=\"https://phenomic.io/\">Phenomic</a> if you&apos;re doing something bigger or more structured. Phenomic has service worker support &amp; minimal bundles and all kinds of things, Gatsby is getting that stuff too.</li>\n<li>Actually run a server-side React node server because you have more complex stuff to do, like pre-rendering stuff behind a login.</li>\n</ul>\n<h2>License</h2>\n<p>MIT</p>\n"
},
{
"component": "footer",
Expand Down

0 comments on commit 66ee37c

Please sign in to comment.