Code Monkey home page Code Monkey logo

umd's Introduction

UMD (Universal Module Definition)

Build Status

This repository formalizes the design and implementation of the Universal Module Definition (UMD) API for JavaScript modules. These are modules which are capable of working everywhere, be it in the client, on the server or elsewhere.

The UMD pattern typically attempts to offer compatibility with the most popular script loaders of the day (e.g RequireJS amongst others). In many cases it uses AMD as a base, with special-casing added to handle CommonJS compatibility.

Variations

Regular Module

  • amdWeb.js - Defines a module that works with AMD and browser globals. If you also want to export a global even when AMD is in play (useful if you are loading other scripts that still expect that global), use amdWebGlobal.js.
  • returnExports.js - Defines a module that works in Node, AMD and browser globals. If you also want to export a global even when AMD is in play (useful if you are loading other scripts that still expect that global), use returnExportsGlobal.js.
  • commonjsStrict.js - Defines a module that works with more CommonJS runtimes, and for modules that will have a circular dependency. If you also want to export a global even when AMD is in play (useful if you are loading other scripts that still expect that global), use commonjsStrictGlobal.js

jQuery Plugin

  • jqueryPlugin.js - Defines a jQuery plugin that works with AMD and browser globals.

AMD with simple Node/CommonJS adapter

These are useful for using AMD style while still making modules that can be used in Node and installed via npm without extra dependencies to set up the full AMD API.

This approach does not allow the use of AMD loader plugins, just basic JS module dependencies. It also does not support the callback-style require that is usable in AMD.

  • nodeAdapter.js - Best for when using AMD style but want it to work in Node without a helper library that sets up AMD.
  • commonjsAdapter.js - Similar to nodeAdapter.js, but compatible with more CommonJS runtimes, and if you want to define a circular dependency.

Tooling

Build tools

  • docpad-plugin-umd is a DocPad plugin for surrounding JavaScript code with UMD boilerplate
  • grunt-umd is a Grunt task for surrounding JavaScript code with UMD boilerplate
  • gulp-umd is a Gulp task for surrounding JavaScript code with UMD boilerplate
  • grunt-urequire is a Grunt wrapper for uRequire a conversion tool for universal JavaScript modules.
  • generator-umd is an Yeoman Generator that creates a single module project with UMD boilerplate

Testing

Resources

Todos

  • noConflict. Although with AMD loaders and build tools, it should be possible to get version specific bindings, maybe show a version that has a noConflict option.
  • Variation with attaching some functionality to a $ impersonator. Although, it is tempting to say for that case, ask for 'jquery' as a dependency, and if the developer wants to use something different than the actual 'jquery', map that file to the 'jquery' name. That is one of the strengths of module names, they can be mapped to different implementations.
  • Usage examples
    • Further justifications for usage
    • Gotchas/custom-tweaks we're aware of, but would rather not apply to the default UMD boilerplate

Influences

The basic pattern for the UMD variations in this repository was derived from the approach @kriskowal used for the Q promise library.

Earlier UMD variations were also of influence, ranging from Kit-Cambridge's UMD, through to patterns discussed by Addy Osmani, Thomas Davis and Ryan Florence and most recently the UMD patterns proposed by James Burke.

License

Copyright (c) the UMD contributors

Licensed under the MIT License.

umd's People

Contributors

addyosmani avatar adjohnson916 avatar balupton avatar bnjmnt4n avatar csnover avatar cyril-sf avatar dandv avatar duzun avatar evancarroll avatar hiendv avatar jrburke avatar jrf0110 avatar michaelficarra avatar mikesherov avatar nfriedly avatar pangdaxing23 avatar phated avatar ruyadorno avatar sashagavrilov avatar tcyrus avatar thomasdavis avatar unclechu avatar yuchi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

umd's Issues

Further Generalization of commonjsStrict.js

commonjsStrict.js line 22: https://github.com/umdjs/umd/blob/master/commonjsStrict.js#L22

Wouldn't assigning exports to module.exports in here further generalize the module definition by allowing the module to directly assign a function or instantiated object to the exports variable in the module definition?

factory((exports = module.exports), require('b'));

