Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ugultopu/eeffb3f60735c4c612fa996eff752fb8 to your computer and use it in GitHub Desktop.
Save ugultopu/eeffb3f60735c4c612fa996eff752fb8 to your computer and use it in GitHub Desktop.
A better approach to generating a static web-page with your gists on the back-end, instead of dynamically generating them on the front-end

GitHub provides us an easy way of embedding gists on a web page. When we navigate to a gist on GitHub, there is a drop-down list element with the default option named "Embed". The value of this is an HTML <script> tag. The src attribute of this <script> tag is nothing but simply the GitHub Gists URL of this gist, with .js appended to it. When we navigate to this URL (the one that ends with .js), we observe that this is a JavaScript source file with two document.write statements. The first document.write statement adds an HTML <link> element for the CSS of the embedded gist. The second document.write is the gist itself.

Embedding gists this way is acceptable for one or two gists (although still being a bad approach) but for more gists, it simply results in a polluted HTML and needless HTTP GET requests for each gist embed link (the HTTP GET requests to the relevant JavaScript files). In other words, every visit to your web page will result in multiple (as many as the number of gists you have) HTTP GET requests to be made to the gist embed scripts (the JavaScript files). This is a waste of network and hardware resources because in order to obtain the exact same output, every visitor will make the exact same HTTP requests and their browsers will process (execute) the script and add (write) the elements to the document.

A much more reasonable way of doing this is to simply make the HTTP requests to the embed scripts on the back-end, process (execute) the scripts on the back-end and generate a static web page as the output and serve this web page whenever a visitor would like to access that web page. This way, instead of making network requests and processing (executing) embed scripts numberOfVisitors * numberOfYourGists times, you will make them only once, which is numberOfYourGists times and serve the visitors a static web page which has already been populated with your embedded gists.

The benefit of "embedding gists on the back-end" this way are:

  1. Huge savings on network and hardware resources.
  2. A much faster (quicker) render of the web page.
  3. Users that have their JavaScript disabled can view your gists.
  4. Much cleaner (neat, tidy) HTML output.
  5. Much more control on the HTML output since instead of relying on document.write statements, we pick where exactly to place the gists.

Without further ado, the following is the code to embed gists to a web page on the back-end, generating a static web-page:

const GITHUB_USERNAME = 'ugultopu';

// Helper function to perform an easier GET request.
function get(link, options, callback) {
  if (!callback) {
    callback = options;
    options = {};
  }
  require('https').get(link, options, response => {
      let data = '';
      response.setEncoding('utf8');
      response.on('data', chunk => data += chunk);
      response.on('end', () => callback(data));
    }
  );
}

get(
  `https://api.github.com/users/${GITHUB_USERNAME}/gists`,
  {headers: {'User-Agent': ''}},
  data => {
    const gistEmbedLinks = getGistEmbedLinks(data);
    let stylesheetLink;
    const gistElements = new Array(gistEmbedLinks.length);
    for (let i = 0; i < gistEmbedLinks.length; i++) {
      get(gistEmbedLinks[i], embedScript => {
        const scriptData = [
          ...embedScript.matchAll(/document\.write\((.*)\)/g)
        ];
        stylesheetLink = eval(scriptData[0][1]);
        gistElements[i] = eval(scriptData[1][1]);
        /**
         * Alternatives to the lines above:
         *
         * Alternative 1
         * =============
         * stylesheetLink = new Function(`return ${scriptData[0][1]}`)();
         * gistElements[i] = new Function(`return ${scriptData[1][1]}`)();
         *
         * Alternative 2
         * =============
         * eval(`
         *   stylesheetLink = ${scriptData[0][1]};
         *   gistElements[i] = ${scriptData[1][1]};
         * `);
         *
         * etc.
         */

        // After all gists have been obtained
        if (!gistElements.includes(undefined)) {
          require('fs').writeFile(
            'myGists.html',

            `
            <!DOCTYPE html>
            <html lang="en">
            <head>
              <meta charset="UTF-8">
              <meta name="viewport" content="width=device-width, initial-scale=1.0">
              ${stylesheetLink}
              <style>
                .gists {
                  max-width: 80ch;
                  margin: auto;
                }
              </style>
              <title>All my GitHub Gists</title>
            </head>
            <body>
              <div class="gists">
                ${gistElements.join('\n')}
              </div>
            </body>
            </html>
            `,

            () => console.log('Write complete!')
          );
        }
      });
    }
  }
);

function getGistEmbedLinks(data) {
  return JSON.parse(data).map(
    gist => `https://gist.github.com/${GITHUB_USERNAME}/${gist.id}.js`
  );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment