About JavaScript modules

Lazy and ugly 2021-09-15 08:21:45

1. the front

It used to be nodejs Use in require , Now all front ends need to use modules , Just learning webpack I saw this piece in the picture , So learn by the way

  • commonjs
  • amdjs

2. commonjs

First, make it clear that this is an internal module , All your content is in this module , That is, private variables

  • module.id The ID of the module , Usually the module filename with absolute path .
  • module.filename The file name of the module , With an absolute path .
  • module.loaded Returns a Boolean value , Indicates whether the module has finished loading .
  • module.parent Return an object , Indicates the module calling the module .
  • module.children Returns an array , Indicates other modules to be used in this module .
  • module.exports Indicates the output value of the module .

These attributes are only... For me module.exports Most useful .

Other properties I haven't found usage scenarios in my work yet .

You can go to model.exports Add variables , Here's the code

 Copy code 

In fact, it's called model.exports

So I simply wrote a list


exports.hello = () => { return 'hello' };
 Copy code 


const other = require('./other.js');
 Copy code 

So you can see the value in the above attribute .

2.1 cache

In theory, just call , It will cache .

 Copy code 

You can see the cache , Want to get rid of

delete require.cache[name]
 Copy code 

2.2 load

  1. If the parameter string is “/” start , It means that a module file in absolute path is loaded . such as ,require('/home/marco/foo.js') Will load /home/marco/foo.js.

  2. If the parameter string is “./” start , It means that the load is a relative path ( Compared to the current location where the script is executed ) Module files for . such as ,require('./circle') Will load... From the same directory as the current script circle.js.

  3. If the parameter string does not use “./“ or ”/“ start , It means that a core module provided by default is loaded ( be located Node In the system installation directory ), Or one at all levels node_modules Installed module for directory ( Global or local installation ).

for instance , Script /home/user/projects/foo.js Yes require('bar.js') command ,Node The following files will be searched in turn .

  • /usr/local/lib/node/bar.js
  • /home/user/projects/node_modules/bar.js
  • /home/user/node_modules/bar.js
  • /home/node_modules/bar.js
  • /node_modules/bar.js

The purpose of this design is , This enables different modules to localize the dependent modules .

  1. If the parameter string does not use “./“ or ”/“ start , And it's a path , such as require('example-module/path/to/file'), You will find example-module The location of , Then take it as a parameter , Find the next path .

  2. If the specified module file is not found ,Node Will try to add .js.json.node after , Search again ..js It will be in text format JavaScript Script file parsing ,.json The document will use JSON Format text file parsing ,.node The file will be parsed as a compiled binary .

  3. If you want require The exact filename the command loads , Use require.resolve() Method .

The above is an excerpt from Ruan Yifeng's blog , It may not be useful to know this , If you don't Scribble, you won't use it .

2.3 Scope

I did a simple experiment , Proved one thing ,commonjs The scope is completely isolated , Neither internal nor external changes can affect the output


let number = 1;
setTimeout(() => { number = 2 }, 3000);
setInterval(() => {
}, 1000)
exports.number = number;
 Copy code 


var other = require('./other.js');
setInterval(() => {
other.number = 3;
console.log('index', other.number);
}, 1000);
 Copy code 

Whether it's changing internal values , Or change the external value , Will not affect the output .

2.4 global

One problem is how to communicate between the two modules ?

In general, the two modules should remain independent , Should not be contacted by , But there are inevitable special circumstances

So you can use global

 Copy code 

3. AMD

AMD namely Asynchronous Module Definition, The Chinese name is “ Asynchronous module definition ” It means . It is a specification for modular development on the browser side

This belongs to some of the early JavaScript The rules used by the framework

Create a file called "alpha" Module , Used require,exports, And called "beta" Module :

 define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
