0

I've tried to read up on JavaScript modules, but I'm still not clear on one thing: assume the following minimal HTML example:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
  <title>Test</title>

  <script type="module">
  export function hello() {
    console.log("hello");
  }
  </script>

</head>
<body>
</body>
</html>

Let's say I load this in my browser via file:///C:/tmp/test.html - it is the file:// protocol, yes, but there is no .js file being loaded, as the script is embedded, so CORS should not be a problem (and I don't get a Console JavaScript error either).

So let's say, I load this page in Firefox 115, and I open the Console/JavaScript Debugger. No "hello" is accessible by default:

>> hello
Uncaught ReferenceError: hello is not defined
    <anonymous> debugger eval code:1

... and I cannot "import" or "require":

>> import { hello }
Uncaught SyntaxError: import declarations may only appear at top level of a module

>> require("hello")
Uncaught ReferenceError: require is not defined
    <anonymous> debugger eval code:1

(maybe require needs a library, but as you can tell, I'm not really a JavaScript guru)

So - is there anything I can do with my <script type="module"> from "normal" JavaScript (that is, either <script> which is not type="module" - or direct commands in JavaScript Debugger/Console), without explicitly saying window.hello = hello; at the end of the module code?

sdbbs
  • 4,270
  • 5
  • 32
  • 87
  • 1
    You're not too far, but not exactly right. I'd suggest reading https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules – WilomGfx Jul 18 '23 at 02:00
  • 2
    What are you trying to do? Your script is loaded into the browser; there's nowhere to `export` to. You can create a global value to expose symbols from the script to other scripts on the page. – Pointy Jul 18 '23 at 02:04
  • 2
    Generally you make an inline script a module because you want to **import** something, not export. Recall that `import` needs a "from"; there's no "from" for a script like yours. – Pointy Jul 18 '23 at 02:05
  • 1
    Related answer: https://stackoverflow.com/a/44355041/188331 – Raptor Jul 18 '23 at 02:07
  • Thanks all: "I'd suggest reading" - did that, but it mostly deals with import/export to/from modules, not with interaction of "normal" script and module; "What are you trying to do?" understand if there is an interaction between "normal" script and module or not. Just an explicit statement "No - a normal script cannot interact with a module, unless the module exports global (window.) variables" would be good enough for me (if it is indeed true). – sdbbs Jul 18 '23 at 02:09

1 Answers1

0

It's a losing battle.

  • You can inline a script of type module in HTML successfully and create exports. Well you can go through the motions and console.log that the script ran without error.

  • You can inline a script of type module and execute an import statement, but at this point the fun begins:

    • Attempts to import an inline module that exports something fail because the inline module has no module-name associated with it.

    • Ok, so put code for the exporting module code in a file called test-module.js, in the same folder as the HTML file and try importing it in a script inlined in the HTML

        <script type="module">
        import {x} from "./test-module.js";
        console.log("x from xmodule = ", x);
        </script>
    

    At this point the module loader does attempt to load the file using CORS. And generates the following error:

    ❌ Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at file:///html-path/test-module.js. (Reason: CORS request not http).

    An explanation of the error reason is given on MDN but essentially CORS does not support any protocols other than http:// or https://.

Battle lost I believe.

The work around commonly suggested is to install a localhost server to run and load all module testing code from, which can be frustrating in use and unsuited for projects that are intended to work off-line. I am unaware of any attempts to provide support for ES6 module access when using the file:// protocol. Not even the ability to give an inline script of type module a module-name attribute.

traktor
  • 17,588
  • 4
  • 32
  • 53