Now, Require.js is my favorite way to program Javascript. It makes code-breaking into pieces and easy to manage. Require.js Optimizer can help us distribute a larger application into multiple smaller applications, connect it through dependencies, and finally merge it during compilation and packaging. These reasons prompt us to use require.js.
So, let’s take a look at what awesome features require.js have!
Compatible with CommonJS
AMD (Asynchronous module definition specification) appears from the CommonJS workgroup. CommonJS aims to create an ecosystem of Javascript. An important part of CommonJS is transport/c, the predecessor of AMD, and require.js is an implementation of this specification.
The syntax difference between CommonJS module and AMD module is mainly due to AMD's need to support the asynchronous features of the browser. The CommonJS module needs to be synchronized, for example:
The code copy is as follows:
var someModule = require( "someModule" );
var anotherModule = require( "anotherModule" );
exports.asplode = function() {
someModule.doTehAwesome();
anotherModule.doMoarAwesome();
};
The AMD module loads the module asynchronously, so the module definition requires an array as the first parameter, and the callback function after the module is loaded is passed in as the second parameter.
The code copy is as follows:
define( [ "someModule"], function( someModule ) {
return {
asplode: function() {
someModule.doTehAwesome();
// This will be executed asynchronously
require( [ "anotherModule" ], function( anotherModule ) {
anotherModule.doMoarAwesome();
});
}
};
});
However, AMD is also compatible with CommonJS syntax in require.js. By wrapping the CommonJS module through AMD's define function, you can also have a CommonJS module in AMD, for example:
The code copy is as follows:
define(function( require, exports, module )
var someModule = require( "someModule" );
var anotherModule = require( "anotherModule" );
someModule.doTehAwesome();
anotherModule.doMoarAwesome();
exports.asplode = function() {
someModule.doTehAwesome();
anotherModule.doMoarAwesome();
};
});
In fact, require.js interprets the module content of the callback function through the function .toString, finds its correct dependency, and turns it into a normal AMD module. It should be noted that if you write modules in this way, it may be incompatible with other AMD loaders because this violates the AMD specification, but it can understand how this format is written well.
What's going on here, requires.js actually does the function.toString callback function parses the module's contents and finds the correct dependency, just like it if it's a normal AMD module. It is important to note that if you choose to write modules like this, they will most likely be incompatible with other AMD module loaders as this violates the AMD specification, but it is a good idea to understand this format exists!
CDN Back
Another hidden require.js treasure is that it supports rollback loading the local corresponding library when the CDN is loading incorrectly. We can achieve this through require.config:
The code copy is as follows:
requirejs.config({
paths: {
jquery: [
'//cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js',
'lib/jquery'
]
}
});
No dependencies? Object literal? no problem!
When you write a module that has no dependencies and just returns an object that contains some functional functions, we can use a simple syntax:
The code copy is as follows:
define({
forceChoke: function() {
},
forceLighting: function() {
},
forceRun: function() {
}
});
It's simple and useful if the module is just a collection of functions, or just a packet.
Circular dependency
In some cases, we may need the functions in modules moduleA and moduleA to rely on some applications. This is circular dependency.
The code copy is as follows:
// js/app/moduleA.js
define( [ "require", "app/app"],
function( require, app ) {
return {
foo: function( title ) {
var app = require( "app/app" );
return app.something();
}
}
}
);
Get the module address
If you need to get the address of the module, you can do this...
The code copy is as follows:
var path = require.toUrl("./style.css");
BaseUrl
Usually, when conducting unit tests, your source code may be placed in a folder similar to src, and at the same time, your test may be placed in a folder similar to tests. This may be difficult to get the test configuration correct.
For example, we have an index.html file in the tests folder and need to load tests/spec/*.js locally. And assuming that all source code is in src/js/*.js and there is a main.js in that folder.
In index.html, data-main is not set when requiring.js is loaded.
The code copy is as follows:
<script src="src/js/vendor/require.js"></script>
<script>
require( [ "../src/js/main.js" ], function() {
require.config({
baseUrl: "../src/js/"
});
require([
"./spec/test.spec.js",
"./spec/moar.spec.js"
], function() {
// start your test framework
});
});
</script>
You can find that main.js is loaded. However, since data-main is not set, we need to formulate a baseUrl as we want. When using data-main, baseUrl will automatically set according to the file it sets.
Here you can see main.js is loaded. However, since it does not load the data main script tag, then you have to specify a base. When the data is mainly used for baseURL, inferred from the location in the main file. By customizing baseUrl, we can easily store test code and application code separately.
JSONP
We can handle JSONP terminals like this:
The code copy is as follows:
require( [
"http://someapi.com/foo?callback=define"
], function (data) {
console.log(data);
});
For non-AMD libraries, use shim to solve
Under many requests, we need to use non-AMD libraries. For example, Backbone and Underscore do not adapt to the AMD specification. And jQuery actually just defines itself as a global variable called jQuery, so you don't have to do anything with jQuery.
Fortunately, we can use the shim configuration to solve this problem.
The code copy is as follows:
require.config({
paths: {
"backbone": "vendor/backbone",
"underscore": "vendor/underscore"
},
shim: {
"backbone": {
deps: [ "underscore" ],
exports: "Backbone"
},
"underscore": {
exports: "_"
}
}
});