In this series, I'll take a look on a simple usecase of js+html application, build with various js bundlers. For a start, let's see what we can have without introducing any building tool.
esModules support
As of 2021, we can see very good support of esModules across all the major browser. According to can i use it the only browser lagging behind are opera & uc browser for android. If we can afford not supporting users on those browsers, we can be tempted to use native es modules to build our application on the browser side.
The application
The key features we use in this app set up are:
- single js to be included in the html
- app broken down into component(s), for better code organization
- separate file for component logic & template
There are other aspects that could be interesting to compare across builders, such as:
- importing npm modules
- compiling ts
- importing css in components let me know if you are interested in seeing those, or any other features in various bundlers.
Code
The html part is very straight forward:
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Contact App</title>
<link rel="shortcut icon" href="#" />
<script type="module" src="./src/index.js"></script>
<link rel="stylesheet" href="style.css" />
</head>
<body></body>
</html>
the key part is to import js as a module - by adding type="module"
to the <script>
tag. If you fail to do it, all you will see will be error in the console:
Uncaught SyntaxError: import declarations may only appear at top level of a module
the main js file, is just one line:
// ./scr/index.js
import "./contact-list/contact-list.js";
for a one-component application this is a bit over engineering, but in a more real word cases we will definitive want to break down application into multiple components. So here we make the example future proof, but preparing for more complicated set up.
The component
The component is broken into three files. The main js file:
// src/contact-list/contact-list.js
import { template } from "./contact-list.html.js";
import { contacts } from "./data.js";
const contactList = document.createElement("div");
contactList.className = "contact-list";
contacts.forEach((entry) => {
const element = document.createElement("div");
element.className = "contact";
element.innerHTML = template;
element.querySelector(".name").innerHTML = entry.name;
element.querySelector(".phone").innerHTML = entry.phone;
contactList.appendChild(element);
});
document.body.appendChild(contactList);
data file:
// src/contact-list/data.js
export const contacts = [
{
name: "Christopher L Sanders",
phone: "769-232-1807",
},
{
name: "Frances J Nolte",
phone: "901-287-0419",
},
];
and template file:
// src/contact-list/contact-list.html.js
export const template = `<h2 class="name">name</h2>
<p class="phone">phone</p>`;
The main downside of using es modules alone, is that we are limited to js files only. It would be better to have data as a json file & template as html, but those cannot be imported with es module syntax. So we are force to tweak them to become js files, and we move them from main component file just to follow common pattern of keeping different aspects of a component in a separate files. We have no benefits of easy integration with tooling - prettier, linters, etc. - specific for each of the content types.
Complete code & application example
If you want to see the application in action in the browser you can see it here:
https://marcin-wosinek.github.io/js-html-comparison-native-esm/
and for the working code example you can go here:
https://github.com/marcin-wosinek/js-html-comparison-native-esm
You can see other articles in this section, to see how the same application can be build with some of js bundlers.
Top comments (0)