深入了解Node的模块机制,聊聊模块实现流程

本篇文章带大家了解一下commonjs规范和node的模块机制,介绍一下node实现commonjs规范的基本流程,希望对大家有所帮助!

深入了解Node的模块机制,聊聊模块实现流程

在CommonJs规范提出之前,Javascript是没有模块系统的,这意味着我们很难开发大型的应用,因为代码的组织会比较困难。

什么是CommonJs规范

首先CommonJS不是Node独有的东西,CommonJs是一种模块规范,定义了如何引用和导出模块,Nodejs只是实现了这个规范,CommonJS模块规范主要分为模块引用、模块定义和模块标识三个部分。

模块引用

模块引用就是我们可以通过require引入其它的模块。

const { add } = require('./add');const result = add(1 ,2);

登录后复制

模块定义

一个文件就是一个模块,模块里会提供两个变量,分别为module和exports。module为当前模块本身,exports为要导出的内容,同时exports为module的一个属性,即exports为module.exports。其他模块通过require导入的内容即为module.exports的内容。

// add.jsexports.add = (a, b) => {    return a + b;}

登录后复制登录后复制

模块标识

模块标识即为require里面的内容,比如require(‘./add’),则模块标识为./add。

通过CommonJS构建的这套模块导入导出机制使得用户完全无需考虑变量污染,可以方便的构建大型应用。

Node的模块实现

Node实现了CommonJs规范,并且增加了一些自己需要的特性。Node为了实现CommonJs规范主要做了以下三件事情:

路径分析

文件定位

编译执行

路径分析

当执行require()的时候,require接收的参数即为模块标识符,node通过模块标识符来进行路径分析。路径分析的目的就是为了通过模块标识符找到这个模块所在的路径。首先,node的模块分为两类,分别是核心模块和文件模块。核心模块是node自带的模块,文件模块是用户编写的模块。同时文件模块又分为相对路径形式的文件模块、绝对路径形式的文件模块和非路径形式的文件模块(比如express)。

未命名文件.png

当node找到一个文件模块之后,会将这个模块编译执行并且缓存起来,大致原理是将这个模块的完整路径作为key,编译后的内容作为值,后续再第二次引入这个模块的时候就不需要再进行路径分析文件定位编译执行这几个步骤了,可以直接从缓存中读取编译好的内容。

// 缓存的模块示意:const cachedModule = {    '/Usr/file/src/add.js': 'add.js编译后的内容',    'http': 'Node自带的http模块编译后的内容',    'express': '非路径形式自定义文件模块express编译后的内容'    // ...}

登录后复制

当要查找require导入的模块时,查找模块的顺序是先查看缓存里是否已经有该模块,如果缓存里面没有再查看核心模块,然后再查找文件模块。其中路径形式的文件模块比较好查找,根据相对或绝对路径就可以得到完整的文件路径。非路径形式的自定义文件模块查找起来会相对麻烦一些,Node会从node_modules这个文件夹里去查找是否有这个文件。

node_modules这个目录在哪里呢,比如说我们当前执行的文件为/Usr/file/index.js;

/** * /Usr/file/index.js;*/const { add } = require('add');const result = add(1, 2);

登录后复制

这个模块里我们有引入了一个add模块,这个add不是一个核心模块也不是一个路径形式的文件模块,那么这时候如何找到这个add模块呢。

module有一个paths的属性,查找add模块的路径在paths这个属性里,我们可以把这个属性打出来看一下:

/** * /Usr/file/index.js;*/console.log(module.paths);

登录后复制

我们在file目录下执行node index.js可以打印出paths的值。paths里的值是一个数组,如下:

['/Usr/file/node_modules','/Usr/node_modules','/node_modules',]

登录后复制

即Node会依次从上面的目录里寻在是否包含add这个模块,原理和原型链类似。先从当前执行的文件的同级目录的node_modules文件夹里开始找,如果没找到或者没有node_modules这个目录,则继续往上级查找。

文件定位

路径分析和文件定位是搭配一起使用的,文件标识符可以是不带后缀的,也可能通过路径分析找到的是一个目录或者一个包,这个时候要定位到具体的文件需要一些额外的处理。

文件扩展名分析

const { add } = require('./add');

登录后复制

比如上面这段代码,文件标识符是不带扩展名的,这个时候node会依次查找是否存在.js、.json、.node文件。

目录和包分析

同样是上面这段代码,通过./add查找到的可能不是一个文件,可能是一个目录或者包(通过判断add文件夹下是否有package.json文件来判断是目录还是包)。这个时候文件定位的步骤是这样的:

查看是否有package.json文件有读取package.json里的main字段的值作为文件没有寻找目录下的index作为文件(依次查找index.js、index.json、index.node)

如果package.json里没有main字段,那么也会将index作为文件,然后进行扩展名分析找到对应后缀的文件。

模块编译

我们开发中主要遇到的模块为json模块和js模块。

json模块编译

当我们require一个json模块的时候,实际上Node会帮我们使用fs.readFilcSync去读取对应的json文件,得到json字符串,然后调用JSON.parse解析得到json对象,再赋值给module.exports,然后给到require。

