The principle and implementation of COMMONJS module of browser loading server-side JavaScript

Source: Internet
Author: User
Tags unpack

NPM's modules are written in JavaScript, but cannot be used by browsers because the COMMONJS format is not supported. To allow browsers to use these modules, you must convert the format.

This article introduces the principle of browser loading COMMONJS, and gives a very simple implementation.


First, the principle

The root cause of the browser incompatibility Commonjs is the lack of four variables for the node.js environment.

Module
Exports
Require
Global

The browser can load the Commonjs module as long as the four variables can be supplied.

The following is a simple example.


var module = {
Exports: {}
};

(function (module, exports) {
exports.multiply = function (n) {return n * 1000};
} (module, module.exports))

var f = module.exports.multiply;
F (5)//5000

The code above provides module and exports two external variables to an immediate execution function, which is placed inside the immediate execution function. The output value of the module is placed in the module.exports, so that the load of the module is realized.


Ii. the realization of browserify

If you know the principle, you can make the tools. Browserify is currently the most commonly used COMMONJS format conversion tool.

Take a look at an example of the Main.js module loading the Foo.js module.


Foo.js
Module.exports = function (x) {
Console.log (x);
};

Main.js
var foo = require ("./foo");
Foo ("Hi");

Using the following command, you can convert main.js to a browser-usable format.


$ browserify main.js > Compiled.js

What the hell did browserify do? Install a browser-unpack, you can see clearly.


$ NPM Install Browser-unpack-g

Then, unpack the compile.js that you generated earlier.


$ Browser-unpack < Compiled.js

[
{
"id": 1,
"Source": "Module.exports = function (x) {\ n console.log (x); \ n};",
"Deps": {}
},
{
"id": 2,
' Source ': ' var foo = require (\ './foo\ '); \nfoo (\ "hi\"); ",
"Deps": {"./foo": 1},
' Entry ': true
}
]

As you can see, browerify all the modules into an array, the ID attribute is the module number, the Source property is the module source code, the Deps attribute is the module dependence.

Because the foo.js is loaded inside the main.js, the Deps attribute is specified./foo corresponds to module 1th. When executed, the browser encounters the require ('./foo ') statement, automatically executes the Source property of module 1th and outputs the Module.exports property value after execution.


Third, Tiny Browser Require

Although the browserify is very powerful, but can not operate in the browser, sometimes very inconvenient.

I made a pure browser COMMONJS module Loader Tiny-browser-require According to Mocha's internal implementation. There is no command line at all, just put it in the browser and all the code is only 30 or more lines.


Its logic is very simple, is to read the module into the array, loading path is the ID of the module.


function require (p) {
var path = Require.resolve (p);
var mod = Require.modules[path];
if (!mod) throw new Error (' failed to require ' + P + ' ");
if (!mod.exports) {
Mod.exports = {};
Mod.call (Mod.exports, mod, mod.exports, require.relative (path));
}
return mod.exports;
}

Require.modules = {};

Require.resolve = function (path) {
var orig = path;
var reg = path + '. js ';
var index = path + '/index.js ';
return Require.modules[reg] && reg
|| Require.modules[index] && Index
|| Orig
};

Require.register = function (path, FN) {
Require.modules[path] = fn;
};

Require.relative = function (parent) {
return function (p) {
if ('. '!= p.charat (0)) return require (p);
var path = Parent.split ('/');
var segs = p.split ('/');
Path.pop ();

for (var i = 0; i < segs.length; i++) {
var seg = segs[i];
if ('.. ' = = seg) path.pop ();
else if ('. '!= seg) path.push (SEG);
}

return require (Path.join ('/'));
};
};

When used, first put the above code into the page. Then, you can call the module by placing it in the immediate execution function as follows.




Or the previous main.js loading foo.js as an example.


Require.register ("./foo.js", function (module, exports, require) {
Module.exports = function (x) {
Console.log (x);
};
});

var foo = require ("./foo.js");
Foo ("Hi");

Note that this library only simulates require, module, exports three variables, and if the module uses global or other Node-specific variables (such as process), it is provided by executing the function immediately.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.