As far as I can tell, there shouldn't be a downside to this, though I cannot determine whether the exports special object from AMD can be treated the same.

Dependency not loading, seems to be a naming issue?

Hello all,

I am attempting to transpile a file (it comes with it's own transpiled version but i wanted to be able to work with the es6 version and transpile it myself):
https://github.com/cbcrc/knockout-dragula/blob/master/knockout-dragula.js

I have set up gulp like so:

gulp.task('transpile', function() {
    return gulp.src('Dependencies/lib/knockout-dragula/knockout-dragula.js')
        .pipe(plumber())
        .pipe(babel({
            presets: ['es2015'],
            plugins: ["transform-es2015-modules-umd"]
        }))
        .pipe(gulp.dest('Scripts/generated'));
});

The file that it is generating looks starts like this:

(function (global, factory) {
    if (typeof define === "function" && define.amd) {
        define(['exports', 'knockout', 'dragula'], factory);
    } else if (typeof exports !== "undefined") {
        factory(exports, require('knockout'), require('dragula'));
    } else {
        var mod = {
            exports: {}
        };
        factory(mod.exports, global.knockout, global.dragula);
        global.knockoutDragula = mod.exports;
    }
})(this, function (exports, _knockout, _dragula) {

The problem i am encountering and i am not sure if it is ignorance on my part but _knockout is coming through undefined.
I looked at the transpiled file that they supply and this looks like this at the start:
https://github.com/cbcrc/knockout-dragula/blob/master/dist/knockout-dragula.js

(function (global, factory) {
  if (typeof define === 'function' && define.amd) {
    define(['exports', 'module', 'knockout', 'dragula'], factory);
  } else if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
    factory(exports, module, require('knockout'), require('dragula'));
  } else {
    var mod = {
      exports: {}
    };
    factory(mod.exports, mod, global.ko, global.dragula);
    global.knockoutDragula = mod.exports;
  }
})(this, function (exports, module, _knockout, _dragula) {

After some debugging the breaking difference seems to be this:
factory(mod.exports, global.knockout , global.dragula);//broken
vs.
factory(mod.exports, mod, global.ko, global.dragula); //works

If i change my version to global.ko it works.

Am i doing something wrong, do i need to do something extra so that it knows to look for knockout inside global.ko and not global.knockout?

Many thanks.
4imble

Why two jQuery templates?

We have two templates

  • jqueryPluginCommonjs.js
  • jqueryPlugin.js

This is really stupid. We're making the learning curve complex because of one concern..

} else if (typeof module === 'object' && module.exports) {
    // Node/CommonJS
    module.exports = factory(require('jquery'));
}

That's one branch in an else statement? Is that all there is too it? Who cares.. Browserify is huge and growing explosively. The time it takes to,

  • See there is a difference
  • Read which file you should use

isn't worth saving a branch on an if statement. Not to mention, we're making assumptions about how people are using UMD. The whole purpose of UMD is that it should just work if it at all possible.

tldr; _DELETE jqueryPluginCommonjs.js, and move the conditional into jqueryPlugin.js_

wrapping pre-existing modules/scripts with a umd

This may not be within the scope of this repository, but I am wondering if there is a recommendation for the best way to wrap pre-existing code as a umd, without having to be concerned with modifying the code itself, other than to wrap it, that would work equally well with typical browser scripts as well as node.js modules, and result in wrapped source that is a umd.

So in this case not so much an approach for someone writing a new module to take, as the approach for a build script, package manager, etc. to take that would like to be able to do something like apply existing code to a mustache template of the form

// top portion of umd definition here
{{ source }}
// bottom portion of umd definition here

such that the wrapped source is a well-defined umd that could withstand minifiers that rename variables and properties and realizing that scripts, when node.js modules, could easily take one of two forms:

  • directly referencing exports
    exports.foo= 'bar';
    exports.baz = function() { return 'buz' };
    
  • returning module.exports
    module.exports = function(foo) {
      foo.bar = 'buz';
    };
    

What would be best-practice (or even a suggested boilerplate) for this?

Strict vs Returning variants with CommonJS support

The variant returnExports.js says:

// If you want something that will work in other stricter CommonJS environments,
// or if you need to create a circular dependency, see commonJsStrict.js

But it doesn't really explain what the strictness is about. What is violating CommonJS in the stricter sense, and which still seems to work in node, in this example?

UMD is not compatible with JavaScript modules

Description

When using UMD in a script that is evaluated as a JavaScript module (tested in Chrome Canary and Safari stable), the reference to the global object (presumably window) is incorrectly detected.

Test case

Please refer to this test case for a demonstration of the problem: http://jsbin.com/yuvulec/1/edit?html

Analysis

JavaScript modules are always evaluated as JavaScript strict mode code [1]. In strict mode, an undefined or null this is no longer coerced to the global object [2].

What I expected

The following output in the console:

Everything is great!

What actually happened

Uncaught TypeError: Cannot read property 'b' of undefined

XMLHttpRequest with UMD?

I have a project that's built to use node, requirejs and regular web scripts. It uses XMLHttpRequest to make calls to the server, but that's not available by default in node. It needs to be required first.

I found a few solutions, but all of them feels hacky. Is there any way of doing this easily? Shouldn't UMD have this 'feature' built in?

Any help would be greatly appreciated.

Cheers.

A different approach to UMD with Vaccine

I just added UMD support to Vaccine. I thought you may be interested in seeing the different approach to handling the many options for UMD. (I don't have all the options in there currently, though.)

Instead of having separate discrete files, like is done in this repository, the UMD boilerplate is configured based off options like "support CommonJS", "export with return", etc. When a user checks one of the options, the file adjusts. This makes it easier for the user to get what they want. It also makes it easier to add other options.

In case a user picks a combination of options that doesn't work together, it highlights the problem options and provides a link to fix it.

I just started working on the site three days ago, so there may be some issues that I haven't caught. That said, there are already some neat features, like showing minified (and approximate gzipped) sizes and "diffing" between two different versions.

I hope you find this approach interesting. Let me know your feedback.

Add support for System.register

As noted at es6-module-loader wiki:

System.register can be considered as a new module format...

How about extending the UMD pattern to also use System.register?
Something like:

if (System && typeof System.register === "function") {
    System.register(['b'], factory);
} else if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define(['exports', 'b'], factory);
} else if (typeof exports === 'object') {
    // CommonJS
    factory(exports, require('b'));
} else {
    // Browser globals
    factory((root.commonJsStrict = {}), root.b);
}

A similar discussion also takes place at mozilla/localForage#158.

umd3-draft.js is confusing and possibly unnecessary

The file umd3-draft.js simply contains an unfinished draft, I am not sure what it is needed for. If it is useful, could an explanation be included in the README.md file? Otherwise, could it be deleted? Thanks.

UMD should always immediately run factory

i've got es5-shim with UMD, and synchronous inline script which uses this shim (it must be synchronous due to block html parsing) but require.js resolve es5shim dependency asynchronous, and inline script rise an error, because inline-script run before require(['es5-shim']) is done.

So UMD in case of such libraries, should always immediately run factory and exports for AMD its value;

also there is one more example why it should always immediately run factory, #78

if(false) { var define; } overites the global `define` in IE - nodeAdapter.js

I had this issue before with IE.
Take a look at this code:

    var x = 10; 
    function a(){ return x; try{}catch(x){} }; 
    alert(a()); // 10 in V8, undefined in IE

In IE (not sure until which version), if a variable is declared anywhere in the scope (inside any block, even a false if), it is available everywhere in that scope, even before its declaration.

Therefore this code overwrites define in environments like IE:

    if (typeof module === 'object' && typeof define !== 'function') {
         var define = function (factory) {
             module.exports = factory(require, exports, module);
         };
    }

give `window` to a jQuery plugin

Please help me how to provide window to this plugin.
It is clear to me that parameters should be reordered
from function (window, $, undefined)
to function ($, window, undefined)

But how to give window to it in AMD mode?

/*global jQuery: true */

/*!
   --------------------------------
   Infinite Scroll
   --------------------------------
*/

(function (window, $, undefined) {
    "use strict";

    $.infinitescroll = function infscr(options, callback, element) {
        this.element = $(element);

        // Flag the object in the event of a failed creation
        if (!this._create(options, callback)) {
            this.failed = true;
        }
    };

})(window, jQuery);

Instructions unclear, code stuck in cyberspace

Its not immediately obvious how I need to modify the scripts in order to use them for my own module. Maybe using more informative variable names would improve the intuitiveness.

myModuleName, dependencyOne, dependencyTwo

How can I do that?

Hi everyone

How can I solve this problem when I use AMD?

(function (factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery'], factory);
    } else {
        factory(window.Zepto || window.jQuery);
    }
}(function ($) {
    $.fn.Plugin = function () {};
}));

Some thing like this:

define(['zepto' || 'jquery'], factory)

🍻

templates/jqueryPlugin.js doesn't seem to conform to CommonJS spec

Not sure if I'm looking at the right CommonJS spec (the commonjs.org-site is a bit confusing), but in the current jQuery plugin template (jqueryPlugin.js, line 7) module.exports is used instead of the CommonJS standard exports.

You can compare this with commonjsStrict, line 23, which does check and use the exports-object – not module.exports.

I think jqueryPlugin.js should be changed to use the exports-object.

Note: Both files were checked at commit 95563fd (latest master as of 23rd Dec 2016)

Rethinking jQuery and CommonJS

Reviewing this code..

This line is almost entirely useless..

module.exports = factory(require('jquery'));

This is because require('jquery') returns a factory itself if it doesn't have a window object. So, if you're using node, you're feeding a factory into a factory, and confusingly calling the factory $.

We can do this..

(function (factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['jquery'], factory);
    } else if (typeof module === 'object' && module.exports) {
        // Node/CommonJS
        module.exports = factory(null, require('jquery'));
    } else {
        // Browser globals
        factory(jQuery);
    }
}(function ($, jQueryFactory) {
    if ( $ ) {
      $.fn.jqueryPluginCommonJs = function () {};
    }
}));

