Download and install
To use SeaJS in your project, all the preparation you need to do is download sea.js and put it somewhere in your project.
The SeaJS project is currently hosted on GitHub, with the homepage at https://github.com/seajs/seajs/. You can download sea.js (compressed) or sea-debug.js (uncompressed) in the build directory of its git library.
After the download is completed, put it in the corresponding position of the project, and then introduce it through the <script> tag on the page, and you can use SeaJS.
SeaJS basic development principles
Before discussing the specific use of SeaJS, let’s first introduce the modular concept and development principles of SeaJS.
The basic principle of using SeaJS to develop JavaScript is: Everything is a module. After SeaJS was introduced, writing JavaScript code became writing one module after another. The concept of modules in SeaJS is somewhat similar to object-oriented classes - modules can have data and methods, and data and methods can be defined as public or private, and public. Data and methods can be called by other modules.
In addition, each module should be defined in a separate js file, that is, one corresponding to one module.
The following describes the writing and calling of modules.
Definition and writing of modules
Module definition function define
In SeaJS, use the "define" function to define a module. Because SeaJS documentation does not have a complete reference for definition, I read the SeaJS source code and found that define can receive three parameters:
Copy the code as follows:/**
* Defines a module.
* @param {string=} id The module id.
* @param {Array.|string=} deps The module dependencies.
* @param {function()|Object} factory The module factory function.
*/
fn.define = function(id, deps, factory) {
//code of function…
}
The above is excerpted from the SeaJS source code. The parameters that define can receive are module IDs, dependencies on module arrays and factory functions. After reading the source code, I found that the parsing rules for the number of different parameters of define are as follows:
If there is only one parameter, then assign the value to the factory.
If there are two parameters, the second is assigned to factory; if the first is an array, it is assigned to deps, otherwise it is assigned to id.
If there are three parameters, they are assigned to id, deps and factory respectively.
However, almost all places where define are used, including SeaJS's official example, only one factory function is passed in, similar to the following code:
The code copy is as follows:
define(function(require, exports, module) {
//code of the module...
});
I personally recommend that you follow the standards of SeaJS official examples and define the module with a parameter definition. So what will be done with id and deps?
id is the identification string of a module. When define has only one parameter, id will be assigned to the absolute path of this js file by default. If you use define to define the module in the a.js file under example.com, the ID of this module will be assigned to http://example.com/a.js. There is no special need to recommend not passing in the id. Deps generally does not need to be passed in, and the modules needed can be loaded with require.
Factory function factory analysis
Factory functions are the main body and focus of the module. When only one parameter is passed to define (recommended writing), this parameter is the factory function. At this time, the three parameters of the factory function are:
1.require-Module loading function, used to record dependent modules.
2.exports-interface point, when defining data or method, exposes it to external calls.
3.module-the metadata of the module.
These three parameters can be selected as needed to display the specification.
Let’s talk about module below. A module is an object that stores the meta information of the module, as follows:
1.module.id - the module ID.
2.module.dependencies—An array that stores the ID list of all modules that this module depends on.
3.module.exports--points to the same object as exports.
Three modes for writing modules
The first mode to define modules is the exports-based mode:
The code copy is as follows:
define(function(require, exports, module) {
var a = require('a'); //Introduce module a
var b = require('b'); //Introduce the b module
var data1 = 1; //Private data
var func1 = function() { //Private method
return a.run(data1);
}
exports.data2 = 2; //Public data
exports.func2 = function() { //Public method
return 'hello';
}
});
The above is a relatively "authentic" module definition model. In addition to appending public data and methods to exports, you can also directly return an object to represent the module, such as the following code has the same function as the above code:
Copy the code as follows: define(function(require) {
var a = require('a'); //Introduce module a
var b = require('b'); //Introduce the b module
var data1 = 1; //Private data
var func1 = function() { //Private method
return a.run(data1);
}
return {
data2: 2,
func2: function() {
return 'hello';
}
};
});
If the module definition has no other code and only returns one object, the following simplified writing method can be found:
Copy the code as follows: define({
data: 1,
func: function() {
return 'hello';
}
});
The third method is very suitable for modules that define pure JSON data.
Loading and reference of modules
Module addressing algorithm
As mentioned above, a module corresponds to a js file. When loading a module, it usually provides a string parameter to tell the module required by the loading function. Therefore, there is a set of parsing algorithms from the string identification to the file path where the actual module is located. . SeaJS supports the following identifiers:
Absolute address - gives the absolute path to the js file.
like:
The code copy is as follows: require("http://example/js/a");
It means loading http://example/js/a.js.
Relative Address - Use relative calls to find the module to find the relative address of the js file where the load function is located.
For example, load it in http://example/js/b.js
The code copy is as follows: require("./c");
Then load http://example/js/c.js.
Base address - If the loading string identifier is neither an absolute path nor starts with "./", it is addressed relative to "base" in the global configuration of SeaJS. This method is discussed later.
Note that when loading modules above, you do not need to pass the suffix name ".js" and SeaJS will automatically add ".js". But the following three cases will not be added:
When loading css, such as:
The code copy is as follows: require("./module1-style.css");
When the path contains "?", such as:
The code copy is as follows: require(<a href="http://example/js/a.json?cb=func">http://example/js/a.json?cb=func</a>);
When the path ends with "#", such as:
The code copy is as follows: require("http://example/js/a.json#");
According to different application scenarios, SeaJS provides three APIs for loading modules, namely seajs.use, require and require.async, which are introduced below.
seajs.use
seajs.use is mainly used to load the entry module. The entry module is equivalent to the main function of the C program, and is also the root of the entire module dependency tree. In the TinyApp example above, init is the entry module. The usage of seajs.use is as follows:
The code copy is as follows:
//Single mode
seajs.use('./a');
//Callback mode
seajs.use('./a', function(a) {
a.run();
});
//Multi-module mode
seajs.use(['./a', './b'], function(a, b) {
a.run();
b.run();
});
Generally, seajs.use is only used to load the entry module on the page. SeaJS will parse all dependency modules along the entry module and load them. If there is only one entry module, you can also omit seajs.use by adding the "data-main" attribute to the script tag that introduces sea.js. For example, the index.html of TinyApp above can also be changed to the following writing method:
The code copy is as follows:
<!DOCTYPE HTML>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>TinyApp</title>
</head>
<body>
<p></p>
<script src="./sea.js" data-main="./init"></script>
</body>
</html>
This way of writing will make html more concise.
require
require is the main module loading method of SeaJS. When other modules are needed in one module, it is generally loaded with require:
The code copy is as follows: var m = require('/path/to/module/file');
Here is a brief introduction to the automatic loading mechanism of SeaJS. As mentioned above, after using SeaJS, just include sea.js. So how do other js files load in? SeaJS will first download the entry module, then use regular expressions to match all the requirements in the code along the entry module, and then download the corresponding js file according to the file path identification in the require, and then iterate the downloaded js file. The whole process is similar to the traversal operation of a graph (because there may be a cross-cycle dependency, the entire dependency data structure is a graph rather than a tree).
Once you understand the above point, the following rules will be easy to understand:
The path identifier passed to require must be a string literal, not an expression. For example, the following method using require is wrong:
The code copy is as follows: require('module' + '1');
require('Module'.toLowerCase());
This will cause SeaJS to fail to perform correct regular matches to download the corresponding js file.
require.async
As mentioned above, SeaJS will record all required js files at once through static analysis when the html page is opened. If you want a certain js file to be downloaded only when it is used, you can use require.async:
Copy the code as follows: require.async('/path/to/module/file', function(m) {
//code of callback...
});
In this way, only when this module is used, the corresponding js file will be downloaded, which realizes the on-demand loading of JavaScript code.
Global configuration of SeaJS
SeaJS provides a seajs.config method that can set up a global configuration and receive a configuration object representing the global configuration. The specific usage method is as follows:
Copy the code as follows: seajs.config({
base: 'path/to/jslib/',
alias: {
'app': 'path/to/app/'
},
charset: 'utf-8',
timeout: 20000,
debug: false
});
Where base represents the base address path during base addressing. For example, base is set to http://example.com/js/3-party/ , then:
The code copy is as follows: var $ = require('jquery');
http://example.com/js/3-party/jquery.js will be loaded.
alias can set abbreviation for longer common paths.
charset represents the charset attribute of the script tag when downloading js.
timeout indicates the maximum time to download the file, in milliseconds.
debug indicates whether it works in debug mode.
How SeaJS works with existing JS libraries
To use an existing JS library such as jQuery with SeaJS, just encapsulate the existing library according to SeaJS's module definition rules. For example, the following is the encapsulation method for jQuery:
Copy the code as follows: define(function() {
//{{{{jQuery original code starts
/*!
* jQuery JavaScript Library v1.6.1
* http://jquery.com/
*
* Copyright 2011, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* Includes Sizzle.js
* http://sizzlejs.com/
* Copyright 2011, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
*
* Date: Thu May 12 15:04:36 2011 -0400
*/
//...
//}}} jQuery original code ends
return $.noConflict();
});
SeaJS project packaging and deployment
SeaJS originally integrated a packaged deployment tool sm. Later, in order to make KISS a little more KISS, the author dismantled the sm out of SeaJS and became a separate project. The core idea of spm is to merge and compress the code of all modules and then merge it into the entry module. Due to the characteristics of SeaJS itself, html can be easily switched between the development environment and the production environment without any changes. However, since spm has not been released for the official version, this article does not intend to introduce it in detail. Interested friends can refer to its github project homepage https://github.com/seajs/spm/.
In fact, since the JS merge and compression tools used for each project are different, spm may not be completely suitable for each project. After understanding the principles of SeaJS, you can write a merge and packaging script that matches the characteristics of your project.