The website I needed to convert had a very traditional setup, as you can see from the file structure.
There was a single
Using Chrome’s nifty network search filter you can see that there were a lot of calls to local files.
To create my starting point, I needed to break all the local file URLs. This way I could be sure I wasn’t accidentally pulling in any local files.I achieved this by moving the
index.html file out of the initial file structure.
I started off by fixing the CSS files. I used publicly hosted versions of popular 3rd party libraries including bootstrap, fontawesome and aos. As a result, the following
<!-- Bootstrap , fonts & icons --> <link rel="stylesheet" href="./css/bootstrap.css" /> <link rel="stylesheet" href="./fonts/icon-font/css/style.css" /> <link rel="stylesheet" href="./fonts/typography-font/typo.css" /> <link rel="stylesheet" href="./fonts/fontawesome-5/css/all.css" /> <!-- Plugin'stylesheets --> <link rel="stylesheet" href="./plugins/aos/aos.min.css" />
<link href="https://firstname.lastname@example.org/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous"> <link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.9.0/css/all.css"/> <link href="https://email@example.com/dist/aos.css" rel="stylesheet">
This gave the website some form and some of the icons started working.
Next, the custom styles had to be embedded into the file. First, I minified the CSS using the following website https://www.toptal.com/developers/cssminifier/ and then inserted a
<style> tag with the minified CSS into the
This resulted in minimal visible changes.
Same as with the CSS, CDN hosts were found for the popular 3rd party libraries.
<!-- Vendor Scripts --> <script src="js/bootstrap.min.js"></script> <!-- Plugin's Scripts --> <script src="./plugins/fancybox/jquery.fancybox.min.js"></script> <script src="./plugins/aos/aos.min.js"></script>
<!-- Vendor Scripts --> <script src="https://firstname.lastname@example.org/dist/js/bootstrap.bundle.min.js"></script> <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script> <!-- Plugin's Scripts --> <script src="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.js"></script> <script src="https://email@example.com/dist/aos.js"></script>
<script> tag at the bottom of the page.
Most of the text is now visible!
For Image fixes I had several options: scour the web for images that I could use in place of my local ones, host my local images on some online platform, or encode the images and directly embed them into the page. I chose the final option as it seemed most aligned with what I was trying to accomplish.
<img> tags within HTML pages allow you to specify a
src. Typically, this
src is a URL from which the image is fetched. However, you can also transform your image into a base64 string and embed it into the src attribute. The same can be done for a CSS background using the
https://www.base64-image.de/ is a handy tool for doing exactly this; you can upload an image and it will give you the necessary code to do the embedding.
All my Images were encoded into base64 strings and then directly embedded into the page, even the favicon!
Voilà! It looks almost identical to the original version of the website. For those of you with a keener eye, you may notice that the remaining difference between the original and current version of the site are the fonts!
Fonts are essentially a bunch of photos of the characters in our alphabet. Which, as you may have already guessed, we can encode into a base64 string and directly embed into our page.
https://hellogreg.github.io/woff2base/ converts fonts to base64. I used this tool when I was unable to find a hosted version of the font.
\ characters to be
As you can tell from the following two images, the starting and ending product are identical (besides the network calls).
For a little fun I decided to compare the performance of the two pages.
The following JS snippet
window.performance.timing.domComplete - window.performance.timing.requestStart
window.performance.timing object to measure the time between the page request start event to the page loaded event (including all fonts, styles, etc). On my machine, the non-embedded version tended to be quicker by about 10-30ms which is hardly noticeable to the end user.
Overall, embedding all your assets into one page is not very practical, but it is feasible and has minimal impact on the end user (at least for such a minimal site like this).
I had to go through this process to deploy my website onto a FaaS platform, the following Chrome extension I recently discovered, called SingleFile, posted on Hacker News which allows others to perform this embedding process automatically!