Error trying module loading ( AMD ) with require.js - javascript

I'm getting a little frustrated with requirejs at this point.
I'm trying to load jquery and other libraries in my App.coffee file. The problem is that I can't load module dependencies in my define. Some of the input arguments (jq, jsn, etc) are null or just HTMLDocument objects. This changes based on the permutation of plugins that I try: 'order', 'domReady', or none.
My js lib directory looks like A). And my App.coffee file looks like B). I've tried to use 'paths' in the require.config and just raw file referencing (what you see below). I'm aware of requirejs-jquery integration. But shouldn't I be able to order my plugin loading?
I get a different set of errors if I try named 'paths'. I see someone suggested jquery 1.7 (also here). Is this working? I first wanted to take a step back and make sure that I have the concepts down correctly. i) require.config ii) module definition w/ dependencies, iii) the order plugin, etc.
If I have these concepts down correctly, I would think it's a jquery version issue. However, it's not just jquery as a dependency. And it's incredibly irksome to lose time in this manner. Any help is appreciated. Thanks in advance.
A)
$ tree js/lib/
js/lib/
├── backbone.js
├── backbone_loader.js
├── domReady.js
├── jquery-1.6.3.js
├── json2.js
├── order.js
├── pure.js
├── require.js
└── underscore.js
B)
require.config({
baseUrl: "/js",
paths:
order : '/js/lib/order'
jQuery : '/js/lib/jquery-1.6.3'
json2 : '/js/lib/json2'
Underscore : '/js/lib/underscore'
Backbone : '/js/lib/backbone_loader'
pure : '/js/lib/pure'
})
define( [ 'js/lib/order!js/lib/jquery-1.6.3',
'js/lib/order!js/lib/json2',
'js/lib/order!js/lib/underscore',
'js/lib/order!js/lib/backbone',
'js/lib/order!js/lib/pure',
'js/lib/order!js/bkeeping/models', ]
(jq, jsn, und, bbn, pur, models) ->
console.log('bkeeping LOADED')
# return an object with the models in it
models : models
jQuery : jq.noConflict()
json2 : jsn
Underscore : und.noConflict()
Backbone : bbn.noConflict()
pure : pure
)

The latest jQuery supports AMD loaders and will behave fine with require.js.
Underscore and Backbone don't and you will need to either:
use a modified version, for instance the one from the author of require.
use a plugin. I have found the use! plugin from here to fit my needs perfectly.

Thanks for the direction on this.
But I went to jquery-1.7, but still had to pull from the global space to get the object. That applies for my other libs for now, and their dependencies. What I ended up doing was returning an object with the dependencies in it. I got library loading done with the order plugin.
The contract of dependency objects being passed into your callback function (jq,pur,jsn, etc), simply isn't working for these libraries. It works for my defined modules (ex: models), but not external libs. I tried the use plugin, but found that it didn't work for underscore and backbone, or I didn't set it up properly. This is my workable solution for now; although I have to say that the headaches are seriously clouding the benefits for require.js.
define( [ 'order!js/lib/jquery-1.7',
'order!js/lib/pure',
'order!js/lib/json2',
'order!js/lib/underscore',
'order!js/lib/backbone',
'order!bkeeping/models', ]
(jq, pur, jsn, und, bbn, models) ->
console.log('bkeeping LOADED')
# return an object with the dependencies in it
models : models
jQuery : jQuery.noConflict()
pure : pur # pure and json2 objects are simply used in other libs. I don't need them directly
json2 : jsn
Underscore : _.noConflict()
Backbone : Backbone.noConflict()
)

Related

requirejs can't see jquery

