DEV Community

Cover image for Using ES Modules in native HTML & CSS apps
Mirza Leka
Mirza Leka

Posted on • Updated on

Using ES Modules in native HTML & CSS apps

While using ES module imports in native HTML apps is a powerful feature, it comes with a set of challenges along the way. This blog will teach you how to overcome them.

Challenge #1: The module script tag

To be able to use Import() statement in your JavaScript files and have them work as HTML scripts, you need to add type="module" tag to your script tag.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1 id="title"></h1>
    <button id="year-btn">Get Current Year</button>
  </body>
   <!-- type="module" enables ES Modules-->
  <script type="module" src="./index.js"></script>
</html>
Enter fullscreen mode Exit fullscreen mode

Challenge #2: When importing custom modules you need to add .js suffix to the file import path

Consider this module:

// date.helper.js
export const currentDateTime = new Date();
Enter fullscreen mode Exit fullscreen mode

To use it elsewhere you need to import it using a file path, but you also need to set a .js extension on the import:

// importing date.helper into index.js
 import { currentDateTime } from './date.helper.js';

console.log(currentDateTime.getFullYear()) // 2024
Enter fullscreen mode Exit fullscreen mode

Challenge #3: You can no longer call JavaScript functions from HTML

If you declare a function in the index.js file:

function sayHello() {
  alert('Hello!')
}
Enter fullscreen mode Exit fullscreen mode

And try to call it from the HTML:

    <button onclick="sayHello()">Say Hello</button>
Enter fullscreen mode Exit fullscreen mode

You'll get the following exception:

ReferenceError: sayHello is not defined
    at HTMLButtonElement.onclick
Enter fullscreen mode Exit fullscreen mode

The alternative to this is to use the addEventListener function to listen to click on the button and then act upon it.

  <body>
    <h1 id="title"></h1>
    <button id="year-btn">Get Current Year</button>
  </body>
  <script type="module" src="./index.js"></script>
Enter fullscreen mode Exit fullscreen mode
import { currentDateTime } from './date.helper.js';

// pick up the button element from the HTML
const yearBtn = document.querySelector('#year-btn');

// listening to click events
yearBtn.addEventListener('click', (event) => {
  const currentYear = currentDateTime.getFullYear();
  document.querySelector('#title').textContent = `Current Year: ${currentYear}`;
});
Enter fullscreen mode Exit fullscreen mode

Challenge #4: You can no longer run the HTML files natively in the browser:

Usually, the HTML page can loaded just by double-clicking on the .html file. With ES modules in place, you'd need a background server to serve the index.html document for the script to work.

This can be achieved using NPM modules, but if you're using Visual Studio Code you can install the Live Server extension from the extensions marketplace.

live-srver extension VSC

Then right-click on the index.html file and choose the Open with Live Server option. It should open up the web browser running on some port and modules will work fine.

From this point, you should be good to go. Happy coding 🥳

Top comments (0)