How to import a Javascript module in plain HTML? - javascript

my situation is as follows:
I want to try out some components from the Azure Communication Services UI Library: (https://azure.github.io/communication-ui-library/?path=/docs/quickstarts-composites--page).
The thing is: I want to use them in codebase that is kind of legacy (let's say an older version of ASP.NET), so there is no way I can import the modules in a React/Angular-way. I would probably need to import them in plain HTML.
My idea was: I can create a separate 'site.js' file, import the module in there and load this in the main _Layout.cshtml.
I wrote this script:
// TODO: How can we import this module?
import { Chat } from "#azure/communication-chat";
const chat = new Chat({
auth: {
token: "Your token here"
},
conversationId: "Your conversation Id here",
});
const chatContainer = document.getElementById("chat-container");
chat.render(chatContainer);
And then imported the script like this:
<script src="~/js/site.js" asp-append-version="true"></script>
But that gives me the error: "Uncaught SyntaxError: Cannot use import statement outside a module".
Apparently it is not possible this way.
So my question is: Is it possible at all? What other ways are there to try?

You need to source your JS as a module, which requires adding type="module" to the script node:
<script src="~/js/site.js" type="module" asp-append-version="true"></script>
Taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules#applying_the_module_to_your_html. The whole page is probably worth reading.
You can only use import and export statements inside modules, not regular scripts

Related

Javascript library without using an import in the script tag

I try to create a library using typescript and I would like to use a static method that allows me to render some HTML content that is returned to me by an api rest call based on the parameters I pass to that function now there is a way to create it using a architecture eg pattern repository, compile it and then use it as in the code below (in js format of course)?
<div id="test"></div>
<script scr="../myLybrary.js"></script>
<script type="module">
MyLibrary.render({
param: "test",
param1: "test",
param2: "test"
}, "test")
</script>
at the moment to create this situation I have to use an import in the script where the call to the static method resides in this way:
import MyLibrary from './myLybrary.js'
is there any way to avoid this last step?
Thanks to anyone who wants to help me.
at the moment to create this situation I have to use an import in the script where the call to the static method resides in this way:
import MyLibrary from './myLybrary.js'
That would generally be the right thing to do. You'd just remove the first script tag, since with it you'll end up loading your library twice. So that leaves us with:
<div id="test"></div>
<!-- Note: No `script` tag for `myLybrary.js` here. -->
<script type="module">
import MyLibrary from "./myLybrary.js";
MyLibrary.render({
param: "test",
param1: "test",
param2: "test"
}, "test");
</script>
Loading a module runs the top-level code in the module, so if myLybrary.js has top-level code that loads some resource, that code will be run when the import declaration is processed.

Why Stats.min.js can only be imported by `script src=` but not `import`?

I have Javascript codes as below. When the importation is inside <script src="..."></script>, it works. However, if I moved the importation to import ...;, it doesn't work. The error message is: "Uncaught ReferenceError: Stats is not defined".
Why is that? Since I am working on a Jekyll site, I prefer to do the import ...; way to make sure other elements of the site work. Any idea how to do the import ...; way without error?
It works
<div id="stats"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stats.js/r16/Stats.min.js"></script>
<script type="module">
const stats = new Stats()
stats.setMode(0)
document.getElementById('stats').appendChild(stats.domElement)
</script>
It doesn't work
<div id="stats"></div>
<script type="module">
import 'https://cdnjs.cloudflare.com/ajax/libs/stats.js/r16/Stats.min.js';
const stats = new Stats()
stats.setMode(0)
document.getElementById('stats').appendChild(stats.domElement)
</script>
import allows you to import JavaScript modules which conform to the ES6 module format.
Stats.min.js does not. The code is obfuscated but appears to create a global and support the old CommonJS module format.

import a library into a single file component of vue.js

I need to import a library in my vue component, in the documentation I explain how to install it using npm (already do this step) but not how to import it into a vue component, this is the way in which it explains how to use the files:
<link href="node_modules/webdatarocks/webdatarocks.min.css" rel="stylesheet"/>
<script src="node_modules/webdatarocks/webdatarocks.toolbar.min.js"></script>
<script src="node_modules/webdatarocks/webdatarocks.js"></script>
and this is the way to instantiate the library:
<script>
var pivot = new WebDataRocks({
container: "#wdr-component",
toolbar: true,
report: {
dataSource: {
filename: "https://cdn.webdatarocks.com/data/data.csv"
}
}
});
</script>
So what is the best way to call this in my component?
This is a bit heavy.
The library is is not develop in module-like system, so the solution is make the js file imported as global.
A good library would be like const WebDataRocks = require("WebDataRocks"); or with imports, but the library is made only for end-client.
First Part - Add the JS file to the global web client
To use WebDataRocks you have to get the global variable, to get the global variable you have to inyect, as common javascript on html but with webpack.
Here are a solution for this
Webpack - How to load non module scripts into global scope | window
You have to do this for webdatarocks.toolbar.min.js and webdatarocks.js
Second Part - Add the CSS
You have some options, the easy way i found to do this is use require in your <script> zone:
require('../node_modules/webdatarocks/webdatarocks.js')
Good luck! 😁
If something fails check the paths and let us know more information about it
Alternative solution (But worse)
If you are going to use this script in a internet system, you could insert the script and CSS in the HTML. For this do:
Open index.html
Add this code on the head section:
<link href="https://cdn.webdatarocks.com/latest/webdatarocks.min.css" rel="stylesheet"/>
<script src="https://cdn.webdatarocks.com/latest/webdatarocks.toolbar.min.js"></script>
<script src="https://cdn.webdatarocks.com/latest/webdatarocks.js"></script>
Rebuild
Extracted from WebDataRocks React Example
Important! this is unsafe ☣ ⚠
Make this only if you are sure about what this mean
If the webdatarocks CDN's fails, your app will also fails.
Hope it helps :)
I did this and it works:
import WebDataRocks from 'webdatarocks'
import '#/../node_modules/webdatarocks/webdatarocks.min.css' // # is resolved to src/ folder
I didn't import the toolbar as I don't need it:
WebDataRocks({
container: '#pivot',
toolbar: false,
...
})

Can't figure out how to import modules in browser with javascript

This is a simple problem. I'm attempting to import modules from one javascript file to another, and then run it on Chrome. I'm using 2 javascript files and an html file, all in the same folder:
first js file (testfile1.js):
import {test} from 'testfile2.js';
test.func();
second js file (testfile2.js):
let f = function() {
console.log("TEST");
}
let test = {
func: f
};
export test;
The html file is plain, empty html file with a link to testfile1.js script in the header:
<script type="text/javascript" src="testfile1.js"></script>
Whenever I open the html file in chrome, I get the error:
testfile1.js:1 Uncaught SyntaxError: Unexpected token {
When I removed the brackets in the import statement, I get an unexpected identifier statement. Isn't this the proper way to import modules in the browser? Why is it not working at all?
Modules require type="module" not "text/javascript"
As per Jaromanda X's comment, you need to change the value of the type attribute of the <script> tag to "module" as import { test } from 'testfile2.js' is module code.
<script type="module" src="testfile1.js" />
What about dynamic import()
If you really don't feel like using type="module", any javascript file is allowed to use the dynamic import() syntax, even without type="module".
However, the dynamic import has a caveat, the function import() returns a promise, therefore, you are unable to use it synchronously. You must either await or .then a dynamic import to use the value it resolves to.
import('testfile2.js').then(({ test }) => {
// your code
});

How to import es6 module that has been defined in <script type="module"> tag inside html?

I am able to define a module in my html file me.html:
<script type="module" id="DEFAULT_MODULE">
import Atom from './atom.js';
console.log("definition of getAtom")
export default function getAtom(){
return new Atom('atom');
}
console.log("exported getAtom")
</script>
Also see
https://blog.whatwg.org/js-modules
https://github.com/whatwg/html/pull/443#issuecomment-167639239
=> Is it possible to import that "anonymous" module to another module script in the same html file? Or to some "code behind"- JavaScript file that also has been loaded by the me.html file? The export seems to work; at least it does not throw any error.
For the import of the getAtom method I tried for example:
<script type="module">
import getAtom from '.'; //this line does not work
console.log("usage of getAtom")
var atom = getAtom();
</script>
I would expect some syntax like
import getAtom;
import getAtom from '.';
import getAtom from window;
import getAtom from './me.html';
import getAtom from '.DEFAULT_MODULE';
However, none of these lines worked.
=>What is the correct syntax to reference the "anonymous" module if it is possible at all?
I use Chrome version 63.0.3239.108.
Related question:
How to dynamically execute/eval JavaScript code that contains an ES6 module / requires some dependencies?
As I understand, there is no way to import "anonymous" module, because "anonymous" module have no module specifier or individual url (its import.meta.url is just the html url as current spec). In theory it can be extended in the future, but I can not find the good use cases for such feature.

Categories