Or, we can do something like this...

(function (factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['jquery'], factory);
    } else if (typeof module === 'object' && module.exports) {
        // Node/CommonJS
        if ( window === undefined ) { throw new Error("jQuery requires a window") }
        module.exports = factory( require('jquery')(window) );
    } else {
        // Browser globals
        factory(jQuery);
    }
}(function ($) {
    $.fn.jqueryPluginCommonJs = function () {};
}));

Or, we can try to instantiate one with jsdom or the like. Just saying this follows the UMD paradigm doesn't skirt the issue that jQuery requires a window. We should handle cases where there is no Window Object if we're going to call this a fair boilerplate for jQuery.

mismatched anonymous define for jQuery plugin example

I tried following the jquery plugin example with the jQuery plugin for valums/file-uploader (see akre54/file-uploader@6972e0e) but got a "Uncaught Error: Mismatched anonymous define() module:" error, where the rest of the code block printed to the console.

Can you give me some pointers on what I might be doing wrong? requirejs version is 2.1.2. Thanks!

jQuery plugins name

This jQuery plugin's file is called: jquery.scrollTo.min.js

How should I define its name?

define('jquery.scrollTo.min', ['jquery'], factory);

I would like to name it "jquery-scrollto" without path definition:

define('jquery-scrollto', ['jquery'], factory);

Please help me on this.

Testing

The Grunt example linked in the readme isn't very clear for me. I can only assume that if it wasn't properly UMD, then loads of the underlying tests would fail, which isn't ideal really.

It would be great if there were solid tests (in this / a separate project) for testing if everything is exported correctly, etc. Having tests properly documented, maintained and used would only increase confidence. Then there could be build system specific plugins / projects which just wrap / use these tests (perfect for CI).

What do you think? I'd love to contribute but I wouldn't be 100% sure what exactly sure be tested and what all the edge cases are.

nodeAdapter breaks AMD

I am using the nodeAdapter for AMD modules, however it breaks AMD because it overrides the define function, as var define is hoisted outside of the if statement.

I'm a bit confused how anyone has actually got this to work…

Discussions

This issue is to discuss the current patterns in the repo as well as how we would like to address the variations on the todo list. I recall that Thomas had some particular comments here about how best the library/noConflict versions should best be handled, but let's carry on the conversation here so that it's not left in gists and lost later :)

What should a jQuery plugin return?

I think it's no use, but please advise.

(function (factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['jquery'], factory);
    } else {
        // Browser globals
        factory(jQuery);
    }
}(function ($) {
    $.fn.jqueryPlugin = function () {};
    // it is OK?
    return $.fn.jqueryPlugin;
}));

Google Closure module support

Support for the Google Closure module system is easy to add also.
Example: https://developers.google.com/closure/library/docs/tutorial

Just add this style at the top of the file:

if (typeof goog != 'undefined' && typeof goog.provide == 'function') {
    goog.provide('MyModule');

    goog.require('MyDependency1');
    goog.require('MyDependency2');
    // ...
}

The tool then used to build the full dependency tree is found here:
https://developers.google.com/closure/library/docs/depswriter

Regards
/ Fredrik Blomqvist

Adopt build tool core and frontends?

Hi,

Given it would be fairly simple to extract the core out of grunt-umd and make it a library of its own I started thinking perhaps the project would belong below umdjs.

It would look like this:

  • umdjs/build-core - Streaming library used by actual build tools
  • umdjs/grunt-umd - The plugin just moves under this namespace and uses `build-core´
  • umdjs/gulp-umd - Gulp plugin, same core.
  • umdjs/-umd - plugin, same core.

The primary advantage of having the tools below the same namespace would be discoverability. In addition it would add some credibility to the build tools and allow more people (umdjs team) to maintain them.

Does this sound reasonable to you? I understand if you are busy and prefer to keep tooling outside of umdjs but there are certain benefits as outlined above.

Explicit code license

It's unclear what the license is for these code snippets. My very limited understanding of copyright law suggests that source code without a license implies a copyright by the author and does not allow sharing / modifications / distribution / etc.

I would love to use these patterns, but am hesitant to do so until I understand the IP implications. It would be great if the example source files had a license header, if there was a LICENSE file, README.md was updated, or similar.

optional dependencies

I don't know if I can post this question here. Feel free to reject it, please.

What if my universal module need underscore OR lodash? May I be explicit about that in my module definition?

Thanks,
Adriano

Example Implementations Section

My first attempt at a UMD implementation: MultiEvent provided a lot of issues that I imagine might affect others who'd like to support UMD.

Any chance on creating a section in the readme for example implementations? Seeing working examples would be a big help.

JavaScript Module shim for UMD bundles

UMD isn't currently compatible with JavaScript modules because import and export declarations would cause a syntax errors in engines that don't yet support modules. This makes UMD now less universal than it could be.

#125 makes UMD bundles loadable via import statements, but the bundle will still write to globals (or use define or exports if available), so there are no useful symbols to import.

I think we can make importing UMD from JS modules better with a small shim that's imported instead and provides real exports.

There are two possible versions of the shim:

  1. A generic shim that exports a single object with all the UMD exports.
  2. A custom shim with a JS export for every UMD export

Generic Shim

The shim first sets up a global object to capture the UMD exports, then loads the UMD, then resets the global:

my-module-setup.js:

// Each UMD-JS-module shim needs it's _own_ setup module, even though the contents are the same, so that it evaluates before each UMD loads
window.exports = {}

my-module.js:

// We need a separate import to run code before the UMD module evaluates
import './my-module-setup.js';

// load the UMD module, which will populate window.exports
import './my-module.umd.js';

//export the UMD exports
export default let exports = window.exports;

// cleanup
window.exports = undefined;

Custom Shim

The custom shim works the same, but uses individual exports. This would likely be generated:

my-module.js:

// We need a separate import to run code before the UMD module evaluates
import './my-module-setup.js';

// load the UMD module, which will populate window.exports
import './my-module.umd.js';

//export the UMD exports
export const a = window.exports.a;
export const b = window.exports.b;

// cleanup
window.exports = undefined;

Custom shims would not support mutable bindings, ie you can't reassign an export from within the defining module.

Sharing instances of jQuery and packaging just extensions in CommonJS

jQuery-plugin should provide a paradigm that shares instances of jQuery. It currently doesn't. If I want to share one instance of jQuery and have multiple different CommonJS-packaged extensions to it, we should be able to make that work.

This problem is pervasive. It affects at least two projects I'm working on now: DataTables and Notify.js. My suggestion is to have the jQuery plugin look like this..

require('jQuery-plugin-foo')(window, [$]);

where

require('jQuery-plugin-foo')(window, $); // extends $
require('jQuery-plugin-foo')(window); // creates a jQuery object from the provided window.

If an instance of jQuery is provided the plugin gets that instance rather than creating its own in the UMD code. As for adding window, why not? It's explicit, but we can always satisfy this signature easily. Further, where window is not native (like under Node) it permits the user to provide something like jsdom. Ideas?

AMD using require sugar syntax

RequireJS allows some syntatic sugar so that instead of passing an array of dependencies, then declaring names for those dependencies in the factory in (hopefully) the correct order, you just class require, and then can use more familiar (to CommonJS people) require() calls:

define(function(require){
  var $ = require('jquery')
  var utilities = require('../app/utilities')
  // insert magic words here that make browser do things
})

To do this in a UMD friendly way, I think you'd do something like this:

(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    define(factory)
  } else {
    // Browser
    root.returnExports = factory()
  }
}(this, function (require) {
  if (typeof require === 'function' && define.amd){
    var $ = require('jquery')
  }
  // insert more magic words here
  return {}
}));

I don't know how prevalent this type is, but I find it much easier to write and read. Maybe this example could be covered?

Start With CommonJS Instead of AMD?

A plugin of mine – mark.js – needs the name mark.js in CommonJS environments, and markjs in RequireJS environments due to the fact that otherwise RequireJS will try to load a file mark.js directly instead of the plugin specified in the dependency path (Example of a working path naming).

Due to the fact that Webpack and others support both – AMD and CommonJS – it would be safer to name the CommonJS statement before the AMD statement. Because otherwise it would take the AMD statement which would be markjs in my above named examplen, and markjs isn't valid for CommonJS environments (because the node module name is mark.js).

I guess this is a common approach for JavaScript modules where the name is ending with .js.

Suggested pattern for AMD/commonJS/global with dependencies and r.js optimization

Hi
I wasn't sure where else to post this. I've been working on a library that implements a UMD pattern to allow modular loading of dependencies through a package syntax. You can find the project here: https://github.com/wellcaffeinated/PhysicsJS

The extension modules plug into the core so loading can happen with RequireJS like this:

require({
    packages: [
        {
          name: 'physicsjs',
          location: 'path/to/physicsjs',
          main: 'physicsjs-0.5.1.min'
        }
    ]
}, [
    'physicsjs', // core
    'physicsjs/bodies/circle' // extensions...
], function( Physics ){
    // use library with the circle body mixin defined
});

The extensions that mixin to the core need to declare the core (and possibly other extensions) as dependencies. So the current UMD suggestions weren't quite working for me.

I finally found something that works, and compiles nicely with the r.js optimization tool.

Here is the syntax:

(function( root, define, fn ){

    define = (typeof define === 'function' && define.amd) ? define : function( name, deps, fn ){
        if ( !fn ){
            fn = deps;
            deps = name;
        }

        // Node.js
        if ( typeof exports === 'object' ){

            deps = deps.map( require );
            module.exports = fn( deps );

        } else {
            // global object
            // map
            for ( var i = 0, l = deps.length; i < l; ++i ){

                deps[ i ] = root[ deps[i] ];
            }
                        // could also have root.NAME = fn.apply( root, deps );
            fn.apply( root, deps );
        }
    };

    define([ 'dep' ], fn);

})(this, this.define, function( dep1, dep2, ... ){

    // code plugs into the first dependency
});

Thought it would be useful. Feedback is appreciated!

Check for CommonJS before AMD

Scenario

  1. I'm building an embeddable widget using Browserify.
  2. Some client sites already have RequireJS loaded on the page, so define() is defined
  3. Some of my CommonJS dependencies use UMD
  4. So... these UMD dependencies suddenly can't be resolved since the UMD wrapper decides that this is an AMD context.

Solution
I think the solution is pretty simple - simply check for module.exports before checking for define. Browserify - unlike RequireJS - doesn't need to pollute the global namespace so the likelihood of module and exports being globally defined is low.

Thoughts?

Making UMD prettier

It seems a lot of people find these inclusions ugly out of principle. It really makes no sense to me.

But perhaps some simple rejigging could help people see them more nicely?

For example, removing the unnecessary '{' in the definitions. Perhaps even simplify the comments.

Then instead of:

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['b'], factory);
    } else {
        // Browser globals
        root.amdWeb = factory(root.b);
    }
}(this, function (b) {
    //use b in some fashion.

    // Just return a value to define the module export.
    // This example returns an object, but the module
    // can return a function as the exported value.
    return {};
}));

We can have:

(function (root, factory) {
  // AMD
  if (typeof define === 'function' && define.amd)
    define(['b'], factory);
  // Browser global
  else
    root.amdWeb = factory(root.b);
}(this, function (b) {

    //use b and return the exported object / function
    return {};

}));

I know there's good reasons for allowing multiple globals etc. Also there are probably many arguments against removing unnecessary braces. But I still find it nicer to look at, and I'm just trying to see why people are getting caught up with this!

Remove discouragement of jqueryPluginCommonjs.js

With CommonJS being used not only in node.js but also in browser environments, such as browserify and webmake, the discouragement [1] of jqueryPluginCommonjs.js should be removed (concerns Readme.md and jqueryPluginCommonjs.js itself).

[1] "However, jQuery is unlikely to run in most CommonJS environments, so only use this version if you know you are targeting a CommonJS environment that can load jQuery appropriately."

// It is unlikely jQuery will run in a CommonJS
// environment. See jqueryPlugin.js if you do
// not want to add the extra CommonJS detection.

Inconsistent usage of amdWebGlobal

https://github.com/umdjs/umd/blob/master/templates/amdWebGlobal.js

What about case when i have amd, but for any architecture reasons i dont use it, but i still want just to include library and get global variable.

More correctly will be:

        define(['b'], function (b) {
               return factory(b);
        });
        root.amdWebGlobal = require('b');

because global variables are for "inline" usages, not for amd approach.

"backward compatibility" of libraries should not be affected by my architecture.

why by adding third party amd it should breaks existing usages of any library?

this is definitely wrong approach.

Examples for multi-file projects

I have a project that splits functionality into multiple submodules to manage complexity.

Are there patterns for UMD (in my case, global/require/node support) when multiple files are involved?

More specifically, my project creates a namespace for the library with submodules placed within that namespace, e.g. MyModule is the module namespace with MyModule.SubModule1 and MyModule.SubModule2 as submodules.

My specific goal is to be able to concatenate/minify the files into one file to be distributed.

Any ideas? Thanks!

Use UMD with JSDOM?

In a Jest test I'm writing I need to initialize jsdom (just for that specific test).

The problem is that doing:

// init jsdom here

import library from 'umdLibrary';

The umdLibrary that requires window will blow up because window is not yet defined when imported, but it's needed when used.

How can this be solved?

myModule is not a function at HTMLDocument

hi everybody,
I'm trying to use the "jqueryPluginCommonjs.js" for the first time and I'm using browserify to create the bundle for the browser.
I wrapped a simple jquery plugin that I made (and tested) before, but I can't figure out why it works only if I specify the "browser" property within the package.json of my app:

"browser": {
  "fvalidation": "./node_modules/fvalidation/index.js"
},
"dependencies": {
  "fvalidation": "^0.1.1"
}

If I don't specify the browser field i get the error:

TypeError: $(...).fvalidation is not a function at HTMLDocument.

The module is here: https://github.com/Giulico/fValidation
And in my app.js file I'm doning something like this

var fvalidation = require('fvalidation');
$(document).ready(function() {
  $('#myForm').fvalidation({
      onSubmit: function() { console.log('done!'); }
    });
});

I’m wondering if you might help me to understand what am I wrong.
Thank you in advance
Giulio

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.