Failed to resolve module specifier. Relative references must start with either

avatar
Borislav Hadzhiev

Last updated: Mar 7, 2024
6 min

banner

# Table of Contents

  1. Failed to resolve module specifier. Relative references must start with either
  2. Using a CDN to import the module
  3. Using a relative path when importing the module in the browser
  4. Using an import map to import a module in the browser
  5. Using an import map with local modules

# Failed to resolve module specifier. Relative references must start with either

The error 'Failed to resolve module specifier "X". Relative references must start with either "/", "./", or "../"' occurs when you try to import a module directly in the browser, e.g. import axios from 'axios'.

To resolve the issue, use a CDN, load the module from a relative path or use an import map.

failed to resolve module specifier

Here is the complete error message.

shell
Uncaught TypeError: Failed to resolve module specifier "X". Relative references must start with either "/", "./", or "../". Uncaught TypeError: The specifier “X” was a bare specifier, but was not remapped to anything. Relative module specifiers must start with “./”, “../” or “/”.

Here is an example of how the error occurs.

This is my index.html file.

index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> </head> <body> <div id="box">bobbyhadz.com</div> <script type="module" src="index.js"></script> </body> </html>
The code for this article is available on GitHub

Make sure that type is set to module on the script tag to be able to use the import/export syntax.

And here is the related index.js file.

index.js
// ⛔️ Uncaught TypeError: Failed to resolve module specifier "axios". Relative references must start with either "/", "./", or "../". import axios from 'axios'; async function getUser() { try { const response = await axios.get( 'https://randomuser.me/api/', ); return response.data; } catch (err) { console.log(err); } } console.log(getUser());
The code for this article is available on GitHub

The issue in the code sample is that we are trying to import a module as import module from 'module'.

This is the module resolution system that is used for Node.js and not for the browser.

When importing modules in the browser, you have 3 options:

  1. Using a CDN, e.g. https://some-cdn.com/module-name.
  2. Using a relative path that points to the file, e.g. ./module-name.js or ../module-name.js.
  3. Using an import map.

# Using a CDN to import the module

If you are trying to load a third-party library, you could use a CDN such as jsdelivr.com.

For example, you can Google for "jsdelivr axios" to get the ESM script that you have to import from.

When you visit the jsdelivr.com website:

  1. Click on the ESM button under Type:.
  2. Copy the URL for the module you're trying to import.

copy cdn url of module

Here is an example of how this works with the axios module.

index.js
import axios from 'https://cdn.jsdelivr.net/npm/axios@1.3.5/+esm'; async function getUser() { try { const response = await axios.get( 'https://randomuser.me/api/', ); return response.data; } catch (err) { console.log(err); } } console.log(await getUser());
The code for this article is available on GitHub

If I start my server with npx serve . and open my browser, I can see that the error is resolved and the module is loaded successfully.

module loaded successfully

You can also directly import and use the module in a script tag in your index.html file.

index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> </head> <body> <div id="box">bobbyhadz.com</div> <script type="module"> // 👇️ import and use module here... import axios from 'https://cdn.jsdelivr.net/npm/axios@1.3.5/+esm'; async function getUser() { try { const response = await axios.get( 'https://randomuser.me/api/', ); return response.data; } catch (err) { console.log(err); } } console.log(await getUser()); </script> </body> </html>
The code for this article is available on GitHub

The code sample achieves the same result but imports the axios module using a CDN directly in the index.html file and not in an external JS file.

# Using a relative path when importing the module in the browser

You can also use a relative path when importing a module in the browser.

The example uses the following file structure.

shell
my-project/ └── index.html └── index.js └── greet.js

Here is the code for the index.html file.

index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> </head> <body> <div id="box">bobbyhadz.com</div> <script type="module" src="index.js"></script> </body> </html>
The code for this article is available on GitHub

Note that type is set to module on the script tag.

And here is the code for the greet.js file.

greet.js
export function greet(name) { return `hey ${name}`; }

The file uses a named export to export a function.

Here is how we can import the file in our index.js file.

index.js
import {greet} from './greet.js'; console.log(greet('bobby hadz'));

If I issue the npx serve . command and open the page in my browser, I can see that everything works as expected.

import file using relative path

Notice that we used the ./ prefix when importing the file.

This means that the greet.js file is located in the same directory as the index.js file.

If the file that you are importing is located one directory up, you would use the ../ prefix, e.g. import {greet} from '../greet.js'.

