HuasoFoundries/googlemaps-loader

jspm buildStatic not working

Closed this issue · 6 comments

dpix commented

I'm having trouble bundling a static jspm bundle with this library. It errors with this:
TypeError: Global SFX bundle dependency "https://maps.googleapis.com/maps/api/js" must be configured to an environment global via the globalDeps option.

I could add it as a global dependency but I actually want it loaded by SystemJS.

It seems very similar to this issue in a related library HeinrichFilter/systemjs-plugin-googlemaps#5

I used the paths section of config to set "gmaps" resolve to the url.

I declared meta for that url to build = false, and be loaded with my plugin.

If you're planning to redistribute your app, and it is included with a script tag, then it needs to have gmaps object in the global scope. This means you should bundle as

jspm bundle-sfx a + b dist/module.js  --globalDeps { "gmaps" : "gmaps" }
dpix commented

I am using the jspm builder with gulp but effectively the same thing.

my gulp task looks more or less like this:

const Builder = require('jspm').Builder;
const builder = new Builder();

gulp.task(bundle, function(){

    const buildConfig = {
            format: 'global',
            minify: true,
            sourceMaps: true,
            globalDeps: {"https://maps.googleapis.com/maps/api/js" :"gmaps"}
        };

    return builder.buildStatic(moduleName, outFile, buildConfig);
});

However if I do this then I need to load google maps in a separate script tag, and I can't ensure it will be loaded before the rest of my app in the browser.

How can I have gmaps loaded via SystemJS the same way as when I'm not using a bundle?

I believe there are two ways to achieve this. One is to shape your app logic to treat gmaps as a dependency for everything else. All my entrypoints start with something like

define([
  'gmaps', 
  'jquery', 
  'underscore', 
  'backbone'
],function(gmaps, jQuery, _, Backbone) {

     var mymap = new gmaps.Map({ ... });

});

so while I can't guarantee that gmaps will load before jQuery, I do know that inside the function all the dependencies will be loaded.

Using System.import you can grab the promise of google maps api loading:

import jQuery from 'jquery';
import _ from 'underscore';
import Backbone from 'backbone';

System.import('gmaps', __moduleName)
  .then(function(gmaps) {

     var mymap = new gmaps.Map({ ... });

  });

On the other hand, you can use google maps from a script tag. Here's the way to guarantee it will be loaded before your app executes:

<script src="/jspm_packages/system.js"></script>
<script src="/config.js"></script>
<script>
  function startMyApp() {
    System.import('my_app');
  }
</script>
<script src="https://maps.googleapis.com/maps/api/js?callback=startMyApp&key=[YOUR KEY]&v=3.exp"></script>

Which means I:

  • load my config,
  • declare a function that, when called, will start my App
  • insert the google tag with a callback parameter, so it calls my function when he's done

This is a cleaner solution, but introduces a coupling between the html and the script.

PD: perhaps we could summon @guybedford to ask his opinion.

Yes build static support can't workas sfx bundles assume synchronous execution of all built dependencies. Basically we have to just set build: false on this plugin itself and make it purely a non-building plugin.

I guess that the safer way would be to use a google maps script tag and use its callback to init your System.js entry point.