Skip to main content

How to Use Importmap in a WordPress Website

I have been trying to work on a basic WordPress classic theme without build steps which I can use as a starter theme to maybe develop client sites in future. At the time of writing this article, I’m not doing any freelance gigs as I’m working for a web agency and the sites we’re building all involve build steps. So I thought I write up a short tutorial on how to use importmap in a WordPress theme.

Career Tracker is an existing side project of mine that already uses importmap without a build step, but it’s a pure JavaScript app.

Let’s see how we can do it in WordPress world.

Enqueue Module Script

In my theme functions.php, I enqueue my JavaScript file app.js as a module script with wp_enqueue_script_module function from WordPress.

wp_enqueue_script_module( 'frontend-scripts', GEARUP_THEME_URL . '/static/js/app.js', [], GEARUP_THEME_VERSION, true );

This will outputs to below script tag on the frontend.

<script type="module" src="http://test.local/wp-content/themes/GearUp/static/js/app.js?ver=0.1.0" id="frontend-scripts-js-module"></script>

My JavaScript files are placed into the static folder of the theme folder.

static
├── css
│   ├── app.css
│   ├── global.css
│   ├── reset.css
│   ├── utils.css
│   └── variables.css
└── js
    ├── admin.js
    ├── app.js
    ├── components
    │   └── menu.js
    └── utils
        └── index.js

As you can see in this files structure, I need to import index.js from utils folder and menu.js from components folder into my app.js. Before we adding the importmap, let’s see how it looks when I import those two files like this in my app.js.

// Utils
import { onDocumentReady } from './utils/index.js';
// Components
import Menu from './components/menu.js';

But What I have in mind is to import files like this.

// Utils
import { onDocumentReady } from 'utils/index.js';
// Components
import Menu from 'components/menu.js';

Once I change imports to this format, browser will throw this error in the console.

Uncaught TypeError: Failed to resolve module specifier "utils/index.js". Relative references must start with either "/", "./", or "../".

Importmap come to the rescue

Add this inside your template html head tag. You might need to render this part in php so you can get the dynamic url to the static folder.

<script type="importmap">
    {
      "imports": {
        "utils/": "/wp-content/themes/GearUp/static/js/utils/",
        "components/": "/wp-content/themes/GearUp/static/js/components/"
      }
    }
</script>

Use it in my app.js

Now with importmap setup, even though this is not a Node environment, we can still import files under the structure we’re familiar with. Keep in mind that the files need to end with .js.

// Utils
import { onDocumentReady } from 'utils/index.js';
// Components
import Menu from 'components/menu.js';

If I remove the .js from my utils/index.js to utils/index, then browser will log this error in the console.

GET http://test.local/wp-content/themes/GearUp/static/js/utils/index net::ERR_ABORTED 404 (Not Found)

Add files from CDN into our importmap

<script type="importmap">
    {
      "imports": {
        "utils/": "/wp-content/themes/GearUp/static/js/utils/",
        "components/": "/wp-content/themes/GearUp/static/js/components/",
        "ccw/": "https://unpkg.com/cucumber-web-components@0.5.2/dist/"
      }
    }
</script>

I grab a CDN link to my Web Components collection and add it into my importmap. Once added, now we can import Web Components into app.js like this. Isn’t this beautiful?

import "ccw/side-nav/index.js";
import "ccw/side-nav-item/index.js";
import "ccw/icon/index.js";
import "ccw/form-layout/index.js";
import "ccw/text-field/index.js";
import "ccw/email-field/index.js";
import "ccw/date-picker/index.js";
import "ccw/option/index.js";
import "ccw/select/index.js";

For Web Components, clearly I’m not using it in my WordPress theme, but you can check the side project Career Tracker I mentioned in the beginning to see how they work.