loaded script does not appear in global context - requirejs

I am attempting to load a script in one of my models:
attached(){
$.ajax({
type: 'GET',
url: '/lib/zxcvbn/dist/zxcvbn.js',
dataType: 'script',
cache: true
}).done(function(script, textStatus) {
console.log('loaded script');
});
}
The done callback is hit however the export zxcvbn is not available in the global context.
The exact same code run in a plain html page (i.e. not aurelia) works fine (zxcvbn is available in the global context)
I know this is not the recommended way of loading an external JS file in aurelia however the script is quite large and is only required in one spot in my app.
The docs for zxcvbn state:
zxcvbn detects and supports CommonJS (node, browserify) and AMD (RequireJS). In the absence of those, it adds a single function zxcvbn() to the global namespace.
My aurelia app is using RequireJS; If it isn't loaded into the global namespace where is it loaded and how can i reference it?

According to the information you give, the zxcvbn detects that there's an AMD loader present (RequireJS) and calls define to register itself as an AMD module.
Since you already have RequireJS on the page, you can replace your jQuery call with a call to require, and pass the full path:
require(['/lib/zxcvbn/dist/zxcvbn.js'], function (zxcvbn) {
// Do something with zxcvbn ...
});
Since the script registers itself as an AMD module, the parameter zxcvbn will hold the module's value.
Note that when you pass a path that begins with a forward slash, RequireJS uses the path as-is: this bypasses your RequireJS configuration (e.g. baseUrl, paths, map are not applied, etc.), and RequireJS does not add a .js extension, so it needs to have the extension.

Related

Why do I need to add a "shim" for AngularJS when using Require.js?

