I have seen people use an alternate define "syntax" in require js than what is described in the require js' documentation, or in many tutorials.
The usual define "syntax":
define(['module/first'], function (firstModule) {
//Module code with a dependency on module/first goes here.
});
The alternate define "syntax":
<script data-main="app/config" src="assets/js/libs/require.js"></script>
file: config.js:
require.config({
paths: {
jquery: '../assets/js/libs/jquery'
}
});
require(['app']);
file: app.js:
define(function(require) {
var FirstModule = require('modules/first');
//Module code with a dependency on module/first goes here.
What are the advantages, and disadvantages of using this alternate "syntax"?
RequireJS is a JavaScript library and file loader which manages the dependencies between JavaScript files and in modular programming. It also helps to improve the speed and quality of the code.
Advertisements. The define() function can be used to load the modules (module can be an object, function, class or a code which is executed after loading a module). You can load different versions of the same module in the same page.
RequireJS has been a hugely influential and important tool in the JavaScript world. It's still used in many solid, well-written projects today.
To include the Require. js file, you need to add the script tag in the html file. Within the script tag, add the data-main attribute to load the module. This can be taken as the main entry point to your application.
I think your explanation is a bit misleading: in both cases, you will have a top-level require
call with a data-main
attribute specifying a file to kick-start the process of requiring different modules.
So typically you will have this in your HTML:
<script data-main="app/config" src="assets/js/libs/require.js"></script>
Then, in both cases, you would have a file app/config
which sets your configuration (although you could do this directly in the HTML) and more importantly calls require
on your modules:
require.config({
paths: {
jquery: '../assets/js/libs/jquery'
}
});
require(['app']);
Now, it's when we get to defining modules with dependencies that these styles differ. In the amd style you pass in the module names (paths) as an array, and a function which takes the same number of arguments:
app.js
define(['module/first', 'module/second', 'module/third'], function (firstModule, secondModule, thirdModule) {
// use firstModule, secondModule, thirdModule here
});
In the simplified CommonJS syntax, you just pass require
into define
and then require whatever modules you need inline:
app.js
define(function(require) {
var firstModule = require('modules/first');
var secondModule = require('modules/second');
var thirdModule = require('modules/third');
// use firstModule, secondModule, thirdModule here
}
Getting back to your original question, the advantages of the CommonJS style over the amd style should be clear.
For one thing, with the conventional syntax, if there are many modules being required, it is very easy to mistakenly assign modules to the wrong variable names. Consider this common case:
define(['jquery', 'underscore', 'backbone', 'modules/first', 'modules/second', 'modules/third', 'i18n', 'someOtherModule'], function ($, _, Backbone, first, second, third, I18n, someOtherModule) {
// ...
});
Right away, you can see that when we add a new module to this list, we have to be very careful that the corresponding new function argument appears in the right place, or else we can have jQuery assigned to Backbone
, etc. In some cases this can create very subtle bugs that are hard to track down.
Now consider the CommonJS syntax:
define(function(require) {
var $ = require('jquery');
var _ = require('underscore');
var Backbone = require('backbone');
var firstModule = require('modules/first');
var secondModule = require('modules/second');
var thirdModule = require('modules/third');
var I18n = require('i18n');
var someOtherModule = require('someOtherModule');
// ...
}
Note that:
Those are just a few reasons that come to mind, I'm sure there are others. Basically, if you just have one or two dependencies, either syntax will do fine. But if you have a complex network of module dependencies, the CommonJS syntax is probably preferable.
Note that in the RequireJS docs, they mention this small caveat:
Not all browsers give a usable Function.prototype.toString() results. As of October 2011, the PS 3 and older Opera Mobile browsers do not. Those browsers are more likely to need an optimized build of the modules for network/device limitations, so just do a build with an optimizer that knows how to convert these files to the normalized dependency array form, like the RequireJS optimizer.
But this is not a major issue:
Since the number of browsers that cannot support this toString() scanning is very small, it is safe to use this sugared forms for all your modules, particularly if you like to line up the dependency names with the variables that will hold their module values.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With