What problems does modularity solve
To see what modularity solves, you need to understand how front-end engineers introduced JavaScript code before modularity, as follows
<script scr="./js1.js"></script>
<script scr="./js2.js"></script>
<script scr="./js3.js"></script>
Copy the code
Due to the nature of the JavaScript language, there are several problems with introducing JavaScript files in this way.
- Pollution global variable
- Dependencies are not obvious
- The order in which files are imported is limited
As for why these problems exist, there is no more to say here, common sense problems.
As a result of these problems, we need to make JavaScript modular, so that each JavaScript file has a separate scope, not to let the variables between multiple files conflict, between modules also retain mutual import and export, to ensure that modules can communicate with each other, to ensure the dependency between each other.
In the JavaScript language, the ES6 specification has not defined modular import and export at the language level before, and only has its own solution in different JS running environment. There are several commonly used schemes **
- CommonJS running on the server
- AMD for WEB development
- ESModule specification
commonJS
As mentioned above, before the ES6 specification, you want to modularize JavaScript code in different JS environments. CommonJS is a set of modularized specifications defined in node.js environments. The basic syntax is as follows
const module1 = require('./module1') // Import the module1 file
const name = "Lius"
module.exports = name Export the current file
Copy the code
Let’s look at one more piece of code
// index.js
require("./moduleA");
var m = require("./moduleB");
console.log(m);
// moduleA.js
var m = require("./moduleB");
setTimeout(() = > console.log(m), 1000);
// moduleB.js
var m = new Date().getTime();
module.exports = m
Copy the code
This code prints the value of the m variable exported from the moduleb. js file in both modulea. js and index.js files, and prints it late in the moduleA.js file. Executing node index.js shows that the result is the same whether the file is index.js or modulea.js. Thus it can be seen
- Modules have the same variable name in real time, but there is no conflict
- Handle imports and exports between modules via **require ** and **module.exports **
- Loading the unified module moduleB in different modules results in the same, ensuring the module singleton
Based on the above three points, we can draw a conclusion that it is a modular specification if it can meet the above three points.
Note that CommonJS only runs in node.js, where the require and module.exports syntax can be resolved.
AMD
The browser is also a JS runtime environment, and all front-end engineers should know that the browser runtime environment does not provide require and module.exports, as in the CommonJS specification. So the Web side has its own specification AMD ** AMD (Asynchronous Module Definition). ** AMD loads all modules asynchronously according to the name. Modify the above code
// index.js
require(['moduleA'.'moduleB'].function(moduleA, moduleB) {
console.log(moduleB);
});
// moduleA.js
define(function(require) {
var m = require('moduleB');
setTimeout(() = > console.log(m), 1000);
});
// moduleB.js
define(function(require) {
var m = new Date().getTime();
return m;
});
// index.html
<html>
<! -- the module must be loaded with AMD module libraries such as require.js.
<script src="/require.js"></script>
<! -- Just load the entry module -->
<script src="/index.js"></script>
</html>
Copy the code
If we want to use the AMD specification, we also need to add an AMD-compliant loader script to the page. There are many libraries that comply with the AMD specification implementation, the most famous is require.js.
Define () defines the module, load the module with require(), and the module ID defaults to the filename. Open index.html in Chrome on the console and we can see the same output. In the Network bar, you can also see asynchronous loading between modules.
esModules
These two specifications have the following two characteristics
- They are not modularized at the language level, they are defined by the runtime environment itself
- Can only run in a separate environment, cannot share modules (cannot use CommonJS modules in browsers, cannot use AMD modules in Node)
After the ES6 specification came out, modularity was defined at the language level, not restricted by the environment. In ES6, you can import and export modules using the keywords import and export. ESModule is implemented by JS interpreter, CommonJS and AMD are implemented by runtime environment.
Continue to modify the above code
// index.js
import './moduleA';
import m from './moduleB';
console.log(m);
// moduleA.js
import m from './moduleB';
console.log(m)
// moduleB.js
const m = new Date().getTime();
export default m
Copy the code
Steal a diagram to show the relationship between the various module specification syntax and their environment:Every JS runtime environment has a JS parser, which uses the ECMAScript specification to interpret THE JS syntax. As shown in the figure above, there are different global objects in different environments. This is similar to modularity in that there are different modularity specifications in different JS environments, butESModuleIs a modular specification defined at the JS Core level that can be supported in any runtime environment.
On the difference between packaging and compilation:
- The packaging tool deals mainly with modularity differences between different versions of JS
- Compilation tools mainly deal with semantics between JS versions