从0开始Node.js - common.js规范

  • 开始之前,我们先在本地新建一个目录,然后

npm init -y
复制代码

生成一个包含package.json的目录结构,然后在目录下新建一个index.js作为入口js文件。新建一个module目录包含index.js及lib.js文件。之后的目录结构如下:

图片

  • 首先我们需要知道的是common.js规范的require是会引入js并 执行

下面是个简单的demo: module/index.js文件如下:

console.log('start');
require('./lib');
console.log('end');
复制代码

module/lib.js文件如下:

console.log('lib');
复制代码

然后在控制台执行 node module/index.js 结果如下:

图片

显然lib.js被引入并被执行了。

  • 其次是require函数是有返回值的

我们修改一下上面的代码如下

console.log('start');
const res = require('./lib');
console.log('libres', res);
console.log('end');
复制代码

再重新执行代码得到的输出结果为:

图片 可以看到reqiure('./lib.)得到的返回值是一个空对象。下面问题就来了,如果我希望得到非空的返回对象应该怎么做?

  • exports

node.js提供了输出关键字 exports 。我们如下修改下lib.js代码

console.log('lib');
exports.lib = 'lib'
复制代码

再次用node执行module目录下面的index.js。

图片 可以看到require的返回res是一个对象,包含了lib属性。当然我们还可以exports输出更多的其他类型的变量。

console.log('lib');
exports.lib = 'lib'
exports.obj = { a: 1, b: 2 };
exports.fun = (a) => console.log(a)
复制代码

控制台打印的结果如下:

图片

那么exports输出的是对象还是是对象的引用呢?即reqiure得到的对象修改会影响对象的本身吗?测试一下,如下修改module目录下的lib.js和index.js。index.js

console.log('start');
const res = require('./lib');
res.obj2 = { c: 1, d: 2 }
console.log('end');
复制代码

lib.js

console.log('lib');
exports.lib = 'lib'
exports.obj = { a: 1, b: 2 };
exports.fun = (a) => console.log(a)

setTimeout(() => { console.log('lib-exports', exports), 1000 })
复制代码

node module/index.js控制台输出如下:

图片 可以看到exports和require之间传递的是对象的引用。require对象的修改会影响exports对象。

  • module.exports

如果不想导出的始终是个对象。那么可以使用module.exports导出。lib.js

console.log('lib');
exports.lib = 'lib'
exports.obj = { a: 1, b: 2 };
exports.fun = (a) => console.log(a);
module.exports = () => { console.log('Node.js') };

setTimeout(() => { console.log('lib-exports', exports), 1000 })
复制代码

module/index.js

module/index.js
console.log('start');
const res = require('./lib');
console.log('libres', res);
res.obj2 = { c: 1, d: 2 }
console.log('end');
复制代码

打印结果

图片 可以看到res打印的结果不再是个object而是一个function。而同时index.js里面对res添加的属性obj2也不会添加到lib里面的exports对象上。

在浏览器端,webpack打包代码时是支持require命令的。那么看下webpack是如何实现require的。首先安装webpack和webpack-cli。

npm install webpack webpack-cli -D
复制代码

此时的package.json文件如下

{
  "name": "nodejs-start-from-0",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "dependencies": {},
  "devDependencies": {
    "webpack": "^5.37.1",
    "webpack-cli": "^4.7.0"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
复制代码

注意安装的webpack和webpack-cli版本,此版本应该是2021年5月份左右最新的版本 然后执行如下命令:

webpack ./index.js --devtool source-map  --mode development --target node
复制代码

输出结果在dist目录下的main.js文件中

/******/ (() => { // webpackBootstrap
/******/ 	var __webpack_modules__ = ({

/***/ "./lib.js":
/*!****************!*\
  !*** ./lib.js ***!
  \****************/
/***/ ((module, exports) => {

console.log('lib');
exports.lib = 'lib'
exports.obj = { a: 1, b: 2 };
exports.fun = (a) => console.log(a);
module.exports = () => { console.log('Node.js') };

setTimeout(() => { console.log('lib-exports', exports), 1000 })

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
(() => {
/*!******************!*\
  !*** ./index.js ***!
  \******************/
console.log('start');
const res = __webpack_require__(/*! ./lib */ "./lib.js");
console.log('libres', res);
res.obj2 = { c: 1, d: 2 }
console.log('end');
})();

/******/ })()
;
//# sourceMappingURL=main.js.map
复制代码

可以看到lib.js被放在了__webpack_modules__对象中,我们写在lib.js里面的代码被放在key为'lib.js'的属性里面。然后在index.js里面通过执行

const res = __webpack_require__(/*! ./lib */ "./lib.js");
复制代码

导入的lib.js。下面看看__webpack_require__的实现

/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
复制代码

从main.js里面拷出来 前面是判断缓存。后面__webpack_modules__[moduleId](module, module.exports, webpack_require);这一句其实就是执行的lib.js。同时传入了module和module.exports。在lib.js执行的部分可以看到:

module.exports = () => { console.log('Node.js') };
复制代码

exports最终被module.exports覆盖成了这个。所以输出的是module.exports的这个function。

以上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值