A few of you might still remember the post , 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? How it feels to learn JavaScript in 2016 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 displayed in a table jsonplaceholder 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 script for an example. create-react-app 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 , we can see that we have >50 dependencies in our application, even before writing a single line of code. If we run and check the size of the resulting files, we can see the following result: package.json npm run build ❯ 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 and add a file to the folder. The html file should contain the following content: web-app index.html <!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 that all modern browsers support nowadays. And we are going to build , another technology that browsers support that allows us to create reusable elements for the page. the module functionality Web Components 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 , for python 3 and open in your browser. python -m SimpleHTTPServer 3000 python -m http.server 3000 http://localhost:3000 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/lit@2.2.0?module"; import { pureLit } from "https://unpkg.com/pure-lit@2.0.2?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 to . However, there a quite a few things happening now that might be unexpected for you. Please wait while loading... loaded! 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 , we can import other JavaScript libraries, given they expose their library as modules. We import two libraries: , a lightweight framework for easier creation of web components, and , which extends lit to allow usage of functional components. module lit pure-lit By then calling the function the custom-element is registered in the browser, and replaced with the templated HTML string . pureLit("jsonplaceholder-posts", async () => html`loaded!`) <jsonplaceholder-posts> loaded! We can now refactor the existing function to fetch the data from the URL and map the list into table rows. https://jsonplaceholder.typicode.com/posts 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 to have them linted. npx eslint index.js --fix 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, , nicely! How it feels to learn JavaScript in 2016 Frameworks, Tools and Technologies used in this article - Simple fast web components (previously known as Polymer) - Lightweight functional wrapper around lit - disclaimer: I’m the main contributor lit pure-lit - Creating and importing Javascript modules in the browser - Web Components is a suite of different technologies allowing you to create reusable custom elements - Free fake API for testing and prototyping. - Set up a modern web app by running one command JavaScript modules Web Components jsonplaceholder create-react-app