Node.js的require()的工作原理

大多数人都知道Node.js中require()函数做什么的,但是有多少人知道它的工作原理呢?我们每天使用它加载库包和模块,但是它的内部行为原理很神秘。

  我们追寻Node模块系统的核心: module.js,这个文件包含一个令人惊讶的神奇功能,它负责加载 编译和缓存每个用过的文件,让我们揭开它的神秘面纱。

function Module(id, parent) {    this.id = id;    this.exports = {};    this.parent = parent; 
  // ... 

  在module.js中可以发现这个Module类型,扮演两个主要角色:首先,它提供一个所有Node.js模块从其文件被加载时构建一个实例的基础功能,甚至在文件运行时持久,这就是为什么我们能够将一些属性加入module.exports,并在需要时返回它们。

  module的第二个事情是处理Node模块的加载机制,标准的require函数其实是基于module.require的抽象,后者只是一个对Module._load的简单包装,加载方法处理每个文件的实际加载。看看它的代码大概如下:

Module._load = function(request, parent, isMain) { 
  // 1.在Module._cache中检查模块是否被缓存
  // 2.如果缓存中为空,创建一个新的模块实例。
  // 3. 保存到缓存
  // 4. 使用指定的名称调用module.load() 
  //    在读取了文件内容后将调用module.compile() 
  // 5.如果加载和分析文件时有错误
  //    从缓存中删除坏的模块
  // 6. 返回 module.exports 
}; 

  Module._load负责加载新的模块并且管理模块缓存,缓存每个模块能够降低文件的读取频率,从而提高性能,共享模块实例允许像单例模块那样跨应用保存状态。

  如果一个模块在缓存中不存在,Module._load将读取文件创建一个新的,读取文件内容成功后会调用module._compile

  如果你注意上面第六步,你会看到返回的是module.exports,这就是为什么当你定义公共接口时,可以使用exports和module.exports,因为它们确实是Model._load和require返回的。

  下面看看module._compile:

Module.prototype._compile = function(content, filename) { 
  // 1. 创建调用模块需要的require标准函数
  // 2.将其他帮助方法加入require. 
  // 3.包装JS代码到一个函数,这个函数提供我们的require
  //  模块, 比如变量本地化到模块的作用域
  // 4.返回这个函数
}; 

  这里有魔术发生,首先,一个特殊的标准require函数将被创建,这就是我们熟悉的require()函数,当函数自己包装了Module.require,它还包含一些很少人知道的帮助属性和方法,如:

  • require():加载一个外部模块
  • require.resolve(): 根据其绝对路径解决模块名称
  • require.main: 主要的模块
  • require.cache: 所有缓存模块
  • require.extensions: 基于文件的扩展名可用于编译的方法。

  一旦require准备就绪,整个源码将被包装进一个新的函数,这个函数有require module和exports和其他暴露变量作为参数,这创建了模块的一个新函数作用域,这样就不会污染Node.js环境的其余部分。

(function (exports, require, module, __filename, __dirname) { 
  // YOUR CODE INJECTED HERE! 你的代码在这里
}); 

  最后,这个包装了模块的函数将运行,整个Module._compile方法同步执行,这样原来对Module._load方法调用将会等待这个代码运行,然后才会完成,返回module.exports给用户。

 

原文地址:https://www.cnblogs.com/gwyy/p/8490342.html

时间: 2024-08-29 14:43:21

Node.js的require()的工作原理的相关文章

windows下搭建node.js及npm的工作环境

最近在研究数据可视化D3框架,决定在windows下搭建一个nodejs及npm的工作环境,在网上查了n篇文章,别管是编译源码安装也好,还是使用node.msi格式安装包也好,总是有问题.最终,功夫不负有心人,还是搭建完成了.作为新手,其实我也不知道这样搭建对不对,但是运行'npm install'反正不出错了. 下面就把我的一些搭建过程说一下: 下载node.js.在http://nodejs.org/download/下载最新版的node.exe文件,我下载时是v0.10.33.下载完成后,

[ 转]Node.js模块 require和 exports

什么是模块? node.js通过实现CommonJS的Modules/1.0标准引入了模块(module)概念,模块是Node.js的基本组成部分.一个node.js文件就是一个模块,也就是说文件和模块是一一对应的关系.这个文件可以是JavaScript代码,JSON或者编译过的C/C++扩展. Node.js的模块分为两类,一类为原生(核心)模块,一类为文件模块. 在文件模块中,又分为3类模块.这三类文件模块以后缀来区分,Node.js会根据后缀名来决定加载方法. .js.通过fs模块同步读取

解析Vue.js中的computed工作原理

我们通过实现一个简单版的和Vue中computed具有相同功能的函数来了解computed是如何工作的.写的十分的全面细致,具有一定的参考价值,对此有需要的朋友可以参考学习下.如有不足之处,欢迎批评指正. JS属性: JavaScript有一个特性是 Object.defineProperty ,它能做很多事,但我在这篇文章只专注于这个方法中的一个: var person = {}; Object.defineProperty (person, 'age', { get: function ()

使用Node.js进行Web开发(一)

本文介绍Express框架.MVC设计模式.ejs魔板引擎以及MongoDB数据库的操作. 首先要知道Node.js实现网站的工作原理是实现动态网页,也就是说由服务器动态生成HTML页面. MVC(Model-View-Controller,模型-试图-控制器)是一种软件的设计模式,即把一个复杂的软件工程分解为三个层面:模型.试图.控制器. 模型是对象及其数据结构的实现,通常包含数据库操作. 试图表示用户界面,在网站中通常就是HTML的组织结构. 控制器用于处理用户请求和数据流.复杂模型,将输出

Node.js入门:模块机制

CommonJS规范  早在Netscape诞生不久后,JavaScript就一直在探索本地编程的路,Rhino是其代表产物.无奈那时服务端JavaScript走的路均是参考众多服务器端语言来实现的,在这样的背景之下,一没有特色,二没有实用价值.但是随着JavaScript在前端的应用越来越广泛,以及服务端JavaScript的推动,JavaScript现有的规范十分薄弱,不利于JavaScript大规模的应用.那些以JavaScript为宿主语言的环境中,只有本身的基础原生对象和类型,更多的对

【读书笔记】Node.js开发指南

一:Node.js是什么? 正如当年为了统一 JavaScript 语言标准,人们制定了 ECMAScript 规范一样,如今为了统一 JavaScript 在浏览器之外的实现, CommonJS 诞生了. CommonJS 试图定义一套普通应用程序使用的API,从而填补 JavaScript 标准库过于简单的不足. CommonJS 的终极目标是制定一个像 C++ 标准库一样的规范,使得基于 CommonJS API 的应用程序可以在不同的环下运行,就像用 C++ 编写的应用程序可以使用不同的

(译)Node.js的模块-exports和module.exports

原文标题:Node.js Module – exports vs module.exports原文链接:http://www.hacksparrow.com/node-js-exports-vs-module-exports.html exports 和 module.exports 有什么区别? 你一定很熟悉 Node.js 模块中的用来在你的模块中创建函数的 exports 对象,就像下面这样. 创建一个叫做rocker.js的文件: exports.name = function() {

node.js(API解读) - process (http://snoopyxdy.blog.163.com/blog/static/60117440201192841649337/)

node.js(API解读) - process 2011-10-28 17:05:34|  分类: node |  标签:nodejs  nodejsprocess  node.jsprocess  nodjsapi  node.jsapi   |举报 |字号 订阅 下载LOFTER 我的照片书  | nodejs的process是一个全局对象,他提供了一些方法和属性,node.js官方的API说的很简单,并没有把一些详细的应用方法和作用写出来,下面结合我自己的学习,做一下小结吧.1.Even

(译+注解)node.js的C++扩展入门

声明:本文主要翻译自node.js addons官方文档.部分解释为作者自己添加. 编程环境: 1. 操作系统 Mac OS X 10.9.51. node.js v4.4.22. npm v3.9.2 本文将介绍node.js中编写C++扩展的入门知识. 1. 基本知识介绍 在node.js中,除了用js写代码以外,还可以使用C++编写扩展,这有点类似DLL,动态链接进js代码中.使用上也相当方便,只需用require包含,这和一般的js模块并没有什么区别.C++扩展为js和C++代码的通信提