The default loading method of js through script tags is synchronized, that is, after the js in the first script tag is loaded, the second one begins to be loaded, and so on, until all the js files are loaded. Moreover, the dependencies of js must be ensured through script order; and during js loading, the browser will stop responding, which greatly affects the user experience. Based on this, many solutions to js have appeared and loaded, requiring js is one of them.
The modules loaded by requirejs are generally modules that comply with AMD standards, that is, modules that define with define and return exposed methods and variables with ruturn; requirejs can also load modules that fly AMD standards, but it is more troublesome and will not be involved this time.
Require loading js main involves the following aspects:
html demo
<script src ="js/require.js" defer async="true" data-main="js/main" ><!--Give the requiredjs path, declare it as async loading, specify the entry module as main.js (can be omitted.js)-->
main.js
require.config({ //Declare the location of the module paths: { "jquery":"libs/jquery" "login" : "libs/login" } //Or use baseUrl to specify the path of all modules baseUrl: "js/libs" }); //Use require to load the module. The first parameter is an array, that is, the module to be loaded will be loaded in the order of the array; the second is a callback function, which is executed after all loading is completed. require(['jquery','login'],function($,Login){ alert("jquery and login module load success!"); Login.do_login(); //some else });Login module definition in line with amd
//Definition definition of jquery(['jquery'],function($){ // some definitions function do_login(){ $.post('/sessions/create',{uname:$("#uname").val(), password:$("#password").val()},function(data){ //some }); return {do_login:do_login}; } });//Definition definition of other modules(function(){ //some definitions return {xx:xx};});Rails does not apply a js loader. On the one hand, the new version of Rails asset pipe will package all js files into one js file, without multiple js loading status. On the other hand, turbolink uses the so-called pjax technology with mixed praise and criticism. The default link is changed to Ajax method, and only gets the bod part of the html and the head part remains unchanged, so that js loading is only performed when the website is opened for the first time.
Case 1: Loading JavaScript files
<script src="./js/require.js"></script> <script> require(["./js/a.js", "./js/b.js"], function() { myFunctionA(); myFunctionB(); }); </script>The string array parameter in the require method can allow different values. When the string ends with ".js", or starts with "/", or is a URL, RequireJS will think that the user is directly loading a JavaScript file. Otherwise, when the string is similar to "my/module", it will think that this is a module, and will load the JavaScript file where the corresponding module is located with the baseUrl and paths configured by the user. The configuration section will be described in detail later.
It should be pointed out here that by default, RequireJS does not guarantee that myFunctionA and myFunctionB must be executed after the page is loaded. When it is necessary to ensure that the script is executed after the page is loaded, RequireJS provides an independent domReady module. You need to download this module from the RequireJS official website, which is not included in RequireJS. With the domReady module, the code in Case 1 is just slightly modified and the dependency on domReady.
Case 2: Execute JavaScript after the page is loaded
<script src="./js/require.js"></script> <script> require(["domReady!", "./js/a.js", "./js/b.js"], function() { myFunctionA(); myFunctionB(); }); </script>After executing the code of Case 2, through Firebug, you can see that RequireJS will insert a <script> tag on the current page as a.js and b.js respectively declare a <script> tag for downloading JavaScript files asynchronously. The async attribute is currently supported by most browsers, which indicates that the js file in this <script> tag will not block the download of other page content.
Case 3: <script> inserted by RequireJS
<script type="text/javascript" charset="utf-8" async="" data-requirecontext="_" data-requiremodule="js/a.js" src="js/a.js"></script>
Use RequireJS to define JavaScript modules
What's different from traditional JavaScript code here is that it does not require access to global variables. The modular design allows JavaScript code to pass these "global variables" as parameters through dependencies when it needs to access "global variables", and avoid accessing or declaring global variables or functions in the implementation, effectively avoiding a large number of and complex namespace management.
As stated in the AMD specification of CommonJS, defining JavaScript modules is implemented through the define method.
Let’s first look at a simple example. This example creates student objects in the main program and puts the student objects into the class by defining a student module and a class module.
Case 4: student module, student.js
define(function(){ return { createStudent: function(name, gender){ return { name: name, gender: gender }; } }; }); });Case 5: class module, class.js
define(function() { var allStudents = []; return { classID: "001", department: "computer", addToClass: function(student) { allStudents.push(student); }, getClassSize: function() { return allStudents.length; } }; } );Case 6: Main program
require(["js/student", "js/class"], function(student, clz) { clz.addToClass(student.createStudent("Jack", "male")); clz.addToClass(student.createStudent("Rose", "female")); console.log(clz.getClassSize()); // Output 2 });The student module and the class module are both independent modules. Let's define a new module. This module relies on the student and class modules, so that the logic of the main program part can also be wrapped.
Case 7: Manager module that relies on student and class modules, manager.js
define(["js/student", "js/class"], function(student, clz){ return { addNewStudent: function(name, gender){ clz.addToClass(student.createStudent(name, gender)); }, getMyClassSize: function(){ return clz.getClassSize(); } }; });Case 8: New main program
require(["js/manager"], function(manager) { manager.addNewStudent("Jack", "male"); manager.addNewStudent("Rose", "female"); console.log(manager.getMyClassSize());// Output 2 });Through the above code example, we have clearly understood how to write a module, how this module is used, and how to define the dependencies between modules. There are still some tips to use:
Try not to provide the module's ID. As stated in the AMD specification, this ID is an option. If provided, the module's migrationability will be affected in the implementation of RequireJS, and file location changes will cause the ID to be modified manually.
Each JavaScript file defines only one module. The search algorithm for module name and file path determines that this method is optimal. Multiple modules and files will be optimized by the optimizer. Avoid circular dependencies of modules. If it is really impossible to avoid, you can add dependencies on "require" modules to the module and use them directly in the code.
require("dependencyModuleName")Configure RequireJS:
In the previous introduction, we seem to have overlooked a basic question: how did the module name come from? When I require a module, how does this module map to a specific JavaScript file? This involves how to configure RequireJS.
The simplest way to load RequireJS is shown in Case 2. In this case, we do not specify a baseUrl and paths to RequireJS. If the method shown in Case 10, data-main specifies a /js/main.js in the folder parallel to the current index.html directory as the program entrance, and the /js directory will also be used as baseUrl when defining other modules.
Case 9: Loading require.js
<script data-main="js/main" src="scripts/require.js"></script>
Therefore, all module dependencies in our previous examples can be removed from "js/" and write "student", "class", "manager", etc. directly. A more direct way to display the specified baseUrl and paths is to use require.config to set these parameters. As shown in Case Ten.
Case 10. Configuring RequireJS
<script type="text/javascript" src="./js/require.js"></script> <script type="text/javascript"> require.config({ baseUrl: "./js", paths: { "some": "some/v1" }, waitSeconds: 10 }); require( ["some/module", "my/module", "./js/a.js"], function(someModule, myModule) {} ); </script>baseUrl indicates the base URL of all modules. For example, the script loaded by "my/module" is actually /js/my/module.js. Note that files ending in .js will not use the baseUrl when loading, they will still use the relative path where the current index.html is located, so you still need to add "./js/". If baseUrl is not specified, the path specified in data-main will be used.
The path defined in paths is used to replace the path in the module, such as some/module in the above example. The specific JavaScript file path is /js/some/v1/module.js. waitSeconds specifies how long it takes to load a JavaScript file. The default is 7 seconds without the user specifying it.
Another important configuration is packages, which can specify other directory structures that comply with the CommonJS AMD specification, thus bringing rich scalability. Modules such as Dojo, jQuery, etc. can also be loaded by RequireJS through this configuration.
Other configurable options include locale, context, deps, callback, etc. Interested readers can check the relevant documents on the official website of RequireJS.