I recently started working on a project that uses the Nuxt.js JavaScript Framework. It had been several months since the last time I worked on a Web project. I knew from past experience that I should warm up with a simple example of creating an SPA (single page application) using only JavaScript and HTML.
An SPA is loaded once into a user’s browser and then acts as an application without any further page reloads. The page is updated from data from the client or from data fragments (usually as JSON) fetched from the server.
A simple SPA application on the left, and a simple Web server based on node.js on the right. Every time I changed the application code I had to stop and restart the Web server.
In order to test my simple SPA, I needed a simple Web server. I like Node.js so I installed it on my Windows machine (I was using a new machine that didn’t have Node.js) from https://nodejs.org/en/download/. I used the .msi installer file and installation worked without problems (except the installation installed yet another instance of Python 3.10 on my machine which clashed with my installed PyTorch where I use Python 3.7.6).
I created a directory named C:\nodejs\SimpleSPA to hold my files. I created a relatively simple SPA and named it index.html and saved it in directory SimpleSPA. Here it is with less-than and greater-than characters replaced by { and } so my lame blog editor doesn’t choke:
{!-- index.html --} {html} {head} {meta charset="utf-8"} {title}Super Simple SPA{/title} {/head} {script} function loadContent() // initial page content { var contentDiv1 = document.getElementById("content1"); contentDiv1.innerHTML = "Home"; var currDateTime = new Date(); var currTime = currDateTime.getHours() + ":" + currDateTime.getMinutes() + ":" + currDateTime.getSeconds(); var contentDiv2 = document.getElementById("content2"); contentDiv2.innerHTML = currTime; } function showTime() // button click { var currDateTime = new Date(); var currTime = currDateTime.getHours() + ":" + currDateTime.getMinutes() + ":" + currDateTime.getSeconds(); var contentDiv = document.getElementById("content2"); contentDiv.innerHTML = currTime; } // link click causes hashchange window.addEventListener("hashchange", function (){ fragId = location.hash.substr(1); // from URL // alert(fragId); var contentDiv1 = document.getElementById("content1"); if (fragId == "home") { contentDiv1.innerHTML = "This is the Home page"; } else if (fragId == "about") { contentDiv1.innerHTML = "We are awesome"; } else if (fragId == "contact") { contentDiv1.innerHTML = "Our email is someone@somewhere.com"; } }); {/script} {body onload="loadContent()"} {a href="#home"}Home{/a} {a href="#about"}About{/a} {a href="#contact"}Contact{/a} {hr} {div id="content1"}{/div} {hr} {hr} {button type="button" onclick="showTime();"} Get Current Time{/button} {hr} {div id="content2"}{/div} {hr} {/body} {/html}
To test the page, I created a simple Node.js Web server that looks for a file named index.html by default and listens on port 3456, and saved it as server.js in the SimpleSPA directory:
// server.js var http = require('http'); var fs = require('fs'); const PORT=3456; fs.readFile('./index.html', function (err, html) { if (err) throw err; http.createServer(function(request, response) { response.writeHeader(200, {"Content-Type": "text/html"}); response.write(html); response.end(); }).listen(PORT); }); console.log('Node.js web server at port 3456 is running..')
I opened a shell, went to directory SimpleSPA, and issued command “node server.js” to start the server. Then I launched a Chrome browser and navigated to http://localhost:3456/index.html and it all worked after some debugging. The initial page content is placed by loadContent() which gets called by the body onload event. Clicking on one of the three links causes a built-in hashchange event to fire, which is handled by an anonymous function to place Home, About, Contact dummy content. Clicking on the button fetches and displays the current time.
Simple SPAs are easy. The hard part is when you need to maintain state across page loads. That’s when JavaScript frameworks like Vue.js and Nuxt.js become very useful. I think of Nuxt.js as a wrapper over Vue.js which is a wrapper over JavaScript which is a wrapper over Assembly Language which is a wrapper over machine language.
Fashion designers have used bubble wrap for haute couture for many years. Left: Nice. Center: Nice. Right: Um, . . . Interesting.
That was easy
