Original source: https://github.com/seajs/seajs/issues/547
With the rapid development of the Internet, front-end development is becoming more and more complex. In this paper, we will start from the problems encountered in the actual project, describe the problems that can be solved by modularity, and how to use sea.js to carry out the modular development of the front-end. annoying naming conflict
We set out from a simple habit. When I do a project, I often abstract some common, low-level functions, and separate them into functions such as
function each (arr) {
//implementation Code
}
function log (str) {
//implementation Code
}
And put these functions in a util.js. When you need to use it, you can introduce the file. All of this worked well and my colleagues were thankful that I had provided such a handy kit.
Until the team gets bigger, people start complaining.
Xiao Yang: I want to define a each method to traverse the object, but the util.js of the page header has already defined one, my only call eachobject, good helpless.
Xiao Gao: I have customized a log method, why Xiaoming wrote the code is a problem. Somebody help me.
complain more and more. After a heated discussion, the team decided to refer to the Java approach and introduce namespaces to solve the problem. So the code in Util.js became
var org = {};
Org. Coolsite = {};
Org. Coolsite.utils = {};
Org. CoolSite.Utils.each = function (arr) {
//implementation Code
};
Org. CoolSite.Utils.log = function (str) {
//implementation code
};
Don't think the above code is deliberately fabricated to write this article. The concept of namespaces in the front-end to carry forward, the first push Yahoo! YUI2 project. Here is a piece of real code, an Open-source project from Yahoo!.
if (org.cometd.Utils.isString (response)) {return
Org.cometd.JSON.fromJSON (response);
}
if (Org.cometd.Utils.isArray (response)) {return
response;
}
Through namespaces, it does make a great deal of conflict mitigation. But often see the above code, can not help but full of sympathy. In order to invoke a simple method, you need to remember such a long namespace, which increases the burden of memory while depriving you of many coding pleasures.
As the front end of the industry benchmarking, YUI team determined to resolve the problem. In the YUI3 project, a new namespace mechanism was introduced.
YUI (). Use (' node ', function (Y) {
//node module has been loaded
///below can invoke
var foo = y.one (' #foo ') through Y;
});
YUI3 through the sandbox mechanism, a good solution to the problem of too long namespace. However, new problems have also been brought.
YUI (). Use (' A ', ' B ', function (Y) {
y.foo ();
Whether the Foo method is provided by module A or B.
//If both modules A and B provide the Foo method, how to avoid conflicts.
});
Seemingly simple naming conflicts, the actual solution is not simple. How to deal with it more gracefully. Let's press the table for a moment and look at another FAQ first. cumbersome file-dependent
Continue the story above. Based on Util.js, I started developing a common component of the UI layer so that the team colleagues didn't have to reinvent the wheel.
One of the most popular components is Dialog.js, which is easy to use.
<script src= "Util.js" ></script>
<script src= "dialog.js" ></script>
<script>
org. CoolSite.Dialog.init ({/* Incoming configuration */});
</script>
But no matter how I write a document, and how solemnly I send an e-mail announcement, there will always be colleagues to ask why Dialog.js has a problem. Through the investigation, found that the cause of the error is often
<script src= "Dialog.js" ></script>
<script>
org. CoolSite.Dialog.init ({/* Incoming configuration */});
</script>
Util.js is not introduced before dialog.js, so dialog.js does not work properly. Also do not think that my above story is fictitious, in the company I have been to, still have a similar foot this newspaper wrong, especially in a variety of rapid production of marketing pages.
The above file dependency is still controllable. As projects become more complex, the reliance on many files is often maddening. Here are a few of the questions that I believe are happening every day in real life. Universal groups update the front-end base class library, but it is difficult to promote the whole station upgrade. The business group wanted to use a new generic component, but found that it could not be done simply by a few lines of code. An old product needs new functionality, and the final evaluation can only continue to be based on the old class library. Company integration Business, a certain two product lines to be merged. The result found a front-end code conflict. ......
Many of these problems are due to the lack of good management of file dependencies. In the front-end pages, most of the scripting dependencies are still guaranteed through human flesh. When the team compares hours, there is no problem. When the team is growing and the business becomes more complex, the dependency problem will become a big problem if it is not solved.
File dependency, currently in the vast majority of class library framework, such as foreign YUI3 framework, the domestic Kissy class library, is currently through the configuration of the way to solve.
Yui.add (' My-module ', function (Y) {
//...
}, ' 0.0.1 ', {
requires: [' node ', ' event ']
});
The above code, through requires, and other means to specify the dependencies of the current module. This can largely solve the dependency problem, but it's not elegant enough. When a lot of modules, rely on very complex, cumbersome configuration will bring a lot of hidden dangers.
Naming conflicts and file dependencies are two classic issues in the front-end development process. Down we see how to solve it through modular development. For ease of description, we use sea.js as a modular development framework. use Sea.js to solve
Sea.js is a mature open source project, the core goal is to provide a simple, extreme modular development experience for front-end development. There are no more introductions here, and interested visitors can visit seajs.org to view the official documents.
Using Sea.js, you need to adhere to the CMD (Common module definition) module definition specification when writing a file. A file is a module. The util.js in the previous example becomes
Define (function (require, exports) {
Exports.each = function (arr) {
//implementation Code
};
Exports.log = function (str) {
//implementation Code
};
};
The interface can be provided externally through exports. In this way, the Dialog.js code becomes
Define (function (require, exports) {
var util = require ('./util.js ');
Exports.init = function () {
//implementation Code
};
};
The key part is here. Through require ('./util.js ') We can get the interface that is exposed through exports in util.js. The require here can be thought of as a syntax keyword that sea.js adds to the JavaScript language, and require can be used to get the interfaces provided by other modules.
It's not really magic at all. As a front-end engineer, the CSS code is certainly not unfamiliar.
@import url ("Base.css");
#id {...}.
class {...}
Sea.js added require syntax keywords, as in CSS files in the same way, to our source code to give a dependency on the introduction function.
If you are a backend development engineer, not unfamiliar. Java, Python, C #, and so on languages, including include, import and other functions. The JavaScript language itself has similar functionality, but it is still in the draft phase and needs to wait until the ES6 standard is supported by the mainstream browser.
This makes it very easy to use dialog.js on the page.
<script src= "Sea.js" ></script>
<script>
seajs.use (' dialog ', function (dialog) {
Dialog.init (/* Incoming configuration/*);
});
</script>
First of all, in the page to introduce Sea.js file, which generally through the page Head global control, but also easy to update maintenance. When you want to use a component in a page, you just call it through the Seajs.use method.
Take a good look at the code above and I'm sure you've seen two great benefits of Sea.js:
Exposes the interface through exports. This means that no namespaces are required, and global variables are not required. This is a complete naming conflict solution.
Introduce dependency through require. This lets you rely on the built-in, developers only care about the current module dependencies, other things sea.js will be automatically processed. For module developers, this is a good separation of concerns that allows programmers to enjoy coding more. Summary
In addition to resolving naming conflicts and dependency management, there are many benefits to using Sea.js for modular development:
Version management of the module. With the configuration of alias and so on, it is easy to implement the version management of the module with the building tools.
Improve maintainability. Modularity allows for a single responsibility for each file and is very useful for code maintenance. Sea.js also provides NoCache, Debug and other Plug-ins, with online debugging and other functions, can be more obvious to enhance efficiency.
Front-End performance optimization. Sea.js loads modules asynchronously, which is good for page performance. Sea.js also provides combo, flush and other plug-ins, with the service side, can be a good performance of the page tuning.
Cross-environment shared modules. The CMD module definition specification is very similar to the Node.js module specification. Through the Sea.js node.js version, it is easy to implement the module's cross server and browser sharing.
Modular development is not new, but in the Web field, front-end development is a nascent position, has been in the relatively primitive slash-and-burn era. Until the last two or three years, with the Dojo, YUI3, node.js and other community promotion and popular, the front-end of the modular development concept has gradually been deeply rooted.
The modular construction of the front end can be divided into two categories. The other is the cathedral model represented by Dojo, YUI3, Kissy and other libraries in China. In the cathedral mode, all the components are granular, modular, the various components are layered, interlocking. Another kind is based on jQuery, Requirejs, domestic sea.js, OZJS and other class libraries as the basis of the market model. In the Bazaar mode, all components are independent of each other and have a single responsibility, and the components are combined loosely together to achieve development.
These two kinds of modular construction methods have the application scene. In the long run, small and beautiful are more tolerant and competitive, and can form a vibrant ecological circle.
In short, modularity can bring a lot of benefits to front-end development. If you have not yet tried, you may wish to start with the trial sea.js.
Finish
Special thanks for this article: http://chaoskeh.com/blog/why-seajs.html
Some of the content is referenced.