There are limitations in the import
syntax that make it difficult to do if not impossible without using external libraries.
The closest I could get is by using the Dynamic Import syntax. Two examples follow: the first one is the original I wrote while the second one is an edit from a user that wanted to modernize it.
The original one:
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<script>
var moduleData = "export function hello() { alert('hello'); };";
var b64moduleData = "data:text/javascript;base64," + btoa(moduleData);
</script>
<script type="module">
async function doimport() {
const module = await import(b64moduleData);
module.hello();
}
doimport();
</script>
</body>
</html>
The modernized one:
function doimport (str) {
if (globalThis.URL.createObjectURL) {
const blob = new Blob([str], { type: 'text/javascript' })
const url = URL.createObjectURL(blob)
const module = import(url)
URL.revokeObjectURL(url) // GC objectURLs
return module
}
const url = "data:text/javascript;base64," + btoa(moduleData)
return import(url)
}
var moduleData = "export function hello() { console.log('hello') }"
var blob = new Blob(["export function hello() { console.log('world') }"])
doimport(moduleData).then(mod => mod.hello())
// Works with ArrayBuffers, TypedArrays, DataViews, Blob/Files
// and strings too, that If URL.createObjectURL is supported.
doimport(blob).then(mod => mod.hello())
You will however notice that this has some limitations on the way the import code is constructed, which may not precisely match what you need.
The simplest solution is probably to send the code of the module on the server for it to generate a temporary script to be then imported using a more conventional syntax.