What it Takes to Create a Simple JavaScript Table in 2022

Written by matkainer | Published 2022/03/14
Tech Story Tags: technology | javascript | frontend | html | web-development | programming | webpack | python

TLDRA few of you might still remember the post [How it feels to learn JavaScript in 2016] It's 8 years later; a lot should have happened in a fast-paced ecosystem like JavaScript that makes our lives easier, right? So how does it feel to create a simple table nowadays? via the TL;DR App

A few of you might still remember the post How it feels to learn JavaScript in 2016, from which I also took the above image. It's 8 years later; a lot should have happened in a fast-paced ecosystem like JavaScript that makes our lives easier, right?

So how does it feel to create a simple table nowadays? Our user story for today is the following:

As a user

To be able to see some Latin in the browser

We want the post from jsonplaceholder displayed in a table

When you try to approach this topic, you might feel that little has changed since then. Only that some tools hide complexity from you slightly better and will only come to the surface whenever something fails, and you have no idea what's happening. Take a look at the create-react-app script for an example.

We create a new project and eject from it right away to see what complexity is hiding behind the curtain.

npx create-react-app react-app
cd react-app
npm run eject

When we open the package.json, we can see that we have >50 dependencies in our application, even before writing a single line of code. If we run npm run build and check the size of the resulting files, we can see the following result:

❯ du -ch build/static/js/*.js
8.0K    build/static/js/787.28cb0dcd.chunk.js
132K    build/static/js/main.0278e899.js
140K    total

We are at 140K, and we haven't even started to fetch the data or show it in a table. But it's 2022; how about taking a different approach? And to move forward, we are going back to the origins.

Create a new folder web-app and add a file index.html to the folder. The html file should contain the following content:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Table with Posts</title>
  </head>
  <body>
  </body>
</html>

With this, we are still at the point where there is no table on the page, but in 2022, creating it directly in this file, without any bundlers/builders/transpilers/etc, can be done quickly and conveniently.

We will use what the browser offers us, mainly the module functionality that all modern browsers support nowadays. And we are going to build Web Components, another technology that browsers support that allows us to create reusable elements for the page.

First, we create the custom element to the page that should display our table:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Table with posts</title>
  </head>
  <body>
    <jsonplaceholder-posts>
      Please wait while loading...
    </jsonplaceholder-posts>
  </body>
</html>

Let's open this in a browser. First, start a local web server by opening your terminal, and, for python 2, type python -m SimpleHTTPServer 3000, for python 3 python -m http.server 3000 and open http://localhost:3000 in your browser.

We can see the following result:

Please wait while loading...

Congratulations, you have created your first web component! That's a good start, but it lacks functionality. To develop the application further, we will add a script tag to the page and mark it as a module.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Table with posts</title>
    <script type="module">
      import { html } from "https://unpkg.com/[email protected]?module";
      import { pureLit } from "https://unpkg.com/[email protected]?module";

      pureLit("jsonplaceholder-posts", async () => html`loaded!`);
    </script>
  </head>
  <body>
    <jsonplaceholder-posts>
      Please wait while loading...
    </jsonplaceholder-posts>
  </body>
</html>

Refreshing the page in the browser will change Please wait while loading... to loaded!. However, there a quite a few things happening now that might be unexpected for you.

For one, we can import dependencies from URLs in the browser. This is what the beforementioned module functionality provides. Thus, by setting the script tag to module, we can import other JavaScript libraries, given they expose their library as modules. We import two libraries: lit, a lightweight framework for easier creation of web components, and pure-lit, which extends lit to allow usage of functional components.

By then calling the function pureLit("jsonplaceholder-posts", async () => html`loaded!`) the custom-element <jsonplaceholder-posts> is registered in the browser, and replaced with the templated HTML string loaded!.

We can now refactor the existing function to fetch the data from the https://jsonplaceholder.typicode.com/posts URL and map the list into table rows.

pureLit("jsonplaceholder-posts", async () => {
  const posts = await fetch(`https://jsonplaceholder.typicode.com/posts`)
    .then((response) => response.json())
  return html`<table>
    <tr>
      <th>Title</th>
      <th>Body</th>
    </tr>
    ${posts.map(({title, body}) => 
      html`<tr><td>${title}</td><td>${body}</td></tr>`)
    }
  </table>`
});

Refreshing the page in the browser presents us with all posts in the table. And all of this without us needing webpack, babel, not even nodejs, while having convenient javascript features like async/await.

And checking the size of the code we have to maintain will give us the following result:

❯ du -h index.html
4.0K    index.html

That is indeed a fraction of the react-starter example. Of course, one might argue that the complexity involved in loading the modules has simply been moved to the browser, but there is one crucial difference here: whereas before this was part of your build process to install and load the modules, now it is an infrastructure concern implemented following the browser standards. Module loading is no longer your issue and does not need npm, and to include them, you don't need Webpack. Modern JavaScript features are available without Babel. And componentization of your UI elements can be done natively with web components. The libraries are only there to make your life easier, but the resulting custom element can be used in plain HTML without requiring the application that uses them to utilize the same framework. You could even go as far as writing custom elements without any frameworks; they make the task easier, though.

On the other hand, if you want to add functionality that you feel is valuable, you still can. Rather than embedding the script file in the HTML, you can also move it to a file and, for instance, run npx eslint index.js --fix to have them linted.

So, has our life become any better? In parts, one could say it did. Of course, there's still a lot a developer has to know, but my hope is that with JavaScript modules, web components and language features supported in the browsers, we have reached a level where adding a dynamic table to the browser can be done only by reading only the JavaScript documentation on MDN. It also feels that the ecosystem has become more stable, and the number of new frameworks appearing has reduced.

Finally, writing a table that loads and displays some data in HTML + JavaScript in the right and accepted way hasn't been more straightforward in forever.

And thanks to the way we served our application, we were even using python, closing the loop to the original article, How it feels to learn JavaScript in 2016, nicely!

Frameworks, Tools and Technologies used in this article

lit - Simple fast web components (previously known as Polymer) pure-lit - Lightweight functional wrapper around lit - disclaimer: I’m the main contributor

JavaScript modules - Creating and importing Javascript modules in the browser Web Components - Web Components is a suite of different technologies allowing you to create reusable custom elements jsonplaceholder - Free fake API for testing and prototyping. create-react-app - Set up a modern web app by running one command


Written by matkainer | Writing software for hobby and for a living. Also Head of Software@Volocopter
Published by HackerNoon on 2022/03/14