37

Alright, I have looked on this site and have found several different answers, none of which have worked for me. Basically had a js file that had many functions in it along with the main code for the app. I wanted to move all my functions to another js file so that I could clean up my code a little. I am fairly new to js but I know in python it was as simple as saying "import (module) as (nickname) from (path)"

anyways let's say I have a function named show message in my functions.js module.

export function show_message(){
    alert("Hello");
}

and then I at the top of my main.js file I did

import { show_message } from './functions.js'
//I have also tried to import like this:
import * as func from './functions.js'

//And then I call it
show_message();
//I have also tried
func.show_message();

I know this is something simple, but as I said everywhere I have looked I have seen different answers, none of which work for me. I am using Firefox btw. I am also getting an error in the console saying that my import declarations need to be at the top of my module, I fixed that by specifying the type in my HTML link (script src="/static/main.js" type="module") The error went away but is now saying "same origin policy disallows reading the remote resource at the file (path) (reason: cors request not HTTP)."

And the other error says "module source URI is not allowed in this document".

which makes me think maybe my syntax for importing is right and the error is in my HTML code?

Any help is appreciated.

6
  • I know this is an old question but for anyone else searching: Does this resource help? Not sure which methods you've tried yet stackoverflow.com/questions/5797852/…
    – dan webb
    Commented Dec 12, 2018 at 12:57
  • 3
    Have you tried func.show_message();? Given that you are using import * as func from './functions.js' Commented Dec 12, 2018 at 13:00
  • 3
    This is a CORS relative path issue, not an importing issue.
    – Andrew Li
    Commented Dec 13, 2018 at 2:42
  • There's no such thing as 'import' and export' in pure javascript. Please add aditional tags if you are using another library.
    – A Friend
    Commented Dec 13, 2018 at 5:39
  • stackoverflow.com/a/950146/1675954 as far as the errors re. the module source being disallowed, disable /uninstall your extensions Commented Dec 14, 2018 at 21:26

13 Answers 13

34

0. The short answer

You need to install and run a local web server. - For a suggestion on how, read on.

1. The basics

I tried a simple HTML file – index.html – as follows:

<!-- index.html - minimal HTML to keep it simple -->
<html>
<head>
  <meta charset="UTF-8">
  <link rel="shortcut icon" href="#">
</head>
<body>
  <h1>Hello world!</h1>
  <p>Experimenting with JavaScript modules.</p>
  <script type="module" src="js/functions.js"></script>
</body>
</html>

In the subfolder js I put the JavaScript file functions.js:

// js/functions.js
alert('Hello');

When double-clicking index.html, my default web browser – Firefox 89.0 (64-bit) – shows the following, after pressing F12. Notice how the JavaScript code is not running:

JavaScript not working in browser.

The error message:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at file:///C:/stackexchange/reproduce/jsModule/moduleNW/basics/js/functions.js. (Reason: CORS request not http).

A cheating "solution" is to (temporarily) remove type="module" from the HTML code.
The alert then displays without errors.

But I want to run the JavaScript code as a module, so I put back type="module" in the HTML.

2. Install and run a local web server

To run it as a module, it needs to run on a web server. Thus, if you want to run the code on your own computer, you will need to (install and) start a local web server.
One currently popular alternative is live-server. Here is what worked for me.

  • Open a terminal. (On Windows: cmd.exe.)
  • Type npm and hit Enter to see if Node.js is installed.
  • If you get command not found, download at https://nodejs.org/en/download/ and install. 1
    (On Ubuntu, you can try sudo apt install -y nodejs.)
  • Install live-server: npm install live-server -g.
  • Change directory to where your page lives: cd <path-to-index.html>.
  • Start the server: live-server .
    (Should open localhost:8080 in your default browser and show the alert. See below.)

JavaScript running locally on live-server.

Note 1. I am on Windows 10, but the above instructions should work fine on Linux and macOS too.
Note 2. Here I used Firefox 89.0, but I have tried Google Chrome 91.0 as well. The only notable difference is the CORS error message, which in Chrome reads:
Access to script at 'file:///C:/stackexchange/reproduce/jsModule/basics/js/functions.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https.

3. Exporting and importing

Next I create a new folder demo2 containing the following demo2.html:

<!-- demo2.html - even shorter HTML for simplicity -->
<body>
  <h1>Hello world!</h1>
  <p>Javascript modules.</p>
  <script type="module" src="js/main.js"></script>
</body>

I also create the following three JavaScript files in the subfolder js:

// js/module1.js
export function hi () { console.log('Hi from module 1.'); }

and

// js/module2.js
export function howdy () { console.log('Howdy from module 2!'); }

and

// js/main.js
import { hi } from './module1.js';
import { howdy } from './module2.js';
hi();
howdy();

Now I run live-server from the terminal in the folder where demo2.html resides. This time I start by typing live-server --port=1234 --entry-file=demo2.html and hitting Enter. Screenshot:

JavaScript running when called from several sub-modules.

References:


1 On Windows 10, I once needed to repair the installation.