I have a simpliest project using requirejs. A data-main file is js/default.js
You can see there two jQuery files. RequireJS can see only that which is located on the same level that default.js So this code:
require(
['jquery', 'modules/module1', 'modules/module2'],
function($, Module1, Module2){
$('body')
.append(Module1.phrase)
.append('<hr/>')
.append(Module2.ask);
}
);
...works
But if I change ['jquery', ... to ['libs/jquery', ... , it reveals an error:
Uncaught TypeError: $ is not a function
What's wrong here?
Whole code is here: http://plnkr.co/edit/QuFsKN597RD873MOlUw8?p=preview
jQuery must indeed be required as jquery.
Now, there may be still confusion regarding the module name. Someone may look at the dependency libs/jquery and infer that jQuery is in fact required as jquery. That is, doing require(['libs/jquery'], ... would be asking RequireJS to load the module jquery located in libs/. However, this is not the case. The module name of the module being required is the entire name listed in the dependency list. So in the require call above, the module name of the module required is libs/jquery. But jQuery calls define('jquery', ... to declare itself to RequireJS. The module name (the first argument is jquery, not libs/jquery and thus RequireJS fails to find the module requested.
A trivial fix is to add a paths configuration:
paths: {
jquery: 'libs/jquery'
}
Please have a look at the requirejs docs:
jQuery defines named AMD module 'jquery' (all lower case) when it detects AMD/RequireJS. To reduce confusion, we recommend using 'jquery' as the module name in your requirejs.config.
http://requirejs.org/docs/jquery.html

How let users to access requirejs modules outside main?

I'm implementing an AMD module oriented js framework that will be used on third party sites.
With this line, framework users will configure necessary modules
<script data-main="/main.js" src="/require.js"></script>
The problem is that data-main reference is loaded asynchronously so any js logic depending on modules loaded by main.js would fail unless I can be sure that it finished loading.
I'm pretty new to requirejs so not sure what's the good practices to create a framework that will be used by other people.
How could resolve this very simple problem?
EDIT
An example to explain my point
main.js
requirejs.config({
paths: {
jquery: '//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min',
}
});
main js reference + extra code
<script data-main="/main.js" src="/require.js"></script>
<script>
require(['jquery'], function($) {
// since main.js is not loaded yet, it will assume that there is a jquery.js
// file on the same folder that this file
console.log('myModule was also loaded and can use jQuery');
});
</script>
If you want to depend on other libraries and are specifically targeting being in a Require pipeline, all you need to do is to declare some dependencies with
define(
'myModule', // module name
['foo'], // module dependencies
function(foo){ // module construction
var myModule = {};
.... code to set up the module ....
return myModule;
});
and Require will take care of things. This will register your module with Require and won't attempt to build your module until all of your dependencies are available. This functionality is discussed here.
Update with example
Require JS is designed to work both with and without a prebuilt configuration. The paths property of the Require config object only provides Require with information on how to attempt to find libraries which have not yet been registered. However, the registration and then dependency resolution is handled by Require regardless of how/where the module was registered. Please see this JSFiddle for a working example of how you can register and use dependencies.
Update 2 regarding config
Since RequireJS loads everything asynchronously, you are correct, your code example will not work. However, you're making an incorrect assumption about how it is "supposed" to work. You have an incorrect example of what your library's clients' Require configuration will look like. If someone else is building an application using RequireJS and they want to use your library, they should declare the path to your library in their require.config:
require.config({
paths: {
// this tells require how to load jQuery (a library maintained neither by you nor your clients).
'jquery': '//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min',
// this tells require how to load myModule (the library you are building for your clients).
'myModule': '//example.com/js/my-module.min',
// this tells require how to load foo (a library built and hosted by your clients).
'foo': 'scripts/foo'
}
});
On the other hand, if your clients can't update their Require config to include your library in the declarations, then you're out of luck. All you can do is take all of your dependencies and bundle them up in your distribution file and then declare no dependencies:
define(
'myModule',
[], // can't declare any dependencies
function() {
// these dependencies are inside of the definition function to keep the global namespace clean
// since we need jQuery, we have to inline it:
var jQuery = ....
// same goes for d3.js
var d3 = ....
// now we can set up the module itself
var myModule = {};
.... code to set up the module ....
return myModule;
}
);
Obviously, this option means that you can't use the libraries which are being used by your clients. This means your library will be a lot heavier and include effectively duplicate code and data.
Hope that helps you understand how Require works and how other people will use your library.
I've finally used this approach
<script src="http://mydomain/js/require.js"></script>
<script>
requirejs.config({
baseUrl: 'http://mydomain/js'
});
require(['main'],function(){
// here users can do anything they want as all required libraries are loaded
});
</script>
main.js is loaded with a require instruction instead of using data-main attribute from script tag , this provides a callback where users can put their code.

How to include minified library version in RequireJS optimization

My situation is as follows:
My project based on RequireJS.
I am using RequireJS Optimizer for to create a single JS file.
Some of the module use a certain third party library as a dependency.
The third party is NOT included in the optimized file (libName: empty
in the build config).
RequireJS is configured through var require = {} object which appears
on EACH PAGE, right above the RequireJS. The object defines a path to
the unminifed version of the library, among other things.
What i'd like to achieve:
Use the same config file in both development and production (the require={} object is included with tag on each page). During development I'd like modules to use the UNMINIFIED version of the third party.However, after optimization occurs, i would like all the modules to use the minified version of that third party.
I did think of a solution in theory, but it seems a bit messy and Im hopeful cleaner solution exists:
To have the runtime config point to unminified version
var require = {
paths:{
'thirdParty':'lib/thirdParty'
}
}
Create a module which execute (lets call it "PathRewrite" Module):
requirejs.config({
paths:{
'thirdParty':'lib/thirdParty.min'
}
})
In runtime configuration, define path to "PathRewrite" as empty
var require = {
paths:{
'thirdParty':'lib/thirdParty',
'PathRewrite':'empty'
}
}
In the build configuration file define a real Path to "PathRewrite" in order for it to be included in the "main" file (concatenated file after build).
Include "PathRewrite" as a dependency of a module which is executed first.
What I hope that will happen is that during dev, when optimized file is not used, PathRewrite is will not be used, hence the path to unminified third party in the runtime config will be used.
When the project is optimized, PathRewrite will be included and executed. According to RequireJS documentation, it is possible to run RequireJS configuration twice and the configuration will be appended/overwritten. PathRewrite execution will overwrite the path to "thirdParty" to minified, which will thus be used by all the modules.
Hopefully i've provided enough information. I'd be glad hear of other ways to get this done. Thanks in advance.
This topic appears to have been explored a bit in this answer:
Loading min.js files Generated by TypeScript with Require
Don't let the title discourage you. Typescript is not the core issue of the question being answered there. Unfortunately, the discussion reveals that the RequireJS optimizer may be the only way to get decent minification to work, as it seems incapable of selecting alternate paths properly.
Why don't you want to use inbuilt RequireJs optimizer? You may just include this option
optimize : "uglify2"
and all your and third-party code will be minified after concatenation. In this case you don't need to use minified versions of third-party libraries.

Backbone.js and Require.js tool r.js

So in my TODO applications i used Backbone and require.js. All is cool. I separated all models, views, collections to single files and use require.js to load them. After i tried to join all files to one using console require.js optimizer r.js. As i result i get one file with all my libs and classes. But when i tryed to run i met error that Backbone undefined. I checked the file and see that r.js generated next thing:
1. First it added backbone sources to app-built.js file and after placed next string
define("lib/backbone", function(){});
So as result i have Backbone variable in the window but in my modules i use it in require.js way
define('models/todo',['jquery','underscore','lib/backbone'],function ($, _, Backbone) {
No as global and as result in my modules Backbone local variable is undefined.
And the same problem with underscore.js. R.js imported it in the same way.
So question. How to avoid this problem with othew libs in future or how to fix this now? SOme technics?
You might need to use a shim since Backbone according to the RequireJS expects Backbone to be in the base url directory. In your case, it appears to be in the /lib instead. Config Shim. Depending on the RequireJS version that you're using, you just have to make sure as well that the library that you're using is AMD compatible.
In your requireJS configuration:
shim: {
backbone: {
deps: ["underscore", "jquery"],
attach: "Backbone"
},
underscore: {
attach: "_"
}
}

In RequireJS - Cannot alias jQuery name in path

I'm a RequireJS noob. When I use "require.config" and include a path to jQuery with a name different than jQuery, results are not as expected.
Here's a very simple example to help explain my issue.
Structure of files
root
├── Index.htm
└── scripts
├── libs
│   ├── jquery-1.7.1.js
│   └── require.js
├── main.js
└── someModule.js
index.htm
<html>
<head>
<title>BackboneJS Modular app with RequireJS</title>
<script data-main="scripts/main" src="scripts/libs/require.js"></script>
</head>
<body>
<h3>BackboneJS is awesome</h3>
</body>
</html>
Here the script tag references require in scripts/libs. When require gets ran the JavaScript file called main.js in the scripts directory should be executed.
main.js
require.config({
"paths": {
"mod1": "someModule"
}
});
require(["mod1"], function (sm) {
console.log(sm.someValue);
});
In my experience the "mod1" can be anything as long as it's referenced the same in the require.config path and in the require method.
someModule.js
define([], function () {
console.log();
return { someValue: "abcd" };
});
Just for completeness I included someModule.js
The perceived inconstancy occurs when I include JQuery.
In the following main.js I added jQuery to the config and the require method.
Main.js
require.config({
"paths": {
"jquery": "libs/jquery-1.7.1"
,"mod1": "someModule"
}
});
require(["mod1", "jquery"], function (sm, $) {
console.log(sm.someValue);
console.log($);
});
With the additional of jQuery everything seems to still works. The "console.log($)" writes the jQuery function.
Now the kicker. In the following code I change "jquery" to "jqueryA" in both the paths and require
require.config({
"paths": {
"jqueryA": "libs/jquery-1.7.1"
,"mod1": "someModule"
}
});
require(["mod1", "jqueryA"], function (sm, $) {
console.log(sm.someValue);
console.log($);
});
Now "console.log($)" writes null.
Should this be expected? Is there a reason why the name must be jquery, but for mod1 it can be anything?
I can work-around this without a problem, but this issue seems odd. I know I can use the combined RequireJS and jQuery file, but when jQuery has an update I don't want to be dependent on RequireJS to include the new jQuery.
In jQuery 1.7 they decided to support AMD loading. To do this, it defines a module named 'jquery' which passes back a reference to the jQuery object. When you define your path to jquery with another name (eg 'jqueryA'), things aren't exactly breaking as you think they are.
The jquery script always defines itself as a module named 'jquery', which is registered with require for your app. When you named your path shortcut 'jquery' and 'jquery' was loaded as a dependency, require was actually referencing the 'jquery' module defined by jquery-1.7.1.js, which does pass back the correct reference. When you name your module shortcut jqueryA, you are now referencing an undefined reference, because the jquery script itself does not pass back a reference, except via the module named 'jquery'. It's silly, I know.
The jquery script defines the module as 'jquery' and expects that you will simply reference it as 'jquery'. If you want to reference it as another name (and as a bonus, keep it from conflicting with other loaded jquery libraries), use this method:
Use requirejs and jquery, without clobbering global jquery?
Here's my workaround, based on the implementation I read of Require.JS 2.1.0:
define.amd.jQuery = false;
require.config({
...
shim: {
"jQuery-1.8.2": {
exports: "jQuery"
}
}
...
});
I believe I found the answer to my issue.
Optionally call AMD define() to register module
https://github.com/documentcloud/underscore/pull/338#issuecomment-3253751
Here's a quote from the previous link. Even though it pertains to underscore, I believe it relates to JQuery also.
all AMD loaders allow mapping a module ID to a partial
path, usually the configuration is called 'paths', so to do what you
want:
requirejs.config({
paths:
underscore: 'js/libs/underscore-1.2.3.min'
} }); require(['underscore'], function () {}); Since underscore is used by other higher-level modules, like backbone, a common dependency
name needs to be used to communicate a common dependency on
underscore, and it makes sense to call that dependency 'underscore'.
The paths config gives a way to do the mapping to a specific URL you
want to use for that dependency.
Here's a rant that does a very good job of describing the issues with AMD and named modules.
AMD modules with named defines. So much pain for what gain?
http://dvdotsenko.blogspot.com/2011/12/amd-modules-with-named-defines-so-much.html
Quote from the link above
If the only way to consume the module properly is to force the
end-developer to hard-code its name again in a config file, at the
consumption point, (in that respect only) why waste time, effort and
hard-code the name in the module in the first place (let alone cause
grief to those devs who DO need to load the module under different
name / from alternate sources)?
In this post James Burk recommends not using name module.
https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
Normally you should not register a named module, but instead register
as an anonymous module:
This allows users of your code to rename
your library to a name suitable for their project layout. It also
allows them to map your module to a dependency name that is used by
other libraries. For instance, Zepto.js can be mapped to fulfill the
module duty for the 'jquery' module ID.
There are some notable exceptions that do register as named modules:
•jQuery •underscore
Exception suck. Exceptions makes it difficult for noobs.

Categories