Show HN: I created a URL shortener that can be entirely hosted on GitHub Pages
This currently uses about 100KB of JavaScript (over 99KiB of polyfills, about 3KiB of actual code), loading the HTML file, then three JavaScript files, then making an API call to GitHub, then <i>finally</i> doing the actual redirect, by a substantially inferior JavaScript technique. Also, it doesn’t work on IE because the polyfills were insufficient.<p>Yes, this is an interesting technical demonstration of a concept, but it also has some rather serious problems, so that I would strongly recommend that no one actually do things this way.<p>----<p>Firstly, the size of the code: I just golfed it for fun, I think this should do for the full document (though I haven’t tested it):<p><pre><code>  &lt;!doctype html&gt;&lt;meta charset=utf-8&gt;&lt;title&gt;Redirecting...&lt;&#x2F;title&gt;&lt;script&gt;e=new XMLHttpRequest(),e.addEventListener(&quot;load&quot;,function(){try{if(&#x2F;^https?:\&#x2F;\&#x2F;(?!nlsn\.cf(\&#x2F;|$))&#x2F;.test(e=JSON.parse(e.responseText).title))return location.replace(e)}catch(e){}location.replace(&quot;&#x2F;&quot;)}),e.open(&quot;GET&quot;,&quot;https:&#x2F;&#x2F;api.github.com&#x2F;repos&#x2F;nelsontky&#x2F;gh-pages-url-shortener-db&#x2F;issues&#x2F;&quot;+location.pathname.split(&quot;&#x2F;&quot;)[1]),e.send()&lt;&#x2F;script&gt;
</code></pre>
100KB in four requests, down to 412 bytes in one request (and that 20 bytes of &lt;meta charset=utf-8&gt; isn’t even particularly valuable). And it restores support for IE, by using simple regular expression testing instead of `new URL(…)`, which IE never supported. As written, I believe it should work down to IE9, and older could be supported if you replaced the load event handler with an onreadystatechange incantation.<p>(Other general remarks on the HTML:<p>1. In &lt;meta charset=&quot;utf-8&quot; &#x2F;&gt;, the trailing slash is completely ignored by the HTML parser; in fact, I reckon using trailing slashes like this is actively slightly harmful, because it misleads you into thinking it closes elements, as in XML, but it doesn’t.<p>2. On the script elements, type=&quot;text&#x2F;javascript&quot; is the default and thus not needed.<p>3. &lt;html&gt;, &lt;head&gt; and &lt;body&gt; wrappings can all be omitted from the source. This one is a bit more subject to taste; I know some like their source to match the parsed document tree, even down to things like writing the &lt;tbody&gt; out even if there is no thead or tfoot. But I myself always omit the end tags on these, and omit the start tags unless they have attributes, which in practice means I always have the &lt;html&gt; for its lang attribute.<p>)<p>----<p>Secondly, the redirection technique. There are good reasons why you should use HTTP redirects and not JavaScript location.replace for something like this:<p>1. If you use JavaScript, any users unable to run the JavaScript are left high and dry. This includes people like me that disable JavaScript by default (I because it makes the web so much faster and less annoying; others for privacy reasons and similar), but it would also help people on poor-quality connections, especially if the JavaScript is loaded in a different connection (which will probably not be the case here), because it’s surprisingly common for parts of pages’ resources to simply fail to load sometimes on poor-quality connections.<p>2. Various tooling like link checkers likewise won’t be able to work with this. As it stands, even link checkers that ran JavaScript would fail on this because you’re also using location.replace to show the “bad link” error. (Another of my pet peeves: doing a redirect to a “not found” page, rather than serving the “not found” page at the original URL with status code 404.)<p>3. It’s perfectly feasible for the connection to <a href="https:&#x2F;&#x2F;nlsn.cf" rel="nofollow">https:&#x2F;&#x2F;nlsn.cf</a> to have succeeded, but the connection to <a href="https:&#x2F;&#x2F;api.github.com" rel="nofollow">https:&#x2F;&#x2F;api.github.com</a> to fail. When this happens, you’re left trying to decide what to do; and location.replace(&quot;&#x2F;&quot;) is a very bad solution, because you’ve now trashed the URL and I can’t even just try reloading the page to see if it works second time round. If you use HTTP redirects, everything will work perfectly in all cases, regardless of which connections succeed or fail.<p>4. Browsers have redirect loop detection, but you’ve opted out of that. In this thread someone pointed out simple loops and you’ve now tried to work around this by telling it “don’t redirect to the same domain”, but this really isn’t enough: you can easily have A → B → A. If this was done with HTTP redirection, the browser would twig and show an error and stop; but because half of the loop is done with location.replace, this won’t be caught. (Also, there are perfectly legitimate cases for a short URL redirecting to another short URL which redirects to a long URL, which this has now broken.)<p>----<p>A more amusing concept that occurs to me is implementing the URL shortener in a service worker, so that you <i>can</i> issue proper HTTP redirects, while doing it only on the client side.