简体   繁体   中英

Loading bundled AMD modules with SystemJS

I have a couple of AMD modules compiled using TypeScript's --outFile option into a single file:

define("partA", ["require", "exports"], function (require, exports) {
    "use strict";
    function partAFunc() {
        console.log('partAFunc');
        return 'partAFunc';
    }
    exports.partAFunc = partAFunc;
});
define("partB", ["require", "exports"], function (require, exports) {
    "use strict";
    exports.partB = 42;
});
define("partC", ["require", "exports"], function (require, exports) {
    ...
});

Now I want to load only the partA module and call its partAfunc() so I can do the following in Node.js:

SystemJS.config({
  map: {
    'main': 'my-bundle.js',
  },
});

SystemJS.import('main').then((m) => {
  SystemJS.import('partA').then((m) => {
    m.partAFunc();
  });
});

The first import SystemJS.import('main') just registers all the modules and then SystemJS.import('partA') works because module partA is already registered (or at least I guess that's what it does).

However, why I can't just use SystemJS.import('partA') and set the bundle as a dependency:

SystemJS.config({
  meta: {
    'partA': {
      deps: [ 'my-bundle.js' ],
    }
  }
});

SystemJS.import('partA').then((m) => {
  m.partAFunc();
});

The meta is completely ignored. The doc at https://github.com/systemjs/systemjs/blob/master/docs/config-api.md#meta says:

Dependencies to load before this module. Goes through regular paths and map normalization. Only supported for the cjs, amd and global formats.

It looks like SystemJS first checks whether the file partA exists (which obviously doesn't) and throws an error (I tested it with an existing file and the meta config worked):

(node:60981) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: ENOENT: no such file or directory, open '/Users/.../partA'
  Instantiating /Users/.../partA
  Loading partA

I'd expect that also the following should work when the first variant works with two nested SystemJS.import calls.

SystemJS.config({
  map: {
    'partA': 'my-bundle.js',
  },
});

SystemJS.import('partA').then((m) => {
  // m.partAFunc();
  console.log(m)
});

This prints an empty object. It looks like when there're more than one module in a single file it just registers them and doesn't load any of them?

I read all the documents in https://github.com/systemjs/systemjs/tree/master/docs but I think I'm still lost.

What you need to do is use the bundles setting and set your bundle like this:

    bundles: {
      'my-bundle.js': ['partA', 'partB', 'partC'],
    }, 

Roughly, this tells SystemJS "when you look for module partA , fetch and execute the module named my-bundle.js and you'll find partA there."


Your approach using meta cannot work. Your meta setting does not say "don't try to fetch a module named partA and instead fetch my-bundle.js " it says "when you process partA , in addition to the dependencies it already has , add my-bundle.js to the list of dependencies." SystemJS will still fetch partA . There's no reason for it to wait until it has executed my-bundle.js before it tries to fetch it, so it launches the fetch immediately and it fails.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM