How do I noConflict the requireJS require/define methods? - javascript

Looking for requirejs.noConflict(), or some way to remove the global footprint from the library. My use case is that I'm writing a widget to run in a 3rd party page which might already define require and define (with a previous version of requirejs or even another library entirely).
I've tried implementing this myself and it mostly works. For simplicity lets assume I do not restore original values, only remove the footprint. I do something like this in my data-main:
var mycontext = requirejs.config({context : 'asdf', baseUrl : 'http://foo.com' });
mycontext(['require','foo'], function (require, foo) {
var f = require('foo');
});
// namespace cleanup
window.requirejs = undefined;
window.require = undefined;
window.define = undefined;
The problem here is that the f value from require('foo') returns null, but only iff I do my namespace cleanup. This smells like a bug in requirejs, but I'm hoping there's an official no-conflict solution.
Hard to google this one due to all the jQuery related noConflict() questions.

The RequireJS documentation has a section on this titled "HOW CAN I PROVIDE A LIBRARY TO OTHERS THAT DOES NOT DEPEND ON REQUIREJS?"
You can also have a look at the example build file, which shows how wrap can be used.
A good example of how this works is the Flight library.
By default the library uses AMD but there is a standalone version that wraps all the modules in an anonymous function and includes a tiny require/define API at the top (They use their own build tool for this). Source can be found here.
Note that for this to work all the modules will require IDs, but the r.js optimiser will handle that for you.
Using these techniques should allow you to leave any already defined require/define variables alone.

Related

what is this "require" thing? [duplicate]

This question already has answers here:
Is 'require(...)' a common javascript pattern or a library function?
(3 answers)
Closed 7 years ago.
I see this in many JS libraries out there, mostly looking through GitHub, currently looking at PeerJS. I'm referring to this:
var util = require('./util');
var EventEmitter = require('eventemitter3');
var Negotiator = require('./negotiator');
var Reliable = require('reliable');
...
window.Socket = require('./socket');
window.MediaConnection = require('./mediaconnection');
window.DataConnection = require('./dataconnection');
window.Peer = require('./peer');
window.RTCPeerConnection = require('./adapter').RTCPeerConnection;
window.RTCSessionDescription = require('./adapter').RTCSessionDescription;
window.RTCIceCandidate = require('./adapter').RTCIceCandidate;
window.Negotiator = require('./negotiator');
window.BinaryPack = require('js-binarypack');
...
Just from intuition, it seems like require() is importing/including whatever is being passed in, i.e., EventEmitter. However, I can't figure out where require() is coming from?
I'm not too familiar with NodeJS, and this seems like it's a NodeJS thing, but I don't understand how require() fits into a web browser context, where NodeJS doesn't exist.
I've seen RequireJS and Browserify, but these are libraries that would need to be included with application in order to use the require() function. In the example of PeerJS, I can just include it:
<script type="text/javascript" src="/static/js/peerjs.v0.3.13.js"></script>
... and it uses require() no problem. However, it doesn't look like there's any 3rd party libraries that are defining require() that are being bundled along with the PeerJS source code.
How is it being included? How is it being initialized? How is it fetching whatever is being passed in, i.e., "EventEmitter"?
It's a way to include external JavaScript (or really any other file) into your script through a single point of entry without introducing globals. It's most often used with Asynchronous Module Definition (AMD) and CommonJS modules. At it's highest level, require() is an API to use JavaScript modules. NodeJS uses the CommonJS syntax for the most part.
There's also no definite "better" one to use. It becomes almost an East Coast/West Coast turf war trying to discuss one vs the other. Some say that AMD modules are too verbose since you have to capture all of your imports in a closure and then use them which means you have to look in two different places for where you are defining your variables and imports:
AMD from RequireJS also Dojo
define('myModule', ['dep1', 'dep2'], function (dep1, dep2) {
return function () {};
});
CommonJS
var foobar = require('./foobar').foobar,
test = new foobar();
test.bar(); // 'Hello bar'
Additionally, some say that the A part of AMD doesn't really benefit you often enough to be worth the overhead.
Where does the "require" part come from?
In the browser, the require() comes from whatever library you are loading whether it be an AMD or CommonJS loader. However, for your above examples, you look like you're using it in a NodeJS context. NodeJS has the require() defined within the environment just like module.exports. In fact, the module.exports is what is given to whatever variable you're assigning to with the require(...).
Contrast the module.exports from CommonJS to how AMD gets your module into your variable's hands which is just the return from the closure that you put in a call to define().
Can these be used together?
One other thing to touch on is that they aren't exclusive to one another. They can be coerced into playing with one another either using some kind of wrapper or by using another convention: UMD. UMD tries to let you create modules that work no matter the environment exposing your module through whatever convention is available be it module.exports or define().

Can't get $ to work using RequireJS and MooTools

I'm attempting to build a site using a combination of RequireJS and MooTools. It's my first time using both libraries. There is plenty of documentation for using RequireJS with jQuery but less for using it with MooTools. I've found only this really. But I'm having some trouble and much of it probably is a result of ignorance; still, perhaps you all can help.
At the moment, I'm just trying to test out basic functionality and understand how I would go about setting this up. Here is what I have tried:
In my site footer, I have this script tag:
<script src="assets/js/vendor/require.js" data-main="../app.js"></script>
This loads requirejs with the file app.js. Inside app.js I mainly deal with paths:
requirejs.config({
"baseUrl": "assets/js",
"paths": {
"mootools": "//ajax.googleapis.com/ajax/libs/mootools/1.4.5/mootools-yui-compressed"
}
});
// Load the main app module to start the app
requirejs(["main"]);
Finally, in main.js, I have (so far) the following:
define(["mootools"], function($) {
var a = $$('.menu'); // .menu is a nav menu in the DOM
console.log(a);
var b = $('.menu');
console.log(b);
});
So here, a works, but b causes an error: undefined is not a function. So there are a couple of questions embedded here. First, can someone tell me what the difference in meaning for $ and $$ with mootools? I gather from this tutorial, that both are used in mootools. Also, why is it that mootools is not mapped to $? As I understand it, with jQuery, this is how you would do this, see here for example.
I'm sure there are some basic confusions here, but please have mercy. I'm a newbie to these tools.
MooTools (as is) is not AMD-compliant. David Walsh is cool but he does not like or use RequireJS. The info in his post is well out of date and not practical any more. In fact, I believe none of the MooTools-core team likes AMD or uses it. Anyway, that's beside the point. jQuery now IS based around AMD so using it is easy. MooTools tried it 2 years ago - https://github.com/arian/mootools-core/tree/1.5amd - and gave up. 1.5 is still not out (hopefully next week, still no AMD).
Anyway
You cannot do this quite in that fashion by expecting the script to magically return $ where a module has not been defined.
There is another issue here which is with the fact that you are loading a remote script and that you leave the protocol to be determined automatically - which are sort of quirky things for RequireJS to handle in their own accord.
Two or three ways to handle it.
you can just define a local module, eg your own mootools.js
define([
'http://ajax.googleapis.com/ajax/libs/mootools/1.4.5/mootools-yui-compressed.js'
], function(){
return window.$;
});
then use by requiring it:
require(['mootools'], function($){
$(document.body).adopt(new Element('div[html=hi]'));
});
eg. http://jsfiddle.net/dimitar/5zYnW/
however, mootools will export all sorts of globals anyway, so it's not really useful. you are better off using the requirejs shim config.
shim example
require.config({
paths: {
mootools: 'https://ajax.googleapis.com/ajax/libs/mootools/1.4.5/mootools-yui-compressed'
},
shim: {
mootools: {
exports: '$'
}
}
});
// some code.
require(['mootools'], function(){
document.id('foo').adopt(new Element('div[html=hi]'));
});
eg: http://jsfiddle.net/dimitar/5zYnW/1/
old school
I find that it's easier to load MooTools before RequireJS and assume it's all global in all modules that I write - it makes more sense as there are too many global exports to catch. eg. Class, Element, Request etc etc.
eg. https://github.com/epitome-mvc/Epitome/blob/master/example/js/model-demo-require.js -s from my MooTools MVC framework Epitome.
Here's example module code via a UMD wrap - https://github.com/epitome-mvc/Epitome/blob/master/src/epitome-model.js - the only code that implicitly requires MooTools is the node.js code.

RequireJS - Loading AMD modules both inside a require flow and inline

Consider this:
<script src='global.js'></script>
<script src='require.js'></script>
<script>
require(['modular_foo'], function() {
//do stuff
});
...and in side global.js we have, among other things:
//global.js
$.getScript("modular_bar.js");
where both modular_foo and modular_bar are anonymously defined AMD modules. Using requireJS, loading something like the above would give you our favourite error, mismatched anonymous define() modules.
It's fine enough as to why that error occurs (read up on that page if you'd like to know), but the problem is, what if you can't get out of this situation?
I'm working in an established platform which is very gradually migrating to a RJS flow, for now there's no way out of using both inline legacy scripts (some of which have AMD checks to trigger define()) and our requireJS entry-point simultaneously.
In some cases I can simply place inline AMD-compatible scripts above loading the require.js library, but that doesn't work when you need to load other things (modular_bar.js) asynchronously depending on the DOM content. I could also just comment out all AMD checks from those files loading externally to RJS but that's preventing making them incompatible with ever being loaded in a modular flow.
Anyone out there had a similar experience? How do you blend your flows to overcome these sorts of conflicts?
I do not have experience using this solution in a production environment but I spent a couple days on this question figuring out the best way to approach it.
You can use a modified RequireJS library that does not allow the anonymous define's to execute, if it is being passed through eval. Also, you can disallow any define calls by removing type check for string on name in the snippet below.
The following snippet is a modification to RequireJS that will ignore anonymous defines if being called by eval. You can find the fully modified require.js in this GitHub Gist.
The code relies on the parse-stack library. If you can't include the library before RequireJS, I suggest just concatenating it to the top of of the file.
Demo
// This is a snippet of RequireJS
// ...
define = function (name, deps, callback) {
var node, context;
// We will allow named modules to be defined by `eval`
if (!(typeof name == 'string' || name instanceof String))
{
var stack = parseStack(new Error());
// If we find any eval in the stack, do not define the module
// This is to avoid the "Mismatched anonymous define() module" error
// Caused by executing an anonymous define without requireJS
for(var i = 0; i < stack.length; i++)
{
if(stack[i].name == "eval")
{
return;
}
}
}
// ...

Making requirejs modules AMD compliant

I'm currently building an app where the frontend is doing a lot of the heavy lifting.
To keep everything neat and organised I'd like to use requirejs. However, to use require.js to its' full extent all the modules I use should be AMD compliant.
Which means that every time a module that I use is updated I need to either wait for an AMD-compliant version to appear or make one myself ( Which I currently don't know how to ).
This is a real turnoff.
Looking at this https://github.com/jrburke/backbone/blob/optamd/backbone.js it seems to me that making a module like Backbone AMD-compliant isn't as straightforward as wrapping the plugin into a generic function.
Is there a more or less straightforward way of making a module AMD-compliant?
Well his version is pretty bullet-proofed so it'll run under a variety of circumstances. Since you know the environment you are running in and what is available/what isn't then you can make some assumptions that will let you do something that is much more straightforward.
Check out this gist where I make bacbkonejs an AMD module assuming jQuery, underscore and define are in the global scope and I don't need commonjs support:
https://gist.github.com/2762813
I just add
define(function() {
var obj = {};
obj._ = window._;
obj.jQuery = window.jQuery;
to the top and
.call(obj);
return obj.Backbone;
});
to the bottom.
Thanks to #SimonSmith for bringing UseJS to my attention. UseJS is an AMD loader plugin that will allow you to load non-amd formatted modules without modifying them. I haven't used use myself yet but it looks promising: https://github.com/tbranyen/use.js/
UPDATE
RequireJS 2.0 now directly supports the functionality you are looking for via shim configs: https://github.com/jrburke/requirejs/wiki/Upgrading-to-RequireJS-2.0#wiki-shim

What's proper jQuery plugin practice?

Don't be afraid to use any technical jargon or low-level explanations for things, please. I'm savvy enough with computer architecture and low-level programming languages to comprehend any optimizations or memory management techniques, as well as complex structures (classes, member variables, etc.)
My primary focus of code is web-based applications. I work with PHP a lot and I've been learning CSS quickly. Javascript is currently my bottleneck, however. I know enough Javascript to do just about anything sans frameworks (DOM manipulation, AJAX queries, etc.). I also know that I can make my code run quicker, optimize it for specific cases, and I can shrink the over-all size of my code (no external script to include) by manually coding everything. However for ease of reading by other programmers and for speed of coding I'm trying to learn at least one Javascript framework.
After reading through the documentation on a number of frameworks and looking at some tutorials, I preferred jQuery. It allowed for very powerful iterative code in a single line and it had a very small chance of global variable namespace collision. From what I could tell, the ONLY global variable declared is the $ variable and everything else happens within this namespace, and there were even ways to access the namespace without this variable if you wanted to have two frameworks side-by-side. It also had a very small file to include (24 kilobytes gzipped) which means less server load.
My question is what are good practices in creating a jQuery plugin? If I were to start coding websites in jQuery, how should I go about it for the best interoperability and design? I want to ensure that my code can run along-side any other jQuery without interference, it's possible to build plugins off of my code, and I minimize use of the jQuery namespace so that I don't steal variables that might be used by another script.
Read the jQuery plugin authoring suggestions, also look at the unminified jQuery. Notice the last line: window.jQuery = window.$ = jQuery; So there are two global variables window.jQuery and window.$. To delve into this issue a little deeper, read more about the documentation on using jQuery with other libraries and jQuery.noConflict():
// Trigger no conflict mode.
$.noConflict();
// Code that uses other library's $ can follow here.
For writing plugins, make sure to pay special attention to the section called Maintaining Chainability (since jQuery makes use of chainability so nicely). You have to explicitly return this in your plugins to maintain chainability. Additionally, speaking of clashing with other variables, make sure you stop your plugin from clashing with other code by using a closure:
// Use a closure so you can use the dollar sign in your plugin,
// but you don't clash with other uses of the dollar sign in the script
// around where you define your plugin (other libraries, etc.)
(function( $ ){
// Adding your plugin to jQuery
$.fn.yourPlugin = function() {
// Maintain chainability
return this.each(function() {
// ...
});
};
}( jQuery ));
There's a lot of other great information on that plugin authoring page. The above is just the bare bones. There's info on defaults and options, namespacing, and many other things.
Also, if you're concerned about your variables clashing, you can also make use of closures for you own "regular" code... not just jQuery plugins. To do this, enclose your script in a self invoking anonymous function:
(function() {
var ... // these vars will not clash with
// anything outside this anonymous function
// You can do your jQuery in here if you need to access
// the local vars:
$(function() { ... });
}());
For example:
// global 'clash'
var clash = "test";
(function() {
// local 'clash'
var clash = "something else";
// this 'clash' shadows but doesn't change the global 'clash'
}());
alert(clash);
// The global 'clash' has stayed unaffected by the local `clash`
// Output: test
jsFiddle example
You can add plugin methods without using the extend method:
jQuery.fn.myPlugin = function(opts) { ... }
You can use the extend: if you're just looking to extend the jQuery object with multiple
functions you would do:
jQuery.extend({
funcName: function(){
//function code
},
funcName2: function(){
//function code
}
});
"jQuery.extend adds a set of properties to the jQuery object.
jQuery.fn.extend adds a set of properties to the jQuery.fn object
(which is then accessibly via $().foo)."
jQuery.fn is a shortcut for jQuery.prototype.
The official documentation on plugins: http://docs.jquery.com/Plugins/Authoring
Mike Alsup has this good tutorial/pattern discussion:http://www.learningjquery.com/2007/10/a-plugin-development-pattern
EDIT: One other note, be careful of your names with use of packers/minimizers - test on the one of your choice in this regard.

Categories