exports.verb = function() {
return beta.verb();
return require("beta").verb();
 Copy code 


 define(["alpha"], function (alpha) {
return {
verb: function(){
return alpha.verb() + 2;
 Copy code 

This is the simple call , But I didn't test anything else , Because I don't want to use the previous framework , Just make a comparison .

4. AMD && COMMONJS contrast

First of all, it must be in usage , I think commonjs Better , It's equivalent to declaring a variable directly .

The code structure looks more comfortable , But the main difference is not here .

advantage : Server side module reuse ,NPM There are many modules in the package , There are nearly 20 m .

shortcoming : The load module is synchronous , The following operations can only be performed after loading , That is, when the module is to be used , Load and use now , Not only the loading speed is slow , It also leads to performance 、 Usability 、 Debugging and cross domain access .Node.js Mainly used for server programming , The loaded module files are generally stored on the local hard disk , It's faster to load , Don't worry about asynchronous loading , therefore ,CommonJS Norms are more applicable . However , This doesn't work in a browser environment , Synchronization means Blocking Load , Browser resources are loaded asynchronously , So there is AMD CMD Solution .


advantage : Load modules asynchronously in the browser environment ; Load multiple modules in parallel ;

shortcoming : High development cost , It is difficult to read and write the code , The semantics of module definition is not smooth ; Not in line with the general modular way of thinking , It's a compromise ;

But now it doesn't matter which one you use in the front end ,webpack In fact, they all support , It just depends on which one you use better .

I never tried. nodejs Do you support amd..

5. CMD

Actually sum AMD similar , It's just the difference in details , Different implementations of different frameworks , Don't look

SeaJS, RequireJS

7. UMD

UMD It's called the generic module definition specification (Universal Module Definition). It is also born with the trend of big front end , It can use the same code module at runtime or compile time CommonJs、CMD Even AMD In the project . The future is the same JavaScript The package runs on the browser side 、 The service area even APP All you need to do is follow the same script .

This is what can commonjs & cmd amd Get together , stay webpack You can also see , Support umd This means that these specifications support .

8. es6

keyword export Allows you to ESM Expose the contents of to other modules


export function aa() { console.log('aa') };
export function bb() { console.log('bb') };
 Copy code 


import { aa,bb } from './other.js'
 Copy code 

8.1 Promise characteristic

console.log('other.js is loaded dynamically');
async function cc() {
const other = await import('./other.js');
 Copy code 

Another way

if(condition) {
else {
 Copy code 

in other words promise Some functions import Both can be used. .

]).then((a,b,c) => {})
 Copy code 

Make full use of the ability of parallelism

8.2 Dynamic import

In fact, other specifications can also be imported dynamically , I just don't know if it supports regular .

async function test(p) {
return import(p)
 Copy code 

In this way, you can also import something dynamically , If you need some plug-ins , Put it in a directory , Dynamic import is a better choice .

But that's what's going on webpack There's going to be a problem , He will pack all the bags in the whole computer , Because he doesn't know what you'll bring in , For example, you want to be completely dynamic , You are reading the value from the database .

Therefore, it is suggested to narrow the scope .

import('./module/' + p);
 Copy code 

The regular representation was tested for half a day , Later, he issued that he was stupid .

8.3 Scope

A little bit more simple


export let c = 2;
setInterval(() => {
 Copy code 


import c from './module/a';
c = 3;
 Copy code 

The output will always be 2

But if you change it

let c = 2;
export { c };
setInterval(() => {
 Copy code 

It has always been 3

But there's something here that makes me wonder

import('./module/1.js').then(({ c }) => {
console.log(1, c);
c = 4;
import('./module/1.js').then(({ c }) => {
console.log(2, c);
 Copy code 

He keeps outputting 2

I checked for a long time and didn't get the answer , I can only roughly think of the difference between deep replication and shallow replication .

I hope this point can be answered in the follow-up study .

in general

  • dynamic import() Offer based on Promise Of API,Promise Yes, you can use
  • import() follow ES Module rules : Single case 、 Match symbol 、CORS etc.

9. end






Please bring the original link to reprint ,thank
Similar articles