34

I want to access data from script tag in html file, produced by cms. Is it possible to do this without polluting global namespace? I've tried to use es6 modules but I've failed and I couldn't find any info about it.

    <script>
        let list = ['a','b','c'];
        export default list
    </script>
    //test.js
    import list from './index.html' 

Error: 'http://localhost:8080/index.html net::ERR_ABORTED 404' or: 'Failed to load module script: The server responded with a non-JavaScript MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.'

2
  • you can use var to declare the variable so it will be accessible from another files. Commented Apr 5, 2021 at 16:15
  • I'm sure I saw somewhere example how to do that for web-component . but not found the reference Commented Sep 8, 2022 at 23:47

5 Answers 5

25

No, doing that isn't covered by the HTML specification yet¹ (and I suspect it never will be²). (If it were, you'd still need type="module" on your first script tag.) There's no module specifier that specifies a script element in an HTML page. At the moment, the only module specifiers are URLs for JavaScript files. Details in the spec.

Instead, you probably want something like this:

<script type="module">
import { setList } from "./test.js";
setList(['a', 'b', 'c']);
</script>

...where test.js exports a named export that lets you tell it what list to use.

(Or of course, it could be a default export.)

Inline script type="module" tags can import, but while they can use export, nothing can make use of the exports they create because they have no useful module specifier.


¹ It's the HTML spec because the form and semantics of module specifiers are left to the host environment by the JavaScript spec (details here). All that the JavaScript spec says about them is that they're string literals.

² It certainly could be, for instance using fragment identifiers. But with HTTP/2 multiplexing making discrete resource loading so fast compared with HTTP/1.1 (and esp. vs. HTTP/1.0), the impetus to make everything contained in a single resource is dramatically lower now than it was some years ago.

Sign up to request clarification or add additional context in comments.

Comments

7

You can't export JS from HTML. You can import it however, using the type="module" attribute on the <script> tag:

<script type="module">
  import list from "./test.js";
  //Use list
</script>

Comments

3

I also asked myself the same question and found your topic. But then a simple solution came to mind.

// buffer.js
    export default let buffer={};
// index.html
<script type="module">
    import buffer from './buffer.js';
    buffer.helloWorld='hello world';
</script>
....
<script type="module">
    import buffer from './buffer.js';
    console.log(buffer.helloWorld);
</script>

1 Comment

Noticed negative votes. The this answer is 4 years old, and perhaps something has changed in browsers that this method has stopped working for you. Please report any shortcomings in the comments if you don’t like something or don’t work.
0

I had an... interesting... use case at my company where I had to import functions from a file, but the script tag couldn't be a module.

The script tag creates a new script tag in the dom with type = module, which imports an object containing each function. For each of the functions we run window.myFunction = myFunction to allow them to be used from the dom.

HTML:

<script>
    ((path = "./importme.js", fileId = "importme") => {
        if (document.getElementById(fileId)) return;
        let tag = document.createElement("script");
        tag.type = "module";
        tag.id = fileId;
        tag.innerHTML =
            'import codeFromFile from "' +
            path +
            '"; Object.keys(codeFromFile).forEach(k => { window[k] = codeFromFile[k] });';
        document.body.appendChild(tag);
    })();
</script>
<button onclick="testFunction()">Click me</button>

./importme.js

function testFunction() {
    alert("Test Function");
}

export default { testFunction };

Alternatively, if you just want to run what's in the imported file you could do this:

HTML:

<script>
    ((src = "/importme.js", fileId = "importme") => {
        if (document.getElementById(fileId)) return;
        let tag = document.createElement("script");
        tag.id = fileId;
        tag.src = src;
        document.body.appendChild(tag);
    })();
</script>
<button id="click">Click me</button>

./importme.js (wrap everything in the exported anonymous function)

window.onload = () => {
    document.getElementById('click').onclick = e => {
        alert('Element clicked!');
    };
};

This is a bad way to do things, only for a worst-case scenario. This answer is food for thought, please don't do this... My company found a way to get around this in the end.

1 Comment

How did you managed to get around this? I am in a similar situation. With Create React App, it is difficult to import apart from making a dependency a package or keep a local copy.
-1

You can simply use a global variable like so:

  • In your HTML file:
 <script>var myGlobalVar = "foo";</script>
  • In your JS file before enqueuing your script:
/* global myGlobalVar */

alert(myGlobalVar);

Then you can use your variable in the JS file.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.