Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bundle inject (not) using mapped paths #1313

Closed
sergei-maertens opened this issue Jun 13, 2016 · 5 comments
Closed

Bundle inject (not) using mapped paths #1313

sergei-maertens opened this issue Jun 13, 2016 · 5 comments

Comments

@sergei-maertens
Copy link

Versions:

  • jspm 0.17-beta.17
  • SystemJS 0.19.29 (same with 0.19.31)

Confirmed working versions:

  • jspm 0.17-beta.12
  • SystemJS 0.19.25

Relevant config:

// jspm.config.js
SystemJS.config({
  paths: {
    "npm:": "jspm_packages/npm/",
    "github:": "jspm_packages/github/",
    "imtool/": "js/"
  },
  packages: {
    "imtool": {
      "format": "esm",
      "main": "main.js",
      "meta": {
        "*.js": {
          "loader": "plugin-babel",
          "babelOptions": {
            "plugins": [
              "babel-plugin-transform-react-jsx",
              "babel-plugin-transform-class-properties"
            ]
          }
        }
      }
    }
  }
});
// jspm.browser.js
SystemJS.config({
  baseURL: "/static",
  bundles: {
    "SYSTEMJS/build/router.js": [
      "imtool/router.js",
      "imtool/projects/ProjectSetupView.js",
      "imtool/projects/project-setup.js",
      ...
  }
});

Watch bundle created with:

jspm bundle imtool/router.js staticfiles/SYSTEMJS/build/router.js -wid

Observed behaviour (in system.src.js, hook('locate', ...) w/r to bundles:

The load.name is normalize to "http://localhost:8000/static/js/router.js", while the bundle entry is "http://localhost:8000/static/imtool/router.js". Obviously these two don't match, causing the bundle not to be injected.

The requested resource URL is fine, it feels that the bundle-configuration should apply the path mapping (might be related to #1230).

On beta.12, it seems like the bundle config is loaded anyway, in my debugger it seems to be the first hit anyway.

@guybedford
Copy link
Member

Can you try this in 0.17.0-beta.21?

So it's fetching the bundle file, and then requesting the module again? Or is it not even requesting the bundle to begin with?

The names in the bundle config look correct, if they're the same names used in the bundle itself that all sounds right to me. Then just ensuring the configuration is loaded before the bundle as well.

@sergei-maertens
Copy link
Author

Same thing with .21. On .12 it appears that the bundles themselves are
always loaded first, even before a bundled module was requested.

It's not fetching the bundle file - the lookup starts for one of my
modules, say 'imtool/router.js'. This gets normalized to
http://localhost:8000/static/js/router.js, but the normalized bundle config
contains http://localhost:8000/static/imtool/router.js. It never matches,
so the bundle file is never loaded.

Currently on mobile, in two hours or so I can show some more code that is
our current workaround.
On Jun 15, 2016 1:20 AM, "Guy Bedford" notifications@github.com wrote:

Can you try this in 0.17.0-beta.21?

So it's fetching the bundle file, and then requesting the module again? Or
is it not even requesting the bundle to begin with?

The names in the bundle config look correct, if they're the same names
used in the bundle itself that all sounds right to me. Then just ensuring
the configuration is loaded before the bundle as well.


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
#1313 (comment),
or mute the thread
https://github.com/notifications/unsubscribe/AFQ01mWJt7CpZBANwoWzyyy5vHXUfTbrks5qLzdQgaJpZM4I0JnH
.

@sergei-maertens
Copy link
Author

So, our current workaround looks like this:

<script>
  for (var b in SystemJS.bundles) {
    for (var i=0; i<SystemJS.bundles[b].length;i++) {
      SystemJS.bundles[b][i] = SystemJS.bundles[b][i].replace('/imtool/', '/js/');
    }
  }
</script>

after including the config files, ofcourse.

This is confirmed to work.

The problematic check is, in system.src.js (v0.19.31, jspm 0.17-beta.21), starting around line 4959

/*
  System bundles

  Allows a bundle module to be specified which will be dynamically
  loaded before trying to load a given module.

  For example:
  SystemJS.bundles['mybundle'] = ['jquery', 'bootstrap/js/bootstrap']

  Will result in a load to "mybundle" whenever a load to "jquery"
  or "bootstrap/js/bootstrap" is made.

  In this way, the bundle becomes the request that provides the module
*/

(function() {
  // bundles support (just like RequireJS)
  // bundle name is module name of bundle itself
  // bundle is array of modules defined by the bundle
  // when a module in the bundle is requested, the bundle is loaded instead
  // of the form SystemJS.bundles['mybundle'] = ['jquery', 'bootstrap/js/bootstrap']
  hookConstructor(function(constructor) {
    return function() {
      constructor.call(this);
      this.bundles = {};
      this._loader.loadedBundles = {};
    };
  });

  // assign bundle metadata for bundle loads
  hook('locate', function(locate) {
    return function(load) {
      var loader = this;
      var matched = false;

      if (!(load.name in loader.defined))
        for (var b in loader.bundles) {
          for (var i = 0; i < loader.bundles[b].length; i++) {
            var curModule = loader.bundles[b][i];

            if (curModule == load.name) {
              matched = true;
              break;
            }

            // wildcard in bundles does not include / boundaries
            if (curModule.indexOf('*') != -1) {
              var parts = curModule.split('*');
              if (parts.length != 2) {
                loader.bundles[b].splice(i--, 1);
                continue;
              }

              if (load.name.substring(0, parts[0].length) == parts[0] &&
                  load.name.substr(load.name.length - parts[1].length, parts[1].length) == parts[1] &&
                  load.name.substr(parts[0].length, load.name.length - parts[1].length - parts[0].length).indexOf('/') == -1) {
                matched = true;
                break;
              }
            }
          }

          if (matched)
            return loader['import'](b)
            .then(function() {
              return locate.call(loader, load);
            });
        }

      return locate.call(loader, load);
    };
  });
})();

In the example of the previous post, load.name equals to http://localhost:8000/static/js/router.js, while the matching entry in the bundle config (curModule variable) is http://localhost:8000/static/imtool/router.js. So, it looks like the translation from imtool -> js should be done when injecting the bundle, or the actual browser url resolution happens to soon (postpone imtool -> js translation until effectively fetching the module).

@guybedford
Copy link
Member

The reason for this is that the bundle configuration needs to be provided at the same time as the paths configuration so adding paths: { 'imtool/': 'js/' } in the jspm.browser.js file itself is necessary here.

The normalization in SystemJS is all correct but I've added a fix in jspm to ensure that a separate browser configuration file will always include the paths as well - jspm/jspm-cli@af2cf93.

@sergei-maertens
Copy link
Author

Yes, that may have been the cause, since I remember the paths config being in jspm.browser.js, but after the upgrade, the config files are rewritten and the paths config is moved to jspm.config.js. Thanks for the effort and investigation!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants