1. The front

I used to use require in NodeJS all the time, but now all the front ends need to use modules. I happened to see this in learning WebPack, so I’ll take a look at it

  • commonjs
  • amdjs

2. commonjs

First of all, make it clear that this is an internal module so you declare that all of your content is in this module, which is private variables

  • module.idThe module’s identifier, usually the module’s file name with an absolute path.
  • module.filenameThe file name of the module, with an absolute path.
  • module.loadedReturns a Boolean value indicating whether the module has finished loading.
  • module.parentReturns an object representing the module that called the module.
  • module.childrenReturns an array representing other modules used by this module.
  • module.exportsRepresents the output value of the module.

These are the only properties that are most useful to me: Module.exports.

Other attributes I haven’t found usage scenarios in my work yet.

You can add variables to model.exports as shown here

require('./1.js')
Copy the code

This is called model. Exports

So I wrote a simple example

index.js

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

other.js

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

console.log(other.hello());

console.log(module);
Copy the code

You can see the values in the properties above.

2.1 the cache

Theoretically, as long as it’s called, it’s cached.

console.log(require.cache)
Copy the code

You can see the cache and you want to clear it

delete require.cache[name]
Copy the code

2.2 loading

  1. If the argument string begins with a slash, it means that a module file is loaded in an absolute path. For example, require(‘/home/ Marco /foo.js’) will load /home/marco/foo.js.

  2. If the argument string begins with a “./ “, it means that a module file is loaded in a relative path (compared to where the script is currently executing). For example, require(‘./circle’) will load circ.js in the same directory as the current script.

  3. If the parameter string does not start with a “./ “or”/”, it indicates that either a core module provided by default (in Node’s system installation directory) or an installed module (global or local) in each node_modules directory is being loaded.

Script, for example, / home/user/projects/foo js performed the require (‘ bar. Js) command, the Node will search the following files 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

This is designed so that different modules can localize their dependencies.

  1. If the argument string does not start with a “./ “or”/” and is a path, such as require(‘example-module/path/to/file’), the location of example-module will be found first, and then the subsequent path will be found using it as an argument.

  2. If the specified module file is not found, Node will try to add.js,.json, and.node to the file name before searching. .js files are parsed as text JavaScript script files,.json files are parsed as json text files, and.node files are parsed as compiled binary files.

  3. To get the exact filename of the require command to load, use the require.resolve() method.

The above is excerpted from ruan yifeng’s blog, know these may not have what use, you do not write disorderly actually use not to.

2.3 scope

I did a simple experiment that proved one thing: The CommonJS scope was completely isolated, and neither internal nor external changes affected the output

other.js

let number = 1;

setTimeout(() => { number = 2 }, 3000);

setInterval(() => {
 console.log(number);
}, 1000)

exports.number = number;
Copy the code

index.js

var other = require('./other.js');

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

Changing either the internal or external values does not affect the output.

2.4 global

One question is how do the two modules communicate with each other?

In general, the two modules should remain independent and should not be linked, but there are exceptions

So you can use global

global.xxxx
Copy the code

3. AMD

AMD is an Asynchronous Module Definition. It is a specification for modular development on the browser side

This is one of the rules used by some early JavaScript frameworks

Create a module called “alpha” using require, exports, and a module called “beta” :

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

call

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

That’s the simple thing to call, but I didn’t test anything else because I didn’t want to use the old framework again, just to make a comparison.

AMD && COMMONJS comparison

I think commonJS is a better way to declare a variable.

The code structure looks a little more comfortable, but the main difference is not here.

Advantages: server-side module reuse, NPM module packages, there are nearly 200,000.

Disadvantages: The loading module is synchronous, and the following operations can be performed only after the loading is complete. That is, when the module is needed, loading the module now and using it now is slow, but also causes performance, availability, debugging, and cross-domain access problems. Node.js is mainly used for server programming. Loaded module files are generally stored in the local hard disk, which is relatively fast to load without considering the asynchronous loading mode. Therefore,CommonJS specification is suitable. However, this is not suitable in a browser environment where synchronization means blocking loading and browser resources are loaded asynchronously, hence the AMD CMD solution.

AMD

Advantages: Asynchronously loading modules in the browser environment; Load multiple modules in parallel;

Disadvantages: high development cost, difficult to read and write code, semantics of module definition is not smooth; Does not accord with the general modular thinking, is the realization of a compromise;

But now it doesn’t really matter which front-end you use, webPack actually supports it, it just depends on which one you use more easily.

I haven’t tried whether NodeJS supports AMD or not..

5. CMD

In fact and AMD similar, only the details of the difference, different framework implementation of the different implementation, did not look closely

SeaJS, RequireJS

7. UMD

UMD is called the Universal Module Definition. It also follows the trend towards a big front end, which allows the same code module to run at run time or compile time in projects using CommonJs, CMD or even AMD. In the future, the same JavaScript package running on the browser side, the server side, and even the APP side will only need to follow the same script.

This is the ability to bring commonJS & CMD AMD together, as seen in webpack configuration, supporting UMD means that these specifications are supported.

8. es6

The keyword export allows the contents of the ESM to be exposed to other modules

other.js

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

index.js

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

8.1 Promise features

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

Let’s do it another way

if(condition) {
    import("./a.js").then...
}
else {
    import("./b.js").then...
}
Copy the code

This means that all promise functions can be used with import.

Promise.all([
    import("./a.js"),
    import("./b.js"),
    import("./c.js")
]).then((a,b,c) => {})
Copy the code

Take full advantage of parallelism

8.2 Dynamic Import

Other specifications can also be dynamically imported, but I don’t know if they support regex.

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

This allows you to import something dynamically. If you need plug-ins, put them in a directory and import them dynamically is a good choice.

But there’s a problem with that in Webpack, it packs all the packages in the entire computer, because it doesn’t know what you’re passing in, like if you want to be fully dynamic, you’re reading the value from the database.

So narrow it down.

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

Originally tested the regular representation for a long time, then found himself stupid.

8.3 scope

A little bit more simple

a.js

export let c = 2;

setInterval(() => {
    console.log(c);
})
Copy the code

b.js

import c from './module/a';

c = 3;
Copy the code

The output will always be 2

But if I change it

let c = 2;

export { c };

setInterval(() => {
    console.log(c);
})
Copy the code

It’s always going to be 3

But here’s where I get confused

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

He keeps putting out 2

I did not get an answer for a long time, I can only think about the difference between deep copy and shallow copy.

This point is expected to be solved in the follow-up study.

On the whole

  • dynamicimport()Provide apis based on promises, you can use any Promise you have
  • import()Follow ES module rules: singletons, matching characters, CORS, etc

9. end

Javascript.ruanyifeng.com/nodejs/modu…

Github.com/amdjs/amdjs…

www.jianshu.com/p/386916c73…

Blog.csdn.net/ixygj197875…

Webpack.js.org/api/module-…