ArticleDirectory
- This series of directories
- Background
- CMD module definition specifications
- Modular Transformation
- Deep Learning
- Legacy problems
- To be continued
After reading instructor Ruan Yifeng's article on JavaScript modularization, I answered my long-thinking questions and suddenly felt a sudden sense of openness. Later I learned about seajs and wanted to write an article to practice Modular programming. I wrote the article today. I hope it will be useful to you.
This series of directories
- "Javascript Modular programming (I): module prototype and theoretical concepts"
- Javascript Modular programming (II): Modular programming practices, detailed explanation of require. js
Two "Guides" in the third article"
- Give me 35 chances to guess your mobile phone number.
- Source code analysis of 'mobile phone number game': Binary Search + object-oriented
- Javascript Modular programming (III): Practical Application of Modular programming, trial use of seajs
Some time ago, I reproduced two articles by instructor Ruan Yifeng explaining JavaScript Modular programming: "javascript Modular programming (I): module prototype and theoretical concept details ", the prototype and theoretical concepts of JavaScript modules are introduced. The modular programming of JavaScript (2): Practical Application of Modular programming, require. JS details introduce how to use the requirejs library for Modular programming in practice.
After these two articles were published, I learned about seajs, a modular programming library created by yuber, a Chinese speaker. Then, I want to learn and write an article to introduce it to you.
Background
Official website information is the most reliable. On the seajs official website, we found that there was an example of "getting started with seajs in 5 minutes", and then we started to learn from this example. However, I can only see six, six, seven, and seven. I didn't understand what the difference is from my usual JavaScript programming. In addition, I have no hands-on practice, and I am not steadfast in my mind. Therefore, writeProgram. Later, I thought of "Phone Number Game "!
Because the official website already has a tutorial on using seajs, I will not repeat this work, and I also feel that I certainly have not written it well on the official website. As I don't know, the difference between "Modular programming" using seajs and that I do not "Modular programming" at ordinary times. So I want to introduce seajs from another perspective:Transform a program without Modular programming into a program using seajs for "Modular programming". This idea has a large span and a large amount of information. So I organized my thoughts into three articles: the first article, "Give your brother 35 chances to guess your mobile phone number." through a small game, to attract everyone's interest. The second article, "Source code analysis of 'phone number game': Binary Search + Object-Oriented", explains the implementation details of the program without Modular programming; next, this is the third article. Without Modular programming, we transformed the original program into an example of Modular programming using seajs.
Before reading this article, read the first two articles, especially the source code analysis of 'Guess mobile phone number game': Binary Search + object-oriented ". At the same time, it is recommended to read "javascript Modular programming (1): module prototype and theoretical concept details" and JavaScript Modular programming (2): Modular programming practice, require. JS details: standardize and system the knowledge about JavaScript Modular programming.
CMD module definition specifications
To enjoy the good encapsulation brought about by Modular programming, you must follow the modular programming specifications. In seajs, all JavaScript modules comply with the CMD (common module definition) specification. This specification determines the basic writing format and basic interaction mode of the module. Therefore, before using seajs, you must read the rules that seajs requires.
In view of the wide range of contents covered by regulations, it seems that there are more things. Therefore, I want to simplify this specification and focus only on what we need. As for the detailed definition specifications of the CMD module, let's take the example and understand the entire process. Then, let's look back at the specifications and sort out and standardize the knowledge.
Before introducing the simplified version specifications, d guago raised two questions that may be "puzzled:
- How to define a module?
- How to obtain external dependent modules?
The main content of the CMD module definition specification is to answer these two questions. See the following simplified rules by D guago:
- Define and encapsulate modules.(There are many definition methods in the CMD module definition specification. For the sake of simplicity, we only consider using the following method .) As follows:
Define (function (require, exports, module) {// The module code goes here });
Please note that,The three parameter names passed to the parameter must followCodeAs shown in, it cannot be abbreviated or replaced by other strings. At the same time, exports cannot be rewritten to other values in the function. You can regard exports as an object to add attributes, such as exports. key, and then copy it, such as exports. key = "dvalue ".
- Provides external module interfaces.In the previous step, we defined the module in the function, but this is defined in the function, and it is not easy to access outside the function. How can I provide a Module Interface? The definition method is as follows:
Define (function (require, exports, module) {// This method provides the Module Interface Module. exports = {FOO: 'bar', dosomething: function () {};}; // or. Because d guago encapsulates the module as an object, this method is used in this example. Module. Exports = yourfunctionname ;});
The function passed to the factory Constructor (that is, the function in the define (function () {}) method parameter is called factory. The function is only a form of factory, and Other forms will be supplemented later .) The exports parameter of is a reference of the module. Exports object. The interface is provided only through the exports parameter, and sometimes cannot meet all developers' needs. For example, when the Module Interface is an instance of a class, it must be implemented through module. Exports. D. guago is an object, so you can only use module. Exports.
- Obtain the external dependency module.When the module definition is required, you can use the require function to obtain external dependencies. The Code is as follows:
Define (function (require, exports, module) {// use the require function to obtain the external dependency var A = require ('./A'); A. dosomething ();});
The parameter of the require function is the relative path of the. js file. The extension name can be omitted. It is automatically added when seajs loads the module. In addition, the callback function can be executed here. However, our task is to run. Because callback functions are not required, this part is skipped first.
Summary:Define function, define module; module object, save module information; require function, get external dependency module.
It is estimated that everyone is still confused. It doesn't matter. Let's take a look. When the following example runs, you will understand it again.
Modular Transformation
Let's first declare that the following transformation process will refer to the description of "getting started in 5 minutes. Therefore, we suggest you take a look. Of course, you can also watch it together.
By looking at the example of "getting started in 5 minutes", we can see that the directory structure of seajs is still a bit complicated. Therefore, the simplest way is to download her example and modify it based on her: Download the "5-minute getting started" example.
Directory structure
After the download is complete, decompress the package to any directory. Please take a look at the directory,
- Hello-seajs/delegate our HTML file;
- Hello-seajs/assets/sea-modules stores the third-party module blocks we need;
- Hello-seajs/assets/Main. This directory can be said to be the most important. It is the place where we store our own JavaScript and CSS files. There are four sub-directories and one file below:
- SRC stores normal code;
- Test stores the test code;
- Docs stores documents;
- Examples stores sample code;
- Package. JSON is a package configuration file;
Code of the "transformation" module
Next, we start to transform our modules.
First, put my guessnumber. js under hello-seajs/assets/main/src. Then, modify the code in this file according to the requirements of "1st specifications. Because the entire file is the definition of the guessnumber object. At the same time, this Javascript file does not reference other modules. Therefore, you only need to add define in the first line of the file and add a semicolon in the last line. The Code is as follows:
Define (function (require, exports, module) {/*** numberscope number range to be guessed */function guessnumber (numberscope) {// to highlight the modified Code, I omitted some of the same Code, // complete code please see: http://www.diguage.com/archives/80.html} guessnumber. prototype = {constructor: guessnumber, // complete code see: http://www.diguage.com/archives/80.html }});
Secondly, we have defined it as a module. But how do I access this guessnumber externally? Therefore, we need to provide an external interface. For more information, see "2nd specifications ". For specific code, see Row 3:
Define (function (require, exports, module) {/*** numberscope number range to be guessed */function guessnumber (numberscope) {// complete code can be found at: http://www.diguage.com/archives/80.html} guessnumber. prototype = {constructor: guessnumber, // For the complete code, see http://www.diguage.com/archives/80.html#module.exports = guessnumber ;});
At this time, all interfaces have been defined. Below is an example of calling this module.
In article 3 of the "Specification", we illustrate the method for loading external dependency modules. We only need to do it according to the instructions. In addition, you need to pay attention to the loading of modules. For details, see the code comment:
Define (function (require) {// This is the introduction of the jquery class library. The following describes why. VaR $ = require ('jquery '); // introduce the guessnumber module, that is, the guessnumber. js file. // The parameter specifies the relative path of the guessnumber. js file. // The extension name of. js can be omitted. seajs will be automatically added during loading. VaR guessnumber = require ("./guessnumber"); // For the complete code, see http://www.diguage.com/archives/80.html//formatting. The result function formatresult (Num, type ){//......} //...... $ ("# Initbutton "). click (function () {Guess. start (scopearr [type]. min, scopearr [type]. max); showresult ();});});
From the code above, we can see that the transformation of the Main. js file only sets the original
$ (Document). Ready (function () {// main business code });
Transformed,
Define (function (require) {// This is the introduction of the jquery class library. The following describes why. VaR $ = require ('jquery '); // introduce the guessnumber module, that is, the guessnumber. js file. // The parameter specifies the relative path of the guessnumber. js file. // The extension name of. js can be omitted. seajs will be automatically added during loading. VaR guessnumber = require ("./guessnumber"); // same business code as the original file });
In addition, two lines of code are added to add the necessary associated modules. That's all.
Another difference between main. js and guessnumber. JS is that main. js does not need to provide external access interfaces. Pay attention to this.
All the JavaScript code has been modified. Next, let's modify how to introduce in HTML.
Load modules on the page
The original syntax is to use the <scrip> tag to introduce jquery, guessnumber. JS, and Main. js files to the HTML page in sequence. If seajs is used, you need to first load the seajs class library, and then use JavaScript to load the required module through the seajs interface, that is, the Javascript file corresponding to the module. The Code is as follows:
<! -- First, we need to introduce sea. JS -->
<SCRIPT src = "assets/sea-modules/seajs/1.3.1/sea. js"> </SCRIPT>
<SCRIPT type = "text/JavaScript">
Seajs. config ({
Alias :{
// Specify the jquery version used and the jquery path
// Note: The jquery path is well-known. Therefore, we
// When introducing the jquery library, you only need to enter jquery.
'Jquery ': 'gallery/jquery/1.8.2/jquery'
}
});
// Seajs then loads the module by using the use method, which will be modified here After packaging
// You may wonder why the guessnumber. js file is not loaded,
// When you use require to introduce dependencies, seajs automatically loads the required external files
// In addition, The. js suffix can be omitted here, And seajs will automatically complete.
Seajs. Use ('./assets/main/src/main ');
</SCRIPT>
<! -- Only the Code related to JavaScript introduction is shown here -->
<! -- Complete code see: HTML code in http://www.diguage.com/archives/80.html -->
By now, all the transformation work has been completed. You can open the inde.html file to check the effect.
Package and deploy
According to the practice in "14 golden rules of high-performance websites", when we launch a project, we must compress JavaScript files to speed up page loading. In this case, seajs has also taken into account and even done better: It has also implemented file merging.
Here, we need to first introduce SPM, a command line-based front-end project management tool. SPM is closely related to seajs. You can even think that SPM is a specialized tool for seajs. First, install this tool in "installation tutorial. There may be a problem according to the process. Please refer to the "problems" below ".
To package with SPM, You need to modify the package configuration file. The configuration file is hello-seajs/assets/main/package. JSON. The following content is displayed:
{"Name": "Main", "version": "1.0.0", "dependencies": {"jquery": "Gallery/jquery/1.8.2/jquery "}, "root": "Hello-seajs", "output": {"Main. JS ":". "," main.css ":". "}," spmconfig ": {" build ": {" ":".. /sea-modules/{root}/{name}/{version }}"}}}
However, this needs to be modified based on our actual situation. . In addition, note that the output path after packaging is the first line. Now, start packaging. To package a package, run the following command:
$ CD hello-seajs/assets/main $ SPM build... build success! $
After packaging, you will find an additional guessnumber folder in hello-seajs/assets/, which is packaged and output.
Here, we will explain that D guago only executed this command in Linux. I wonder if windows is easy to use. To facilitate testing, the packaging results have been submitted. The downloaded code contains the packaging results.
Observe this result and you will find that there is only one main. JS and main-debug.js; as the name suggests, Main. JS is used for production deployment, compressed files; main-debug.js is used for testing, but Merged Code does not compress, when used directly reference one of the two files on the line, directly add seajs. in use (), change the path to OK. Where did guessnumber. js go? You can open the main-debug.js to see (main. js also line, just compressed, readability is not good), the original, guessnumber. js has been merged into main. js. SPM merges the two files into one file, so that when the browser accesses the webpage, it can reduce an HTTP request and increase the loading speed of the webpage.
In addition, you may also notice that in the original main. the define () function defined in JS, in the new main. JS has some changes, with two more parameters: the ID of the first parameter module, mainly to facilitate the distinction between each module in a file; the second parameter is the path of the external module on which the module depends. because there may be multiple dependent modules, this parameter is an array. The third parameter is the original function, that is, the factory. For more details, see: Why is SPM used to compress the CMD module?
Lazy people need to be lazy to the end! After packaging, you must modify the seajs loading path, which can be avoided by using the following code:
// This path can only be deployed on the server. It is difficult to open the file directly. Seajs. Use (location. Host === 'localhost '? './Assets/main/src/main': 'guessnumber/main/1.0.0/main ');
You can also use variables to configure non-static pages.
Problems
It is inevitable that some problems will occur when such a thing is tossing. d guago has encountered three problems. These problems are mainly concentrated in the establishment of the SPM environment. Share with you.
First problem: when following seajs, the error message "info. JSON" does not exist. The terminal displays the following:
D @ DPC :~ /Dev/Hello-seajs/assets $ SPM install seajsstart installing... success create global config. JSON to/home/D /. spmdownloading: http://modules.spmjs.org/info.jsonjavaserror] caught exception: Error: Not found config http://modules.spmjs.org/info.json
You can open http://modules.spmjs.org/info.jsonin the browser address and you will find that you can open it. What's going on?
I checked the seajs forum and found similar problems. One of the replies is my answer: this is the day of national celebration and the network is unstable. As for the reason, you know. It is estimated that it will be okay after this period of time. Therefore, since the browser can access the content, the content can be accessed. If you encounter this problem, try it twice.
The second problem: According to the jquery library, the error: already_exists is prompted. The terminal displays the following:
D @ DPC :~ /Dev/Hello-seajs/assets $ SPM install Gallery. jquerystart installing... downloading: http://modules.spmjs.org/gallery/info.jsondownloaded: http://modules.spmjs.org/gallery/info.jsondownloading: too many this module already exists: /home/D/dev/Hello-seajs/assets/sea-modules/Gallery/jquery/1.8.2turn on -- force option if you want to override it. [Error] Caught exception: Error: already_exists
As shown in the feedback, the jquery library already exists and does not need to be downloaded again. In the hello-sea exampleSource codeThe source code already contains jquery, which can be ignored here.
Third problem: After package. JSON is modified, an error is returned when the package is re-compiled. The terminal displays the following:
[Warn] http://modules.spmjs.org/GuessNumber/config.json null
This does not affect compilation. Just ignore it. In addition, this error is not seen during the first packaging; the second packaging will appear.
Code download
To help you download the code, I host the code on GitHub. You can download it from GitHub and submit your modifications. GitHub page: guessnumber; if you do not want to download it from GitHub, you can also click Download directly: Click Download.
Deep Learning
The above example is just a brief example to give you a more vivid picture. However, this example is too simple. I also need to add some knowledge that we just simplified for ease of understanding. To learn more about seajs, read the "seajs User Guide ". In addition, here are a few things to focus on:
- CMD module definition Specification
- Require writing conventions
- Module ID
- Quick api reference
- Module loading and startup, focus on the "best practices"
- Module System
After reading all the things in this list, seajs should be ready to learn. If you have any good information, please recommend it to me. I will try again.
Legacy problems
After the above tossing, we have successfully run an example of Modular programming using seajs. However, we still have many questions. The specific questions are as follows:
- D. $ (document) is not used in Js ). ready (); when the Dom is loaded and then run, it does not talk about putting JS at the end of the HTML file. why can it be executed in sequence? What is the internal mechanism of mofei seajs to ensure that we can execute our own JavaScript code after Dom loading is complete?
- The example here is very small, and there are not many modules. In many cases, if a module is organized? You need to write more examples.
- Similarly, in the case of many modules, do you need to create many directories and prepare many main. js files so that many HTML files can be loaded separately?
Just a moment ago, d guago opened it. Main. JS is just an example. you can name your own component and load the corresponding Javascript file in the component. In addition, when configuring package. in JSON format, I suddenly felt that every directory in/assets/main/src/should be regarded as a module with a package configuration file. JSON, used to configure necessary information for this module. I wonder if this understanding is correct? This is to be verified.
To be continued
This article is just a brief introduction to seajs. To gain a deeper understanding of the principles of seajs, d guago thinks that the most reliable method is to implement a seajs. Therefore, in the next article, d guago is ready to implement a simplified version of seajs. Of course, to facilitate understanding of seajs, the implementation of D guago will refer to the "cmd module definition specification" to write code. Coming soon!
PS:
This article has a lot of code and poor layout. It looks not very nice. If you have any good suggestions, please leave a message and ask D guago to immediately improve it. Thank you!
References:
References have been posted in articles, so I will not repeat them here.
Spam:
I spent a lot of effort using syntaxhighlighter to arrange a very beautiful version of the code. It was not easy to go to the "blog Garden. Only pre blocks can be used. We hope the "blog Park" can support syntaxhighlighter. syntaxhighlighter is really good and powerful!
This article is also published on my personal blog, digua. For more information, see the author and original website.
Sweet potato: http://www.diguage.com/archives/82.html