About Modularity

Let’s talk about js modularity.

Js didn’t have the concept of modularity at first, but without modularity it can be very difficult to manage when dealing with large front-end applications. So the community spawned a wild modular specification called CommonJS. This specification is still used in NodeJS today.

Later, ECMA also realized that modularity was necessary, and in ES6, modularity was officially added to the ES standard, which is known as ES6 module.

CommonJS for the first time

In CommonJS we only need to know two uses, require and module.exports.

/ / A document
var firstName = "Michael";
var lastName = "Jackson";
var year = 1958;

module.exports = {
  firstName,
  lastName,
  year
};

/ / B file
const Info = require('./A); console.log(Info); // {firstName: "Michael", lastName: "Jackson", year: 1958} const {year} = require('./A);
console.log(year); / / 1958
Copy the code

In terms of usage, knowing the above example, I think it’s almost ok.

We can also see that the above code actually loads the entire A module, and then imports it wrapped in an object. This type of loading is called “runtime loading.” (Load modules when the code is running)

ES6 module usage exploration

Like ES6 module, it has more patterns, such as only export this aspect, what separate export, default export, forward export. Here’s a look at some of the more common ways to play these days.

Separate export

/ / A document
// The first method is derived separately
export var firstName = "Michael";
export var lastName = "Jackson";
export var year = 1958;
Copy the code
// The second method is derived separately
var firstName = "Michael";
var lastName = "Jackson";
var year = 1958;

export { firstName, lastName, year };
Copy the code

The common features of these two ways of writing are: Export = = = = = = = = = = = = = = = = = = = = = = = = = The word followed by export looks like an object, but it is not an object.

export { nn: firstName, lastName, year }; ❌ SyntaxError: SyntaxError

export { firstName: 'zhang', lastName, year }; //❌ : SyntaxError: SyntaxError
Copy the code

So, the curly braces are just curly braces, and they define which variables to print out.

And something like this is exported separately, because we’re not really exported objects; There is nothing to print directly when other modules import files statically.

import A from "./A";

console.log(A); // undefined
Copy the code

If we want to use it, we can only use the {} form to decide which modules to take, but as mentioned above, the curly brace method here looks like deconstruction, but it’s not really deconstruction, it just looks like it.

//
import { year } from "./A";
console.log(year); / / 1958

// Rename it
import { year as thatYear } from ".A"; // Rename variables
console.log(year); / / 1958

// Import all modules and store them in an object
import * as Info from "./A";
console.log(Info); // Module {firstName: "Michael", lastName: "Jackson", year: 1958}
Copy the code

The default is derived

In addition to exporting alone, there is another method that is used a lot, and that is exporting by default.

The so-called default export is export default, which is essentially exporting a variable named default, followed by the name and value of the variable.

/ / A document
var firstName = "Michael";
var lastName = "Jackson";
var year = 1958;

export default { nn: firstName, lastName, year }; // This is not an error, because it is really an object
Copy the code

At this point, the exported variable is assigned to another variable when it is used outside, rather than being destructed directly.

import JacksonInfo from "./A";
console.log(JacksonInfo); // {firstName: "Michael", lastName: "Jackson", year: 1958}
Copy the code

A quick summary:

  • Export separately. Curly braces export selectively, curly braces import selectively
  • Export by default. Export a variable, import a variable

Cool forward export

There is also a forwarding export, for example:

export { year, firstName } from "./A";

// The export module is not imported into the current module, so it is almost the same as the following:
import { year, firstName } from "./A";
export { year, firstName };
Copy the code

Good good don’t show, if you want to know more operation, you can go to ruan Yifeng ES6 document to see. portal

CommonJS and ES6 modules

But let’s look at the difference, this is more important, the difference in the use of methods, just some tricks.

For now, there are two main differences between the two:

  1. ES6 modules are statically imported and loaded at compile time; CommonJS is dynamically imported, loaded at run time;

  2. When the ES6 module does not use the default export, even if the original data type is exported, the reference is still exported. In contrast, CommonJS exports a raw data type just by exporting a value;

The first difference is easy to understand. We know that static loading in ES6 is a bit powerful. It can determine the import/export relationship of modules at compile time, before the code runs, making it easy to do static optimizations (such as importing a module multiple times and merging it into one import). In addition, the statically loaded nature of the import ABC fom “XXX” statement also determines that the import ABC fom “XXX” statement cannot be placed in a code block such as a conditional statement, but should be placed at the top of the code, because the code block needs to be run to know the result, and since the import ABC fom “XXX” takes precedence over the code run, So even if it is placed at the bottom of the code is no problem, it will also have the effect of command promotion. The following operation does not report an error:

console.log(Info);

import Info from "./A";
Copy the code

What about the second difference? To put it simply, when ES6 modules don’t use default exports, they export references to everything (both primitive and reference types), and when each module imports this value, it actually goes to the same place (the source module) for the value. Or put it this way: when the ES6 module does not export by default, it exports live Pointers.

When CommonJS exports a base type, it simply exports a value, with no connection to the source module.

/ / CommonJS
var num = 0

module.exports = { num }; Num: 0} {num: 0
Copy the code
// In ES6 module
var num = 0

export { num }; // Export a pointer to the current num variable
Copy the code
The ES6 module is exported by default
var num = 0

export default num ; // The exported object becomes a value instead of a live pointer
Copy the code