This assumes that you have a folder structure similar to the following.

shell
└── project-folder/ └── greet.js └── nested-folder/ └── index.html └── index.js

If the file you are importing from is located two directories up, you would use the ../../ prefix.

I've written a detailed guide on how to import and export classes and functions in JavaScript.

Here are a couple of things to note:

  • Make sure to explicitly specify the extension when importing the file.
index.js
// ✅ correct (specified extension) import {greet} from './greet.js'; // ⛔️ incorrect (did not specify extension) import {greet} from './greet';
  • Only warp import statements in curly braces when using named exports.
index.js
// 👇️ when using a named export in the other file import {greet} from './greet.js' // --------------------------------- // 👇️ when using a default export in the other file import greet from './greet.js'
The code for this article is available on GitHub
  • Make sure to specify the correct relative path to the module. A relative path should start with ./ or ../.

# Using an import map to import a module in the browser

You can also set the type attribute of a module to importmap to import one or more modules in the browser.

Here is the index.html file for the example.

index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> </head> <!-- 👇️ setting type to importmap --> <script type="importmap"> { "imports": { "axios": "https://cdn.jsdelivr.net/npm/axios@1.3.5/+esm", "lodash": "https://cdn.jsdelivr.net/npm/lodash@4.17.21/+esm" } } </script> <body> <div id="box">bobbyhadz.com</div> <script type="module" src="index.js"></script> </body> </html>
The code for this article is available on GitHub

Note that the type attribute of the script is set to importmap.

I used the same approach to get the CDN links for the axios and lodash libraries as in the previous subheading.

For example, you can Google for "jsdelivr axios" to get the ESM script that you have to import from.

When you visit the jsdelivr.com website:

  1. Click on the ESM button under Type:.
  2. Copy the URL for the module you're trying to import.

copy cdn url of module

Here is how you can import and use the libraries in your index.js file.

index.js
import axios from 'axios'; import _ from 'lodash'; async function getUser() { try { const response = await axios.get( 'https://randomuser.me/api/', ); return response.data; } catch (err) { console.log(err); } } console.log(await getUser()); console.log(_.multiply(5, 5)); console.log(_.reverse(['bobby', 'hadz', 'com']));
The code for this article is available on GitHub

If I issue the npx serve . command and open the page in my browser, I can see that everything works as expected.

using importmap with third party modules

The importmap value of the type attribute on a script tag enables us to specify a JSON object that instructs the browser how to resolve module specifiers when importing modules.

index.html
<script type="importmap"> { "imports": { "axios": "https://cdn.jsdelivr.net/npm/axios@1.3.5/+esm", "lodash": "https://cdn.jsdelivr.net/npm/lodash@4.17.21/+esm" } } </script>

The object provides a mapping between the text that is used as the module specifier in the import statement and the source where the module should be loaded from.

Make sure to place the script with type of importmap before any other scripts on the page that rely on it.

Otherwise, you'd run the code in your index.js file before the module specifiers have been set up.

You can read more about the importmap value of the type attribute in this section of the MDN docs.

# Using an import map with local modules

You can also use an import map when importing local modules.

The example uses the following file structure.

shell
my-project/ └── index.html └── index.js └── module-1.js └── module-2.js

Here is the code for the index.html file.

index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> </head> <script type="importmap"> { "imports": { "m-1": "./module-1.js", "m-2": "./module-2.js" } } </script> <body> <div id="box">bobbyhadz.com</div> <script type="module" src="index.js"></script> </body> </html>
The code for this article is available on GitHub

We defined an import map that maps the m-1 string to the module-1.js file and the m-2 string to the module-2.js file.

Here is the code for the module-1.js file.

module-1.js
export function sum(a, b) { return a + b; }

And here is the code for the module-2.js file.

module-2.js
export function multiply(a, b) { return a * b; }

Finally, this is the code for the index.js file.

index.js
import {sum} from 'm-1'; import {multiply} from 'm-2'; console.log(sum(5, 5)); console.log(multiply(5, 5));

If I issue the npx serve . command and load the page in my browser, I can see that everything works as expected.

using import map with local modules successfully

Want to learn more about importing files in JavaScript? Check out these resources: Import and export Classes and Functions in JavaScript,Import all Exports from a File in JavaScript or TypeScript.

I've also written an article on how to conditionally import ES6 modules in JavaScript.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.