3
  • I get "live-server : FIle c:\path\to\live-server.ps1 cannot be loaded because running scripts is disabled on this system." :(
    – Sun Bee
    Commented Mar 25, 2021 at 23:45
  • I'm sorry I'm a bit late, but you could run Set-ExecutionPolicy AllSigned or Set-ExecutionPolicy Bypass -Scope Process in PowerShell.
    – Capt 171
    Commented Oct 16, 2021 at 7:53
  • 1
    Thank you ! the post helped a lot ! Commented Nov 17, 2022 at 21:44
12
+25

On the script tag you are using to load the js in the browser you need to add the attribute

type="module"

It will look like the following:

<script type="module">
  import {addTextToBody} from './utils.mjs';

  addTextToBody('Modules are pretty cool.');
</script>

utils.mjs:

export function addTextToBody(text) {
  const div = document.createElement('div');
  div.textContent = text;
  document.body.appendChild(div);
}

This is if you are not using a bundler like webpack and working directly in the browser.

Source of code: https://jakearchibald.com/2017/es-modules-in-browsers/

0
6

You might want to use broswerify instead. It allows you to write NodeJS-style modules and then compiles them into a single browser-friendly JavaScript file, allowing you to get all the performance benefits of loading only a single file. It also means you can easily use the same code both server side and client side.

If you want to stick with separate files, it looks like you are well on your way. Unlike regular JavaScript files, modules are subject to Cross-Origin Resource Sharing (CORS) restrictions. They have to be loaded from the same origin, and cannot be loaded from the local filesystem. If you are loading them from the local file system, move them to a server. If you are already hosting them on a server, add the Access-Control-Allow-Origin: * header to the response that serves the module file.

Lots more gotchas and solutions here and here.

5

Shortcut for Accepted answer

In case you are using Visual Studio Code just install the Live Preview extension by Microsoft.

Live Preview in Visual Studio Code

In any HTML file click the Show preview icon. It will automatically run a local server and show up in the code editor. After every edit you make it refreshes. You can also show it in your default browser.

No need for command line anymore!

3
function show_message(){
    alert("Hello");
}

export { show_message };

and

import { show_message } from './functions'

i think this should do the trick. this is a named export/import technique. you can under this name find more information if you desire it.

3

Consider going through this url some extension might be causing an issue with the loading of modules:

This blog might be an answer to what you're expecting.

You should first check if browser accepts type="module" and use fallback if it doesn't like this:

<script type="module" src="module.mjs"></script>
<script nomodule src="fallback.js"></script>

This might be the main reason for the CORS error as written here:

Unlike regular scripts, module scripts (and their imports) are fetched with CORS. This means cross-origin module scripts must return valid CORS headers such as Access-Control-Allow-Origin: *

So you need to add CORS header to the module file

Consider this blog for CORS issue. You should add CORS header ie. Access-Control-Allow-Origin: * to the server config most probably.

2

JavaScript has had modules for a long time. However, they were implemented via libraries, not built into the language i.e. you can't import or export part of those modules into your js files (whole library needs to be loaded). ES6 is the first time that JavaScript has built-in modules.

Please refer Here for more info about ES modules.

But things have changed and ES modules are now available in browsers! They're in…

Safari 10.1+, Chrome 61+, Firefox 60+, Edge 16+, etc,.

Now, you need to create your JS file using a new extension .mjs, like,

// utils.mjs
export function addTextToBody(text) {
  const div = document.createElement('div');
  div.textContent = text;
  document.body.appendChild(div);
}

and then, you can import that file into your html page like,

<script type="module">
 import {addTextToBody} from './utils.mjs';

 addTextToBody('Modules are pretty cool.');
</script>

Please refer Here for more info about using ES module in browsers.

2

Using JS modules in the browser On the web, you can tell browsers to treat a element as a module by setting the type attribute to module.

<script type="module" src="main.mjs"></script>
<script nomodule src="fallback.js"></script>

More on https://developers.google.com/web/fundamentals/primers/modules

2

If you're using webpack and babel and want to import the code into your bundle, I guess it should be one of the following:

export default function show_message(){
    alert("Hello");
}

and then in your code:

import show_message from 'path/to/show_message.js'
// or 
import { default as someOtherName } from 'path/to/show_message.js'

Or if you'd like to export several functions:

const show_message = function(){
    alert("Hello");
}
export { show_message };

and then in your code:

import { show_message } from 'path/to/show_message.js'
// or 
import { show_message as someOtherName } from 'path/to/show_message.js'

Hope that helps.

0

I know this old thread but I just fixed this problem myself by using Parcel to launch my website Parcel index.html, in my situation I was using Live server and it didn't work until I switched to parcel .

0

Instead of using .js, try using .mjs. Let's say your module file is /modules/App.js, just change it to /modules/App.mjs. And ofcourse, make sure you have added type="module" in script tag, like this - <script type="module" src="./index.js" defer></script>

My folder structure -

index.html
index.js
modules/App.mjs

This worked for me!

1
  • scripts of type="module" are automatically deferred Commented Feb 16, 2022 at 13:20
0

Write your script in the html page. Example index.html

https://pastebin.com/2y8C87SD

<head>
   <meta charset="UTF-8">
   <title>React + htm Demo</title>
   
   <script src="https://unpkg.com/[email protected]" crossorigin></script>
   <script src="https://unpkg.com/react@16/umd/react.production.min.js" crossorigin></script>
   <script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js" crossorigin></script>
   
   <script type="module">
   const { createElement, useState } = React;
   const render = ReactDOM.render;
   const html = htm.bind(createElement);
   
   function ClickCounter() {
     const [count, setCount] = useState(0);
     
     return html`
       <div>
         <button onClick=${() => setCount(count + 1)}>
           Clicked ${count} times
         </button>
       </div>
     `;
   }
   
   render(html`<${ClickCounter}/>`, document.getElementById("App"));
   </script>
</head>

<body>
   <h1> React + htm Demo</h1>
   <div id="App"/>
</body> 

Source

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules

https://www.w3schools.com/js/js_modules.asp

https://javascript.info/modules-intro

https://www.sitepoint.com/using-es-modules/


-1

Use a filename with extension .mjs instead of .js in a script like this:

<script type='module' src='main.mjs'></script>

That worked for me.

Not the answer you're looking for? Browse other questions tagged or ask your own question.