js模块编译

当我们require一个js模块的时候,比如

// index.jsconst { add } = require('./add');

登录后复制

// add.jsexports.add = (a, b) => {    return a + b;}

登录后复制登录后复制

这个时候发生了什么呢,为什么我们可以直接在模块里使用module、exports、require这些变量。这是因为Node在编译js模块的时候对模块的内容进行了首尾的包装。

比如add.js这个模块,实际编译的时候是会被包装成类似这样的结构:

(function(require, exports, module) {  exports.add = (a, b) => {    return a + b;  }  return module.exports;})(require, module.exports, module)

登录后复制

即我们编写的js文件是会被包装成一个函数,我们编写的只是这个函数里的内容,Node后续的包装的过程对我们隐藏了。这个函数支持传入一些参数,其中就包括require、exports和module。

当编译完js文件后,就会执行这个文件,node会将对应的参数传给这个函数然后执行,并且返回module.exports值给到require函数。

以上就是Node实现CommonJs规范的基本流程。

更多node相关知识,请访问:nodejs 教程!

以上就是深入了解Node的模块机制,聊聊模块实现流程的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2701085.html

(0)
上一篇 2025年3月7日 19:12:10
下一篇 2025年2月28日 07:17:58

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 浅析node中path路径模块的一些API

    本篇文章带大家了解一下node的path路径模块,介绍path内置模块的一些api,也准备了一个案例,用于练手,希望对大家有所帮助! 2. 使用 fs 模块,读取需要被处理的 HTML 文件 3. 自定义 resolveCSS 方法,来写入…

    2025年3月7日
    200
  • 详解node中如何安装多版本并进行切换

    本篇文章给大家深入了解一下多版本node的安装方法,并详细介绍一下node版本切换方法,希望对大家有所帮助! 安装多版本node的原因: 在项目开发过程中,不同项目使用的node版本不同,有时会因为node版本过高或太低,导致报错;如何在同…

    2025年3月7日 编程技术
    200
  • 【吐血总结】10个值得使用的热门Nodejs框架

    node.js 是最受欢迎的 javascript 运行时,下面本篇文章给大家总结分享10个值得使用的热门node框架,希望对大家有所帮助! 1. Next.js Next.js 是一个用于生产环境的 React 应用框架,使用它可以快速上…

    2025年3月7日 编程技术
    200
  • 什么是消息队列?node中如何使用消息队列?

    什么是消息队列?下面本篇文章带大家了解一下消息队列的基本概念,介绍一下node中如何使用消息队列,希望对大家有所帮助! 1.消息队列 什么是消息队列 消息队列就是消息的传输过程中保存消息的容器,本质是一个队列(先进先出) 消息指的是需要传输…

    2025年3月7日 编程技术
    200
  • 手把手带你使用node开发一个命令行压缩工具

    本篇文章给大家分享一个node实战,手把手带你使用node开发一个命令行压缩工具,希望对大家有所帮助! hello,最近写了一个压缩文件的命令行工具,今天分享给大家。 起因 由于前公司一些不可抗的情况,最近换了工作,吃饭的家伙也从Mac转成…

    2025年3月7日
    200
  • 聊聊Node.js path模块中的常用工具函数

    本篇文章带大家聊聊node中的path模块,介绍一下path的常见使用场景、执行机制,以及常用工具函数,希望对大家有所帮助! 在开发过程中,会经常用到 Node.js  ,它利用 V8 提供的能力,拓展了 JS 的能力。而在 Node.js…

    2025年3月7日 编程技术
    200
  • 聊聊node+express怎么操作cookie

    node+express怎么操作cookie?下面本篇文章就来给大家介绍一下用nodejs操作cookie的方法,希望对大家有所帮助! Cookie:有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进…

    2025年3月7日 编程技术
    200
  • 聊聊node+multiparty怎么实现文件上传

    利用node怎么实现文件上传?下面本篇文章就来给大家介绍一下node结合multiparty实现文件上传的方法,希望对大家有所帮助! 文件上传是每个项目中大概必不可少的操作,今天我们用node实现一个文件上传模块。 1.模块 npm i m…

    2025年3月7日
    200
  • 一文详解Nodejs中怎么读写文件

    node中怎么操作文件?下面本篇文章带大家聊聊怎么使用nodejs读写文件,希望对大家有所帮助! 操作文件是服务端一个基础的功能,也是做后端开发的必备能力之一。 操作文件主要包括读和写。而这些功能 Nodejs 都已经提供了对应的方法。只要…

    2025年3月7日
    200
  • 推荐11个受欢迎的Node.js 框架,快放入收藏夹吧!

    Node.JS是最流行的开源JavaScript运行时框架之一,并具有在浏览器之外建立代码的跨平台能力。知名开发者Alex Ivanovs自2005年就开始从事Web开发工作,近日,他根据前端构架调查、开发者调查报告以及个人项目经验,总结出…

    2025年3月7日 编程技术
    200

发表回复

登录后才能评论