jspm buildStatic not working
Closed this issue · 6 comments
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" }
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.