Search code examples
javascriptsystemjsjspm

Load JS modules conditionally (SystemJS)


I am currently using jspm and SystemJS to load ES6 modules. However, I would like to be able to

  • Scan the page for certain selectors (e.g., id, data-plugin)

  • Map these selectors to their module dependencies

  • Load only those modules

My thought was to handle these imports through the single entry point, System.import('src/main'), that has access to the document. I could then find the relevant selectors, map those selectors to modules, and then import those modules.

src/main would look something like this:

['d3', 'jquery'].forEach(function(dependency) {
    import dependency;
});

This is not a viable solution as it is invalid syntax. Is there a better way to achieve dynamic module loading in this sense?


Solution

  • Normal import syntax can't be used to conditionally load modules, as you've already seen. To get around this, we can use the programmatic API provided by System. You're already familiar with this API, since you use it to System.import('src/main');.

    To conditionally load modules, instead of using the import keyword, you just have to continue using the System.import method.

    An example of this:

    index.html

    <!DOCTYPE html>
    <html>
    <head>
      <script src="jspm_packages/system.js"></script>
      <script src="config.js"></script>
    </head>
    <body>
      <div id='one'>One</div>
      <div>Two</div>
    
      <script>
        System.import('main');
      </script>
    </body>
    </html>
    

    main.js

    const map = {
      '#one': 'one',
      '#two': 'two'
    };
    
    for (let selector in map) {
      if (document.querySelector(selector)) {
        System.import(map[selector]);
      }
    }
    

    one.js

    window.HAS_ONE = true;
    

    two.js

    window.HAS_TWO = true;
    

    In this example, window.HAS_ONE would be defined, but window.HAS_TWO would remain undefined.