I have seen several examples that use this:
main.js
/*global require*/
'use strict';
require.config({
paths: {
angular: './angular',
app: './Content/app',
ngAnimate: './Scripts/angular-animate',
uiRouter: './Scripts/angular-ui-router'
},
shim: {
angular: {
exports: 'angular'
}
}
});
require(['angular', 'app'], function (angular) {
angular.bootstrap(document, ['app']);
});
Can someone explain to me why the shim is needed? My application uses other modules such as angular-ui router, jQuery etc. Do I need to do something similar and add a shim for these?
The rule is pretty simple: if a library/script/package/plugin is AMD-aware, then you don't need a shim. (Actually, you must not use a shim for it.) If it is not AMD-aware, then you need a shim.
A library/etc is AMD-aware if it detects that an AMD loader is present and calls define to make itself known to the loader.
jQuery from about 1.8 onwards has not needed a shim because it calls define. Angular, on the other hand, does not call define.
To know whether a specific piece of code needs a shim, you can read its documentation or if the documentation is not clear on this, then you can check the source code for a call to define. For instance jQuery 1.11.0 has this code:
// Register as a named AMD module, since jQuery can be concatenated with other
// files that may use define, but not via a proper concatenation script that
// understands anonymous AMD modules. A named AMD is safest and most robust
// way to register. Lowercase jquery is used because AMD module names are
// derived from file names, and jQuery is normally delivered in a lowercase
// file name. Do this after creating the global so that if an AMD module wants
// to call noConflict to hide this version of jQuery, it will work.
if ( typeof define === "function" && define.amd ) {
define( "jquery", [], function() {
return jQuery;
});
}
How it looks like will vary from one case to the other but the basic think you want to look for is the check that define exists, is a function, has the amd property set and the call to define.
(Note that jQuery is a special case where they decided to hard code the name of the module in the define call (first parameter: jquery). Generally the name of the module won't be present in the define call but will be left for RequireJS to infer on the basis of the file name.)

requirejs with existing globals

I have a built library (concatenated, minified and included before require.js) of several globals (jQuery + plugins, constructor functions, etc ). This library is used as a base on which apps are built on top of, with assumed dependencies. i.e, if I include my app scripts after the library, then I can freely use jQuery and constructors without any issues.
For bigger apps I'm considering using requirejs (to manage the different modules within the app), while still using this built library. How might I add existing globals like jQuery to the dependency list in require?
<script src="pathto/lib.js" type="text/javascript"></script>
<script src="require.js" data-main="../js/app" type="text/javascript"></script>
requirejs.config({
shim: {
'jquery': {
exports: '$'
}
},
// jQuery is already loaded with lib.js, no need for any path...
path : {
jquery : 'jquery.js'
}
});
Is this possible? Or should I just continue with assumptions that certain globals will exist within the app modules because lib.js was included before require / the app js?
Using require to load the lib.js is not possible, because it is part of a CMS.
-- EDIT --
What about using a named module, and just return a handle on the global object, as that is where the lib content sits anyway?
define("lib", function () {
return this;
});
require(["lib"], function (lib) {
// use existing globals found in lib via
lib.jQuery
// or simply
jQuery
});
That allows me to follow the require() convention of naming dependencies, rather than assuming.
I am doing the exact same thing for my project where I load jquery from a CDN, so my path configuration looks like this
path: {
'jquery': '//path/to/the/cdn'
}
In your case, I think you should do as you updated (define and then return), because in some 3rd-party libraries, they might define jquery as the dependencies. If you don't have jquery in your RequireJS configuration, you have to modify the source code of the 3rd party libraries

RequireJS - loading multiple config files

I am trying to load several RequireJS configs. In my html I am loading my main config via
<script src="../lib/require.js" data-main="../app/requireConfig"></script>
and once the document is ready I want to load all my plugin configs. So I created a new define file which holds a function that calls require.config:
define(['sharedServices/logger'], function (logger) {
function configVideo() {
logger.info('Adding video modules');
require.config({
path: {
Capabilities: 'videoProvider/Capabilities',
VideoProviderEnums: 'videoProvider/VideoProviderEnums',
VideoProviderCommon: 'videoProvider/VideoProviderCommon',
VideoProviderInstance: 'videoProvider/VideoProviderInstance',
DummyVideoInstance: 'videoProvider/DummyProvider/DummyVideoInstance'
}
});
}
return {
configVideo: configVideo
};
})
However, I get the following error:
Uncaught Error: Mismatched anonymous define() module: function (logger) {
The error you're getting isn't directly related to the stated problem (loading multiple configurations), but is caused by the way your code loading is organized. As the manual says:
To avoid the error:
Be sure to load all scripts that call define() via the RequireJS API. Do not manually code script tags in HTML to load scripts that have define() calls in them.
If you manually code an HTML script tag, be sure it only includes named modules, and that an anonymous module that will have the same name as one of the modules in that file is not loaded.
So the problem now is that when loading the module manually (as you state "when the document is ready", could you clarify how the quoted source is actually loaded?) requirejs doesn't know where the module came from, so it can't assign it a name. If the module were loaded via requirejs api (e.g. if it appeared in a dependencies list of a define call) and it were requirejs itself that determined its script path, it would name the module after the file.
In general it is advisable to have just a single script tag loading all the requirejs-managed javascript. This makes the development setup more closely match the eventual optimized situation (where all the scripts are concatenated together). It is still possible to make require.config calls inside individual modules if necessary and make some code execute only after document is ready. As an example, many our apps do something like the following in their main.js (the module loaded by the requirejs script tag):
// sort of bootstrap config
require.config({
packages: [{
name: "our-framework",
location: "../../our-framework/src/"
}],
// here some app-specific requirejs options
waitSeconds: 5
});
// load the framework, the "our-framework/rjs-config" contains
// framework specific requirejs config (another require.config call)
require(["our-framework/rjs-config"], function() {
// in this context both require configs are loaded
require(["application"], function(application) {
application.init().run();
});
});

JamJS - Still pulls for dependencies separately when compiled - Underscore not loaded for context?

A am relatively new to JamJS, and struggle to make it work properly.
I've got a very simple project based on Backbone and RequireJS, where I use JamJS to manage dependencies, namely: Backbone, _, Less, $, modernizr, underscore, bootstrap.
I tend to follow the method used by Backbone Boilerplate.
This is the code I use to get the Jam-compiled requireJS config file, together with my application-specific require config:
in html:
< script data-main="/assets/js/app/config" src="/assets/js/jam/compiled.min.js"> < /script>
'Compiled.min.js' is obviously the 600kb minified file generated by Jam.
The '/app/config' file is my Require.js configuration file where I'm planning to include all my project-specific code, not managed by the dependency manager.
Here's app/config.js:
require.config({
baseUrl:'/assets/js/',
deps: ['less','modernizer','bootstrap-jam','app/main'],
paths: {
'homeView': 'app/views/homeView'
// Use the underscore build of Lo-Dash to minimize incompatibilities.
,'lodash': '../jam/lodash/dist/lodash.underscore.min'
},
map: {
},
shim: {
}
});
(the files in deps are the ones I need on every page + my main.js - kind of a router.
The problem is that, in my homeView (which is initialized by main.js), I do this sort of thing:
define(['backbone'], function (Backbone) {
return Backbone.View.extend({
el:$('#homepageWrapper'),
initialize: function () {
this.$('#subTitle').text('This text is generated by homeView - the default Backbone View.');
}
})
});
As you can see I want Backbone to be available in this view. I assume that it's available through the compiled Jam code, however when I look in the Network panel in the Web Inspector, I see that this dependency is pulled in separately- this happens to any resource I try to use, not just Backbone.
I suspect that it might be something to do with the error I get as well, which I haven't been able to figure out. When using the compiled jam config, I get:
Uncaught Error: Module name "underscore" has not been loaded yet for
context: _. Use require([])
I'd really appreciate help with this
Thanks.

RequireJs asynchron loading, synchrones loading differences between requirejs and require

Good evening,
im new with requireJs and hope my questions are not stupid, its my first :).
Why the guy is using in the code above require and requirejs, whats the difference?
require(["config"], function(config){
requirejs.config(config);
require(["App", "ember"], function(App, Ember){
var app_name = config.app_name || "App";
root[app_name] = App = Ember.Application.create(App);
App.deferUntilDOMReady();
});
});
Is there a differences beetween the different code spellings?
Will the script ressources are loaded asynchon or synchron in both cases?
If i use requirejs-jquery are jquery (the $) than global or only local scope (amd scope)?
require(['script1','script2'], function() {}
require(function(require) {
require('script1');
require('script2');
}
Is it possible to have several require configs?
For example i have a bunch of nested structures like /modules/helper/example/js/example.
At the moment i have all required shims,paths inside the main.js config.
I want to place a main.js or config.js inside each helper module, which configer the required shims, pathes, etc.
Than i no longer need places all configs, pathes inside the main.
1.1
RequireJS registers TWO instances of itself in global scope - require and requirejs - really just for one reason - if one (most likely require) is overriden with another require that is different in scope or implementation, you still have requirejs - usually always a global. This separation is important when you plan to consume resources that are relative to the module you are in now.
// contents of 'a/b/c.js' module file
define(['require'], function(require){
// "local scope" require call
// resolves to 'a/b/d.js' file
require(['./d'], function(d){})
// "global scope" require call
// resolves to 'd.js' file
requirejs(['./d'], function(d){})
})
Note that asking for local require only makes sense in define calls. As define call is what establishes the "module" and it's ID. The above is equivalent to this named define:
// contents of whatever file
define('a/b/c', ['require'], function(require){
// "local scope" require call
// resolves to 'a/b/d.js' file
require(['./d'], function(d){})
// "global scope" require call
// resolves to 'd.js' file
requirejs(['./d'], function(d){})
})
The other, secret, reason why James put requirejs in there is to force you to keep using require in local scope because his build tool looks for that specific string require to find the require calls. You do this, and r.js suddenly cannot follow you dependency tree because myLocalRequire is not what r.js expects:
// contents of 'a/b/c.js' module file
define(['require'], function(myLocalRequire){
// "local scope" require call
// resolves to 'a/b/d.js' file
myLocalRequire(['./d'], function(d){})
// "global scope" require call
// resolves to 'd.js' file
require(['./d'], function(d){})
})
1.2 RequireJS does NOT do sync loading at all. The only place where you think that "it must be sync!" - the CommonJS style call like var a = require('a') it's still not. It yanks the resource out of cache. In other words, it never loads anything sync.
1.3 Don't use bundled RequireJS+jQuery. It makes an already huge jQuery more huge and interferes with browser cache. (Instead of using cached jQuery from CDN you force user to download same jQuery again - 100k of trash).
See this instead: Use jQuery as a dependency without loading jQuery with RequireJS?
2.0 Don't. separate configs is a trap. It's hell that you willingly enter once you start "building" your apps. I dare you to give me one example of a separate sane config that I cannot express as either named defines group or "packages" where main module loads relative resource.
The only thing that must be in your RequireJS config is 'baseUrl' and 2-5 globally-used 'paths' definitions. That's it.

Resources