define(["jquery","bootstrap","jquery.min"],function($){
var inittest = function(){
alert("hello");
}
var init = function(){
inittest();
};
return {
init: init
}
});
It's not working. How to use jQuery to define array?
You need to do two things here (the details are in the useful thread I linked you to, so please read).
Configure requirejs so that when you declare modules (e.g. "jquery", "bootstrap"), requirejs can resolve them to actual files, minified or otherwise.
Shim bootstrap by specifying jquery as its dependency, so that jquery is loaded before it.
To accomplish these, make a call to requirejs.config({...}) with the appropriate options (here is an example). The use case there is exactly the same as yours: jquery is specified as a bootstrap dependency by shimming bootstrap. There you will also see an example of how to tell requirejs where your files are (this is accomplished via the paths property). Note how the .js extension is not explicitly specified there; do the same.
Needless to say, configuring requirejs can get complicated, but the basic idea is there, configure it by specifying the base directory and where the files are to be found, then shim non-AMD modules. An important thing to be aware of is that bootstrap is going to be what's called a declarative module, which means that it's only used for its side-effects (viz. for what changes it makes to $).
Related
I'm trying out AMD-way of handling scipts and my choise fell upon requirejs. In this project I use MDL (front-end framework; for those who haven't heard of it think of it as bootstrap 3) which should be included as:
<link rel="stylesheet" href="/bower_components/material-design-lite/material.min.css">
<script src="/bower_components/material-design-lite/material.min.js"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
I am not interested in js API that this framework is providing (if it provides any), I need this script only for UI to work properly when I attach framwerk-specific classes to elements.
According to requirejs philosophy I need only one script file to be included with a script tag on my page - the entry point. I understand that in that main script I need to require dependencies. And if it was say jQuery or underscore i.e. the library I actually require and my code depends on, I would write something like:
require(
['jquery'],
function($) {
$('body').append(...);
}
);
But how do I roll if it's not an actual dependency but I still need it to be loaded in my page and, in this particular case, I need it to be loaded first.
What do I do? My guess is I remove the script tag from my head and specify it in square brackets in my entry point script (as I did for jquery in snippet above) but just don't use it. Is it correct?
But how do I roll if it's not an actual dependency but I still need it to be loaded in my page and, in this particular case, I need it to be loaded first.
RequireJS only guarantees the relative order in which modules are loaded. If a module must absolutely be loaded first, then the chain of dependencies must be such that everything else depends on it, directly or indirectly. RequireJS does not provide a method to say "load this before everything else". You can get this effect only through dependencies. (Sometimes people think the deps configuration option guarantees that some modules will load first. It does not. Or they think that the order of dependencies in a require or define call sets an order for loading beyond what the dependencies set. It does not. If A and B have no dependencies of their own then require(['A', 'B'], ... and require['B', 'A'], ... are both free to load the modules in any order.)
What do I do? My guess is I remove the script tag from my head and specify it in square brackets in my entry point script (as I did for jquery in snippet above) but just don't use it. Is it correct?
In theory there's no problem with doing this. I say "in theory" because I do not use MDL so I don't know if MDL has any need that would prevent it from working. You've compared MDL with Bootstrap 3. What you describe is how I load Bootstrap with RequireJS. I tend to use the CommonJS idiom so modules that need Bootstrap look something like this:
define(function (require, exports, module) {
'use strict';
require("bootstrap");
There's no need to do something like var bootstrap = require("bootstrap"); because the value would be undefined anyway because the JS code of Bootstrap installs itself as jQuery plugins.
I've set up a single html page that uses three dojo widgets and I'm trying to create a custom build from it using dojo 1.7.5. The build succeeds leaving me with a dojo.js that includes the files I need using this build file:
var dependencies = {
action: "release",
selectorEngine: "acme",
stripConsole: "none",
cssOptimize: "comments.keepLines",
layers: [
{
name: "dojo.js",
dependencies: [
"dijit.form.ValidationTextBox",
"dijit.form.DropDownButton",
"dijit.form.Button",
"dijit.form.Form",
"dijit._base",
"dijit._Container",
"dijit._HasDropDown",
"dijit.form.ComboButton",
"dijit.form.ToggleButton",
"dijit.form._ToggleButtonMixin",
"dojo.parser",
"dojo.date.stamp",
"dojo._firebug.firebug"
]
}, {
name: "../test/test.js",
dependencies: [
"test.test"
]
}
],
prefixes: [
[ "dijit", "../dijit" ],
[ "dojox", "../dojox" ],
[ "ourpeople", "../ourpeople" ]
]
};
The questions I can't seem to find an answer to:
I'm using cssOptimize, I was expecting a single css file in which all the used css files were imported. However I can't find such a file. Is this the way dojo compresses it's css or are my expectations wrong? If so where can I find it in my release folder?
My test.js contains a function test1() if I call it from my built js it states test1 is not defined. I call that function directly without dojo. I'm assuming that building custom js only works if it is a dojo class using declare?
Final question, I needed to include several dojo files in the build manually such as dojo._firebug.firebug since after my initial build it was still using xhr calls to get those files. After including the files manually I still see xhr calls from dojo to specific resources: dojo/nls/dojo_ROOT and dijit/form/nls/validate.js. Those files are created during the build process and therefore can't be included in the dependencies in the build profile. Anyone any thoughts on this matter since I'm looking to distribute dojo in a single file.
I'm fairly new to the dojo build system and (especially) so perhaps I'm expecting things that the dojo build system isn't designed to do or maybe om going about this the wrong way if so any tips or suggestions are more than welcome.
Cheers!
Test.js:
function test1() {
console.log("test1");
}
Index.php:
<script type="text/javascript" src="js/release/dojo/dojo/dojo.js"></script>
<script type="text/javascript" src="js/release/dojo/test/test.js"></script>
<script type="text/javascript">
dojo.require("dijit.form.ValidationTextBox");
dojo.require("dijit.form.Button");
dojo.require("dijit.form.Form");
dojo.ready(function() {
test1();
});
</script>
I'm using cssOptimize, I was expecting a single css file in which all the used css files were imported. However I can't find such a file. Is this the way dojo compresses it's css or are my expectations wrong? If so where can I find it in my release folder?
When you use cssOptimize, the Dojo build optimizes and flattens CSS files in place. So for example, if you're using Dijit's Claro theme, when you load dijit/themes/claro/claro.css from source, it contains a series of #import statements which in turn load more files. When you load claro.css from a build with cssOptimize, it is one file containing all of the styles previously referenced via those separate files.
My test.js contains a function test1() if I call it from my built js it states test1 is not defined. I call that function directly without dojo. I'm assuming that building custom js only works if it is a dojo class using declare?
Dojo doesn't expect every JS file to be a "class" using declare but it does expect each file to be a module which doesn't implicitly define globals (since globals should be avoided in modules anyway). When the build process encounters a module that it thinks or knows isn't AMD, it assumes it's a legacy Dojo module and wraps it in a boilerplate to convert it to AMD. This boilerplate ends up encapsulating your globals into a function scope, so they are no longer globals.
Given that you're using Dojo 1.7, you should ideally be using the AMD format to define and consume modules. dojotoolkit.org has a tutorial introducing AMD modules, and if you're migrating from Dojo 1.6 or earlier, there's also a tutorial to help you transition.
Final question, I needed to include several dojo files in the build manually such as dojo._firebug.firebug since after my initial build it was still using xhr calls to get those files. After including the files manually I still see xhr calls from dojo to specific resources: dojo/nls/dojo_ROOT and dijit/form/nls/validate.js. Those files are created during the build process and therefore can't be included in the dependencies in the build profile. Anyone any thoughts on this matter since I'm looking to distribute dojo in a single file.
I'm not sure why you're seeing dojo/_firebug/firebug being automatically loaded, but based on what you've said/shown above I would immediately suggest the following:
Convert your modules/code to AMD format
Add async: true to your dojoConfig which will cause the loader to operate in asynchronous mode, which means:
It loads modules through script injection instead of synchronous XHR
It won't unconditionally load all of dojo/_base
Add customBase: true to your dojo/dojo layer which will prevent the build from defaulting to include all of dojo/_base
As for the nls modules, to an extent it's normal to still see NLS files requested, though if your build is configured properly there would ordinarily just be one NLS file per layer and that's it (the fact that you're seeing a separate request for validate leads me to think you haven't covered all of your dependencies). The reason NLS remains separate is because there is one NLS bundle per locale, and it doesn't make sense to build all locales into one layer - that would force people to pay for resources in 20 languages they don't care about.
I've developed a JavaScript plugin to be included on our customers' websites. The plugin I've created depends on some external libraries, which are bundled and delivered to the client as one big package: jQuery 1.8.2 and KnockoutJS v3.0.0.
The plugin plays fine on most sites, but if the host site uses RequireJS, my package fails to load because KnockoutJS automatically detects that RequireJS exists and attempts to use it. Here is the error that gets thrown:
Mismatched anonymous define() module
Obviously, I've found an "explanation" of the error message on the RequireJS site. Unfortunately, I don't understand how to avoid it. In my local copy of the KnockoutJS library, I've found the offending line:
(function(factory) {
// Support three module loading scenarios
if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
// [1] CommonJS/Node.js
var target = module['exports'] || exports; // module.exports is for Node.js
factory(target);
} else if (typeof define === 'function' && define['amd']) {
// [2] AMD anonymous module
define(['exports'], factory);
} else {
// [3] No module loader (plain <script> tag) - put directly in global namespace
factory(window['ko'] = {});
}
}
If I manually edit this file so that condition [2] never executes and only condition [3] every executes, then everything works fine. Of course, I don't want to do this because it requires me editing an external library, which I'd prefer to keep in pristine condition so I can upgrade it later.
I have a feeling there may be a way to make this work, I just don't understand how RequireJS works. Obviously, KnockoutJS is TRYING to play nice with RequireJS, but in my case, it's failing. For me, in this case, even though RequireJS exists, I don't need KnockoutJS to use it.
How can I get these two libraries to work side by side?
EDIT
I have no control over when my library is loaded vs. all other libraries the host site already loads. In fact, most of the time my plugin will be included, it will be by someone with NO web dev experience using a terrible WYSIWYG platform like WordPress, Webs.com or Weebly so sometimes my script tag might make it to the top of the head element, other times it might be included in the body element somewhere.
Also, to be clear, my library does NOT use RequireJS. It just so happens that one of our customers that is trying to use my library DOES use RequireJS and when my library gets included, KnockoutJS (bundled with my library, but NOT already on the host site) throws an exception because it thinks it needs to register itself with RequireJS (or at least that's my speculation as to the exception).
While, in principal, I'm not opposed to loading the libraries my code depends on on demand, the truth is that it will create a slow, poor experience for my users as it will take additional request/response cycles to load them.
Well, the easiest thing to do would probably be to load knockout before requirejs. ko will no longer detect that require is present, and will go with option [3]. If you can't do this, the other option is to add your plugin and ko file in a require hierarchy.
So let's say that you plugin looked like this:
(function(ko){
//stuff
ko.applyBindings({});
})(ko)
You would need to change it to this:
require([
"knockout-3.0.0.js" // this should be the url you use for knockout
], function(ko){
//stuff
ko.applyBindings({});
})
and NOT load the knockout.js file as a separate tag. Require will handle the loading. The server must still be able to deliver the "knockout-3.0.0.js" url of course. This is how require works. It loads whatever urls you pass as elements in the array parameter of require, and passes what they return as parameters to the function.
If you need to minify/bundle both the plugin file and the ko file into a single file, you can use the reuquirejs minifier/optimizer (http://requirejs.org/docs/optimization.html). It will navigate the dependency tree and output only one js file with all modules inside. One quirk here: you need to drop the .js extension for the minifier to work, read more about it the documentation, I just mentioned it to save some headaches.
Also, more documentation on how to use ko with require can be found here: http://knockoutjs.com/documentation/amd-loading.html
EDIT, after op edit:
OK, so in this case you should create a separate scope, in which you can do what you want. You'll need to copy the ko code inside your file, but like this you'll at least get a single file.
So, first create a scope:
(function(){
})()
Then copy ko code inside:
(function(){
//ko code here, should be a single, minified line
})()
Then you need to trick ko into using option 3, so do this:
(function(){
var define = null; //so define will no longer be a function, don't forget the var
var require = null;
//ko code here, should be a single, minified line
})()
Optionally, you might also want to reassign window in the step above, if you don't want ko to be available to the entire page.
And now add your plugin code:
(function(){
var define = null; //so define will no longer be a function, don't forget the var
var require = null;
//ko code here, should be a single, minified line
//plugin code here;
})()
I'm trying to convert a JavaScript-heavy page to use TypeScript, with RequireJS to manage the module dependencies.
The problem I've got is that, as well as the inter-dependencies between the TypeScript files, the page also depends on some common JavaScript files that are shared with other parts of the system, not yet converted to AMD.
Is it very dangerous to put non-AMD scripts in normal <SCRIPT> tags above the tag for Require, and just assume that they're loaded?
If that's a bad idea, what's a better way to handle this? Do I need to have AMD and non-AMD version of each script? Or do I need to convert all scripts so that they optionally call define()?
Recent versions of RequireJS allow you to pretend that the plain JS files are actually AMD modules that just return nothing.
The most recent version I tried - 2.1.4 - actually allows you to treat plain JS files like modules. Example:
require(
[
'path/to/module' // <- AMD module
,'path/to/plainjs' // <- actually a plain JS file
]
, function(module, plain){
// module will be per define in that file.
// plain will be 'undefined' type
}
)
You can just mix module-like refs to plain JS files freely. As long as they are loaded in the right order, they will update whatever globals they update and you get what you want. Example:
require(['js/underscore'], function(){
// nesting to insure Underscore, a prereq to BackBone
// completes loading before backbone starts
require(
[
'path/to/module' // <- AMD module
,'js/backbone' // <- actually a plain JS file
]
, function(module){
// module will be per define in that file.
window.BackBone // is available for you
}
)
})
Note, while RequireJS used to require that you add ".js" to the end of the plain JS files to indicate that they are plain JS, in the examples above you do NOT use ".js" This, extension-less module reference allows the module ID to follow paths and maps aliases, while ids with .js are treated as literal and are never translated.
You can manually include the additional scripts in script tags, but this could become the reason things always break for your team (someone forgot to add a particular script).
You can reference the require.d.ts definition from Definitely Typed and make direct calls to the require function rather than an import statement, which might make things more consistent for you.
I am learning about require.js and think I am just missing something. I don't understand how it loads files.
I have my jquery file in a lib directory.
This does not work:
It shows that jquery is being loaded in the chrome network panel. Error is: Uncaught TypeError: undefined is not a function . so it is basically saying that $ is undefined.
require(['lib/jquery'],function($) {
$(document).ready(function(){
alert('hello');
});
});
This works:
require.config({
paths: {
jquery: 'lib/jquery'
}
});
require(['jquery'],function($) {
$(document).ready(function(){
alert('hello');
});
});
In other examples I see online you don't have to set the paths with require.config. Do I have to do this every time that I want to define a module? I know I am using require and not define in this case, but I am having the same issue with the define method. Every time I make a module using define I have to set the paths using require.config(). I think I am missing something here. Can anyone point me in the right direction?
This is a constraint on the AMD registration done by jquery. It explicitly registers as a named module called 'jquery' so you must have a paths config in for it, or in the case above, set baseUrl to be 'lib' then you do not need the paths config.
Other libraries normally should use an anonymous module registration, so you should not need to do a paths config for every library. More details here.
Also, some libraries, like underscore, do not call define() directly, but you can get a level of support by using the shim config.
Update to reflect comments and James' answer:
You have two problems:
jQuery, for the reasons James outlines in his answer, requires that you either have paths set in your config, or that you, in the code you've outlined, set baseUrl to "lib".
you have to remember that you can't just load any old script with RequireJS. Only scripts that conform to the AMD standard can be loaded.
Having said this, I'd advice you use require-jquery instead.
You'll probably end up using jQuery plugins that will assume jQuery is loaded on the page, and those won't work with the approach you're trying.