I wrote this column because I recently wanted to reorganize my front-end knowledge systematically. I will try to write some business related tips and front-end knowledge of the key content, core ideas.
preface
Engineering is a big step forward for front-end developers, and we’ll start looking at areas like build, build optimization, and service development. The earliest representative of engineering is the birth of modularization. Today we are going to talk about front-end modularity.
The origin of modularity
We all know that front-end pages are made up of HTML, CSS, and JavaScript. As the functions of the page become more powerful, the page logic becomes more and more complex. JavaScript code inevitably becomes bloated. In the early days, in order to separate JS code, developers would divide JS into several different files and import them through the Scritpt tag.
// At the same time we need to mount the introduced utility functions to the page.
(function(window){
function tool(){
// ... do something
}
window.tool = tool; }) (window)
Copy the code
Looking at the code above, we can see that the earliest references to JS had two considerations:
- In order not to pollute global variables, the JS content itself needs to be wrapped.
- Since the tool needs to reference the page, pass the window into the closure and mount the JS internally.
It is not hard to see how js can be introduced in this way. One problem developers face is the uncontrollable dependencies between these JS tools. If there are 10 JS tools on a page, these tools will need to reference each other. This requires careful consideration when HTML references script tags.
To solve this problem, front-end developers have embarked on a modular exploration path.
AMD
【AMD】 (Asynchromous Module Definition) specification can be said to be the first widely used front-end modular solution. It is implemented by require.js. More information about require.js can be found on the requirejs.org/ website
Here’s how it’s used:
// Configure the tools for the entire project in the entry file
require.config({
baseUrl: "js/lib".paths: {
"jquery": "jquery.min".// The actual path is js/lib/jquery.min.js
"underscore": "underscore.min",}});// When defining tools, you need to use the supplied define function
define('myModule'['jquery'.'lodash'].function($, _){
return {
// Jq can be referenced with $, regardless of the order in which the dependencies are referenced.
getInputValue:function(){
var input = $('#input');
returninput.val(); }}})Copy the code
Looking at the code above, we can see what AMD is thinking:
- There is an overall configuration of the project, mainly to verify the alias and path of the tool.
- When defining a new tool, we need to use the define function provided by require.js to pass in the alias of the tool to be defined. Dependent tools, and the content of the tools themselves.
- This allows you to use the dependency tool directly within the tool.
Because AMD’s loading is an asynchronous operation, it does not block synchronous code. The tool only triggers its own callback when the dependent content is loaded. This way we don’t have to worry about the order of references between dependencies.
commonJS
CommonJS is the default module mode for nodeJs. It’s a contemporary product from AMD in terms of time, but commonJS is more about nodeJS and doesn’t change front-end development very quickly.
In nodeJs’ mind, each file is a module. Modules are referenced between modules via require, and modules themselves are exported using module.exports. NodeJs modules are all loaded together at startup rather than during execution, which is a bit different from a browser.
Usage:
// a.js
var printSolgan = function(){
console.log('hello world');
}
module.exports = printSolgan;
//b.js
var printSolgan = require('./a.js');
printSolgan(); // hello world
Copy the code
You can see that as a built-in nodeJs module scheme, commonJS is very convenient to use. Nodejs naturally treats each file as a module, eliminating extra processing such as closures. Unlike AMD, commonJS references are synchronous operations, executing the module on the first reference, and nodeJS removes the file from the cache on the second reference.
CMD
The [CMD] (Common Module Definition) specification is an optimization for AMD. After the commonJs specification came out, front-end developers had to remember two different reference methods (browser, and nodeJs environment). It would be a great help to front-end developers if they could make the same script compatible with both environments. The front end team of Taobao launched Sea.js to solve this problem (later require.js also integrated it).
More about the sea. The content of the js can refer to: seajs. Making. IO/seajs/docs
Usage:
define(function(require.exports.module){
var$=require('jqurey');
var getInputValue = function(){
var input = $('#input');
return input.val();
}
module.exports = getInputValue;
})
Copy the code
As can be seen from the above code, CMD implements the native content of NodeJS, such as require, module, etc. Of course, the module definition still needs to call define function, and the part inside the function is very similar to the NodeJS environment. The biggest difference from AMD is that AMD needs to load all the dependencies used before the function is executed. CMD is referenced dynamically through require. That is, CMD can avoid references to code that has not been executed.
// AMD
define(["a"."b"].function(a, b) {
// As long as the dependency is defined, it will be executed
a.doSomething();
if (false) {
// Even if b is not used, b is already executed in front
b.doSomething()
}
});
/** CMD **/
define(function(require.exports.module) {
// Execute when used
var a = require('./a');
a.doSomething();
if (false) {
// Will not be executed
var b = require('./b'); b.doSomething(); }});Copy the code
ES6 Modules
ES module mode is the official modular scheme launched after ES 2015 version, and it is also the most widely used mode now. ES modules are often written in Babel or typescript compilations in nodeJs environments.
Usage:
// a.js
var printSolgan = function(){
console.log('hello world');
}
export default printSolgan;
//b.js
import printSolgan from './a.js';
printSolgan();
// hello world
Copy the code
ES Module uses import Export to import/export modules. ES6 modules are not objects, and the import command is statically analyzed by the JavaScript engine. The module code is introduced at compile time, rather than loaded at run time, so conditional loading cannot be implemented. Because of this, static analysis is possible.
Features of ES6 module:
- Strict mode: ES6 modules automatically adopt strict mode
- Import read-only Property: The import property is read-only and cannot be assigned, similar to const property
- Export /import promotion: import/export must be at the top of the module, not in scope; Secondly, import/export within the module will be promoted to the top of the module, which is completed during compilation
Use in the browser
Note that when using es module in the browser, you need to add ‘type=”module” to the script tag.
<script type="module">
var foo = 100;
console.log(foo);/ / 100
</script>
Copy the code
UMD module type compatible
With ES6 Moudule, the front end modularity has stabilized. The ES module is preferred for most new projects, including some early development libraries that will be updated with new versions of the ES module that can be used. The problem developers now face is how to deal with so many different module solutions in the past. When writing a library, the developer has no way of knowing which module scheme the user’s project is using. For this we need an approach that is compatible with all modules. That’s UMD.
Universal Module Definition (UMD) is a common javascript Module Definition specification that enables your Module to play a role in all javascript runtime environments. So how did he do it?
implementation
We need to make it clear that UMD is a specification for defining functions, not an operation for referencing. So UMD is not a new module solution, it is just a compatibility solution. With UMD, the function looks like this:
// root: global variable
// factory: function content
(function(root, factory) {
// commonJS can be used if the current environment has module and module.exports
if (typeof module= = ='object' && typeof module.exports === 'object') {
module.exports = factory();
// If the current environment has define and define. Amd, you can use commonJS
} else if (typeof define === 'function' && define.amd) {
define(factory())
// commonJS can be used if the current environment has define and define.cmd
} else if (typeof define === 'function' && define.cmd) {
define(function(require.exports.module) {
module.exports = factory()
})
} else {
// No module environment, mount directly on global objects
root.umdModule = factory();
}
// This will depend on the running environment, the browser is window, nodejs is global} (this.function() {
// Specify the function content
return {
name: 'I am a UMD module'}}))Copy the code
From the example, we can see that the idea of UMD is to determine what module is used in the current operating environment according to the special of various modules, and then use the corresponding module loading function. At present, most of the mainstream tool libraries use umD files, usually ending in umd.js.
If you are interested, you can check out the jquery library. In fact, umD compatibility is also used. Jquery 3.6 CDN address: cdn.bootcdn.net/ajax/libs/j…
reference
www.cnblogs.com/chenwenhao/…
www.jianshu.com/p/9f5a0351a…