-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
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
modules, globals, and plugins #2364
Comments
@sheppard hmm, good question... Maybe not exposing a global variable is not worth it if you have to enforce something on plugins that otherwise don't work. Besides, for people that don't want the global var, it's enough to call |
I actually would suggest keeping the new structure and dealing with any issues that arise on a case-by-case basis. The global is just one of various issues that come from mixing modules with non-modular code, and the best long term fix is always to add module definitions to any files that don't have them. I guess it's not clear to me how many people:
Only users who have all three characteristics should be affected by this issue. As long as there is a clear answer for any issues that come up things should be fine. I personally think standardizing on UMD is logical extension to the existing rule "Never expose global variables in your plugin." However, if you don't want to enforce UMD on plugin maintainers, we could suggest various workarounds for users in the above group:
// leaflet-global.js
define(['leaflet'], function(L) {
window.L = L;
return L;
}); |
As a point of reference, d3 recently went directly from only exporting a global, to declaring a private module if an AMD loader is present. Initially, there were some issues by third party users (d3/d3#1693) but it seems they were sorted out relatively quickly. |
Here's a potential UMD wrapper for an arbitrary Leaflet plugin: (function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['leaflet'], factory);
} else if (typeof module !== 'undefined') {
// Node/CommonJS
module.exports = factory(require('leaflet'));
} else {
// Browser globals
if (typeof this.L === 'undefined')
throw 'Leaflet must be loaded first!';
factory(this.L);
}
}(function (L) {
L.MyPlugin = {
/* ... */
};
return L.MyPlugin;
})); |
Tacking methods and classes onto the |
I agree there wouldn't be a need to use the L namespace - particularly if a module system was in use. To modify the above example: (function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['leaflet'], factory);
} else if (typeof module !== 'undefined') {
// Node/CommonJS
module.exports = factory(require('leaflet'));
} else {
// Browser globals
if (typeof this.L === 'undefined')
throw 'Leaflet must be loaded first!';
this.MyPlugin = factory(this.L);
}
}(function (L) {
var MyPlugin = {
/* ... */
};
return MyPlugin;
})); The above would define a global variable for the plugin if no module system was present. I suppose a // myplugin.js
// UMD or whatever author prefers - no dependency on Leaflet (?!).
define(function() {
// Plugin definition accepts Leaflet as an argument
function MyPlugin(L) {
MyPlugin.doSomething = function() {
L.doSomething();
}
}
return MyPlugin;
}); // myapp.js
// Load deps using system of choice
define(['leaflet', 'myplugin'],
function(L, MyPlugin) {
// Register plugin with Leaflet (or rather, Leaflet with plugin)
L.use(MyPlugin);
MyPlugin.doSomething();
}); Not sure I did that right but you get the idea. It's a little different than the |
ICYMI: d3 has gone back to always exporting a global (d3/d3#1921) |
I think I'll have to agree with Mike. We need to bring back the global. |
Fair enough, it seems like that might be the most practical solution for now. |
Global is back as of #2943. I've also updated the plugin guide with some best practices for plugin authors so plugins don't have to rely on the global if browserify or require js are present. |
With ES modules being around the corner to be shipped to browsers, would it make sense to reconsider? |
ES modules has been shipped in major browsers as of September 15, 2017. |
That's a significant overstatement: in Firefox & Edge, modules are still behind a flag, and on Android, there's no support. Global feature coverage is around 44%. Maybe sometime soon they'll be something you can count on, but they aren't right now. |
@tmcw Maybe I wasn't specific enough (non-native english), I didn't want to say ALL major browsers but SOME, although 44% seems a lot to me. Also take a count for react/vue user base that use babel. |
It looks like 0.8 will not expose a global if a module system (i.e. Node or AMD) is present. This is definitely a good thing, but it will make it a bit trickier to integrate Leaflet plugins that don't have a UMD wrapper. Without the global, said plugins will not have anything to attach to (even when using e.g. a RequireJS
shim
config).What do you think about recommending (but not requiring) that all Leaflet plugins have a UMD wrapper? Proj4leaflet and Leaflet.zoomslider could be good base examples.
The two concrete steps I have in mind are:
I am willing to take action on these as I have time, but thought it would be good to start by determining an overall strategy.
(I should note that I personally avoid compatibility issues by manually adding AMD wrappers to every third party library I work with that doesn't have one. Needless to say that isn't a very scalable approach.)
The text was updated successfully, but these errors were encountered: