javascriptangularwebpacksystemjs

Can I dynamically import a JS module that uses rxjs into an Angular App


I have built an application with Angular 12.

I have a JS module called dynamic_module.js which is not available at build time which I want to import and use in the app. However, dynamic_module.js uses rxjs and other imports - all of which are already used in the Angular application and so included in the built webpack. dynamic_module is not an Angular / webpack artifact or anything complicated - it is a simple JavaScript file located on the same server but not available at build time .

When I try to import "dynamic_module.js" using the import(<path_to_dynamic_module.js> ) function - (I'm assuming this method is hi-jacked by webpack) I get an error:

"Error: Cannot find module '<path_to_dynamic_module.js>' ".

I expected this because the dynamic_module.js is not available when the app was built.

So, I tried the method of inserting a <script> element into the header -

e.g. <script type="module" src="<url_of_dynamic_module.js>"></script>

this loads the module but reports the error :

Failed to resolve module specifier "rxjs". Relative references must start with either "/", "./", or "../".

I also tried this without the import of rxjs in the module, and it works ok.

And if I try using SystemJS with the babel transpiler and try to import the dynamic_module.js, I get an error when System JS tries to load the rxjs module it goes to http.

Error: Fetch error: 404 Not Found Instantiating http://localhost:4400/rxjs

This also works when the import is removed from dynamic_module.js.

My question is : Can modules dynamically loaded with SystemJS (or any other method) import other modules that are already loaded by webpack - without duplication or reloading via http?

If this is not possible, I could make all the necessary module files available via http for SystemJS to load (I have done this with the 'babel' transpiler modules for SystemJS) . Would that cause two copies of the modules (ie. rxjs in this example) to be loaded into the browser - could this be a serious problem (space/performance/clashes ...)?

Here is a very simple example of the module - this can load by any method if the import is removed, but fails in if the import is included.

dynamic_module.js

import { Observable} from 'rxjs';
export class MyClass{
   hello( msg ) { 
     console.log('[MODULE] Hello World');
     console.log(msg);
   }
}

Thanks for any advice!


Solution

  • Ok, after some research I have solved my problem:

    Let me describe concisely what the issue I had was:

    The solution is to let SystemJS know in advance that the dependencies are already available. This is done using the SystemJS.set() method: for example in my case the key steps were:

    import * as rxjs from "rxjs";
    
    SystemJS.set('rxjs', SystemJS.newModule(rxjs));
    
    SystemJS.import( <url_of_module> ).then( module=>.....});