Import a module from string variable

11,465

Solution 1

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. An example follows:

<!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>

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.

Solution 2

Use nodejs flag --experimental-modules to use import ... from ...;

node --experimental-modules index.mjs
index.mjs:
import fs from 'fs';
let fileContents = "export function doSomething(string) { return string + '-done'; };"
let tempFileName = './.__temporaryFile.mjs';

fs.writeFileSync(tempFileName, fileContents);
console.log('Temporary mjs file was created!');

import(tempFileName)
    .then((loadedModule) => loadedModule.doSomething('It Works!'))
    .then(console.log)


Further reading here

How It Works:

  1. I first create the file with fs.writeFileSync
  2. then I use import method's promise to load module and
  3. pipe doSomething method call with "It Works!"
  4. and then log the result of doSomething.

Credits: https://stackoverflow.com/a/45854500/3554534, https://v8.dev/features/dynamic-import, @Louis

Solution 3

You can create component and Module on fly. But not from string. Here is an example:

name = "Dynamic Module on Fly";
const tmpCmp = Component({
  template:
    '<span (click)="doSomething()" >generated on the fly: {{name}}</span>'
})(
  class {
    doSomething(string) {
      console.log("log from function call");
      return string + "-done";
    }
  }
);
const tmpModule = NgModule({ declarations: [tmpCmp] })(class {});

this._compiler.compileModuleAndAllComponentsAsync(tmpModule).then(factories => {
  const f = factories.componentFactories[0];
  const cmpRef = this.container.createComponent(f);
  cmpRef.instance.name = "dynamic";
});

Here is the stackblitz

Share:
11,465

Related videos on Youtube

Guru Kara
Author by

Guru Kara

I convert caffeine into code :)) SOreadytohelp

Updated on September 14, 2022

Comments

  • Guru Kara
    Guru Kara over 1 year

    I need to import a JavaScript module from an in memory variable. I know that this can be done using SystemJS and Webpack.

    But nowhere can I find a good working example nor documentation for the same. The documentations mostly talks of dynamic import of .js files.

    Basically I need to import the module like below

    let moduleData = "export function doSomething(string) { return string + '-done'; };"
    //Need code to import that moduleData into memory
    

    If anyone can point to documentation that will be great

    • bubblez
      bubblez almost 5 years
      Do you have babel in your toolchain already? If so, I guess you already have something like webpack.js.org/loaders/babel-loader where you can configure plugins. Now, I did not find any plugin suiting your needs. But using babel-generator to parse and generate code (babeljs.io/docs/en/babel-generator) and this docs github.com/jamiebuilds/babel-handbook you may write your own plugin.
    • Louis
      Louis almost 5 years
      This Q has the feel of an XY problem. I've used module loaders and module bundlers with JavaScript for years, and contributed to relevant projects, but never ever have I run into a problem that required a solution entailing importing a string as a module. There have been cases where I could have solved my problem by doing this, but there were better solutions available. The way the question is currently written though, we don't know the X part of the XY problem. Why must the module be imported from a string containing the source of the module?
  • Kashkashio
    Kashkashio almost 5 years
    eval is your solution here tough it is not recommended to use it. w3schools.com/js/js_best_practices.asp read some more about it here
  • Grzegorz T.
    Grzegorz T. almost 5 years
    eval = evil good explanation
  • Louis
    Louis almost 5 years
    The objection "eval = evil" is not a good one when it comes to dealing with executing module code. The default mode of operation of SystemJS, Webpack, RequireJS and any other JS module loader I've used is to run the code with the exact same privileges as doing eval would. In other words, require("foo") is not any safer than fetching the source of the module foo and then evaling it. Some module loaders even have eval(sourceOfModule) as part of the module loading process. This being said, eval won't handle the OP's export statement and so it not enough to do what the OP wants.
  • Louis
    Louis almost 5 years
    Post-edit, this answer is still not hitting the mark. Do a search for "es6 dynamic import". Static imports may be hoisted but dynamic imports are not hoisted. I don't think dynamic imports are implemented to allow passing to the import() call a module's source code, but there's could be a plugin for SystemJS or Webpack that allows it. Even if such plugin does not currently exist, I'm sure one could be developed. I would not call what the OP wants to do "impossible".
  • pegasuspect
    pegasuspect almost 5 years
    @Louis yes you were right. I got the answer by searching google about the message. I will include the source as well. Thank you!
  • Guru Kara
    Guru Kara almost 5 years
    Wont work We let the users create the module also on Fly
  • Guru Kara
    Guru Kara almost 5 years
    Basically we have an Angular App, where in we let users create Angular components including HTML Template, TS file and CSS. Once they type those we need to compile and load that in same Angular App. We have figured out how to merge and compile the HTML TS and CSS into a JS module, now the loading part is left
  • Guru Kara
    Guru Kara almost 5 years
    Basically we have an Angular App, where in we let users create Angular components including HTML Template, TS file and CSS. Once they type those we need to compile and load that in same Angular App. We have figured out how to merge and compile the HTML TS and CSS into a JS module, now the loading part is left
  • jhpratt
    jhpratt almost 5 years
    That is absolutely not dynamic.