针对模块化,CommonJS规范,require原理和包查找机制等的整理

require与import的区别和使用(CommonJS规范和es6规范) 你要问前端开发难不难,我就得说计算机领域里常说的一句话,这句话就是『难的不会,会的不难』,对于不熟悉某领域技术的人来说,因为不了解所以产生神秘感,神秘感就会让人感觉很难,也就是『难的不会』;当学会这项技术之后,知道什么什么技术能做到什么做不到,只是做起来花多少时间的问题而已,没啥难的,所以就是『会的不难』。我特地针对初学者整理一套前端学习资料分享给大家,戳这里即可获取[外链图片转存中…(img-zYKJOi5B-1711721890493)] 阅读详情

模块化的好处: 为了更有效的组织代码,提高重用性,增大开发效率,我们会把项目拆分成不同模块,每个模块,职责单一,多人协同,高效运行,易于维护。

模块的发展历程

  • js 不像其他高级语言有模块系统,标准库较少和更缺乏包管理系统。
  • js 起初只有全局对象的形式,通过一个个小函数来实现不同的模块功能
  • 渐渐发展,通过构建对象的形式,来武装不同的功能
  • 继续发展,通过立即执行函数和闭包的形式来分离一个又一个的小组件
  • 当对象多起来的时候,又开始通过命名空间,来实现分级管理
  • 最终,历经十多年,社区渐渐发展壮大,commonJS规范的提出成了javascript 历史上最重要的里程碑。
  • Best Wishes : hope javascript can run everywhere!

CommonJS规范

CommonJS只是一个规范,不是文件或者框架,这点一定要清楚。它的官方网址:http://www.commonjs.org/ ,CommonJS中大部分只是草案或者说是理论,在近几年的发展中已有显著成效,这些规范包括:

  • 模块
  • 二进制
  • I/O流
  • 进程环境
  • 文件系统
  • 套接字
  • 单元测试
  • web服务器网关
  • 包管理等等涵盖了方方面面。

在后端nodejs显然已经是CommonJS规范的最佳实践。

nodejs中的require的内部机制

我们知道,在nodejs 中每个文件就是一个独立的模块。在模块之间不会造成变量污染和命名冲突等问题。通过exports 或者 module.exports 输出功能或者说提供API,我们通过require 来引入一个模块,很像前端通过script标签来引入js文件。但是它的内部细节又如何呢,在朴灵的那本《深入浅出》中有关javascript的模块编译那块已经做了一些讲解,那么我们现在去繁留简来深入体验一把:

  • require 函数的源码可以这样理解,当然我们简化了不少东西,现在我们只把它抽离出来 :

    // 模拟require的实现
    function _require(path) {
        // 定义一个Module对象
        var Module = function() {
            this.exports = {};
        }
    
        // 引入nodejs 文件模块 下面是nodejs中原生的require方法
        var fs = require('fs');
    
        // 同步读取该文件
        var sourceCode = fs.readFileSync(path, 'utf8');
    
        // 头尾拼接包装成新的字符串
        var packSourceCode = '(function(module,exports){ ' + sourceCode + ' return module.exports; })';
    
        // 字符串转换成函数
        var packFunc = eval(packSourceCode);
    
        // 实例化一个Module 里面有一个exports属性
        var module = new Module();
    
        // 把module 和 它内部的module.exports都作为参数传进去 
        // 并得到挂在到module.exports 或 exports上的功能
        var res = packFunc(module, module.exports);
    
        // 最终我们拿到了path代表的文件模块提供的API
        return res; 
    }
    
  • 说明: 上面举了一个小栗子来模拟nodejs中的require的实现,当然源码不会这样写,源码涉及的东西会更复杂些。上面只是一些帮助理解的小demo。

  • 我们自己写的逻辑功能全在path所代表的文件模块中,在内部把所有功能挂在到module.exports 或者exports对象上,最终return 他们得以暴露。

  • 我们可以看出 module.exports 和 exports 指向的是同一对象

  • 在require一个模块时大致经历了这几步:
    • 路径分析
    • 文件定位
    • 编译执行

一个小的 require 模块引入 案例

  • 在 util.js文件模块中,我们这样写

    // 定义一个计算器对象
    var Calculator = function() {};
    Calculator.prototype = {
        add: function(x, y) {
            return x + y;
        },
        subtract: function(x, y) {
            return x - y;
        },
        multiply: function(x, y) {
            return x * y;
        },
        divide: function(x, y) {
            return x / y;
        }
    }
    
    // 虽然exports 和 module.exports 指向同一个对象
    // 但是此处不能使用 exports = new Calculator(); 具体原因,下一篇博客分析
    
    module.exports = new Calculator(); // 暴露API对象
  • 在 index.js 文件中,我们这样写:

    var cal = require('./util');
    var res = cal.add(1, 2);
    console.log(res); // 3
  • 在 CLI 中,我们执行index模块,将会输出3

    $ node index
    3

nodejs中的模块分类和加载顺序

  • nodejs 中核心模块和文件模块的引用方式:

    • 核心模块: require(‘核心模块名’);
    • 文件模块: require(‘路径+文件名’); 路径可以用./代表的相对路径或者绝对路径,其中文件名可以省略后缀名。
    • 自定义模块:特殊的文件模块,可能是一个文件或者包的形式
  • 模块加载顺序 :

    • 优先从缓存加载
    • 核心模块:如http、fs、path等 (优先查找核心模块)
    • 文件模块: ./或../开始的相对路径文件模块,以/开始的绝对路径文件
    • 自定义模块:查找最费时

目录和包查找原则

  • 比如有如下的模块路径: 查找规则是沿路径向上逐级递归,直到根目录的node_modules目录:

    ├─/node_modules/  
    └─/home/node_modules/
    └─/user/test/node_modules/
    
  • 这就是自定义模块加载速度最慢的原因了。

  • 当我们require 的标识符 不包含扩展名node 会按照 .js .json .node 的次序补足扩展名 ,依次尝试。

  • 如果在require过程中,没有查找到对应文件,却得到一个目录,此时 node 会将当前目录当作一个包来处理。

    • 此时,node 会查找目录下的package.json文件,通过JSON.parse() 解析包描述对象,从中拿到main属性指定的文件名进行定位
    • 如果main属性指定错误,或者没有package.json文件,那么node会将index作为默认的文件名,去依次查找index.js , index.json , index.node
    • 在目录分析中没有定位到任何模块,那么它会遍历自己的上一级目录进行查找,如果还没找到,抛出查找失败的异常。
微信小程序反编译实战:从.wxapkg到可读源码的完整流程解析 在软件工程领域,逆向工程是一项重要的技术实践,它通过对编译产物的分析,理解程序的内部结构与运行逻辑。其核心原理在于解析二进制文件格式,还原高级语言的可读表示,常用于代码恢复、安全审计与学习研究。对于微信小程序而言,其开发代码(WXML、WXSS、JS)经官方编译器打包后生成.wxapkg文件,该文件包含了经过压缩、混淆和格式转换的代码与资源。反编译技术正是这一打包过程的逆向,通过社区工具链(如wxappUnpacker)解包、反混淆并重组项目结构,从而恢复出近似原始开发环境的源码。这项技术的工程价值在于,它 阅读详情

相关推荐

从零构建现代化TypeScript CLI工具:AI Agent开发的工程化实践

在软件开发领域,命令行界面(CLI)工具是开发者与系统交互的重要桥梁,其工程化水平直接影响开发效率和维护成本。通过静态类型检查、模块化设计和自动化构建等核心原理,现代CLI工具能够提供更可靠的代码质量和更流畅的开发体验。在AI Agent技术快速发展的背景下,一个健壮的工程基础对于集成复杂AI能力、实现可扩展的智能体框架具有关键价值。本文以TypeScript为核心技术栈,结合ESLint、Prettier、Vitest和Tsup等现代化工具链,详细演示如何搭建一个类型安全、测试完备、构建高效的CLI项目脚

weixin_30776545的博客 399

Node.js——CommonJS同步加载模块

目录 一.了解模块化 二.模块化规范 三.Node.js中的模块分类及加载 四.Node.js中的模块作用域 五.向外共享模块作用域的成员 六.exports和module.exports我们到底该怎么用 一.了解模块化 模块化(module)是指解决一个复杂的问题时,自顶向下逐层把系统划分为若干个模块的过程,在系统结果中,模块化是可组合,可分解,可更换的单元,它用来分割,组织和打包软件,每个模块完成一个特定的子功能,所有的模块按某种方法组装起来,成为一个整体,完成整个系统所要求的功能 .

世界和我们都不该止步于此 1675

一文看懂英伟达A100、H100、A800、H800、H20

想要Deepseek私有化部署吗?无论是训练大型AI模型,还是进行高性能计算(HPC),还是Deepseek私有化部署,都需要强大的GPU支持。而英伟达(NVIDIA)作为全球领先的AI芯片制造商,推出了一系列高性能GPU,包括等,广泛应用于AI训练、推理、科学计算等领域。如果想搭建一个属于自己的算力中心,该如何选择合适的GPU?本文将带你详细了解这些GPU的特性,并指导你如何搭建算力中心。一、英伟达算力GPU系列解析1. A100:数据中心AI计算的奠基石:Ampere:6912:432。

【可全包】本人程序员,不需要做任何吹嘘,只是实在写点程序,写点文档,熟悉各类主流框架,SSM,SpringBoot,Flask,Djiango,Mysql,Sqlite,VUE,Uniapp等,各类程序设计专家,优质作者 2万+

模块打包的三种方式----commonJs、requireJs和esm的简单使用

模块打包的三种方式----commonJs、requireJs和esm的简单使用

qq_64143127的博客 2401

合成孔径雷达Chirp Scaling(CS)算法MATLAB仿真实现

本人也是初学《合成孔径雷达成像算法与实现》,在GitHub上下载的关于CS算法的代码,仔细读了读,发现中间有一些不合理之处,动手改了一改,重新写了一个代码供初学者学习,有什么问题留言即可。 非常感谢源代码的作者,虽然中间有少许不正确的地方,但是对我理解cs算法的帮助非常大,非常感谢!!! 代码中提到的(4.31)这种均是在《合成孔径雷达成像算法与实现》中的公式 以下是MATLAB的仿真程序,直接复...

weixin_41700188的博客 7854

[Linux项目实践] LCD Panel的硬件分析及调试

LCD硬件分析 项目使用3.5” TFT-LCD并且支持触摸控制。LCD的硬件可从几个方面学习:1)查看LCD的硬件连线。2)查看数据手册了解寄存器的控制。3)查看LCD DATASHEET了解硬件操作 1)LCD硬件连线 在图中有33个引脚,22根数据引脚和9根控制引脚。 LCD的工作原理:像素点是从左至右,从上至下逐个显示,LCD控制寄存器会从从内存中的framebuffer通

Terry_Yuan的技术专栏 3025

commonJS的require函数深究原理,解决基全部相关面试题

commonJS的require函数深究原理,解决基全部相关面试题

qq_73917015的博客 332

别再到处找离线包了!Visual Studio 2022 企业版/社区版离线安装保姆级教程(含工作负载选择指南)

本文提供Visual Studio 2022企业版/社区版离线安装的详细教程,包括工作负载选择指南和批量安装优化策略。针对网络隔离或带宽受限环境,介绍如何制作离线安装包、选择合适的工作负载组合,并分享高级技巧如增量更新和自动化部署,帮助团队高效统一开发环境配置。

weixin_28745821的博客 734

commonJs-模块引入require的简单实现

我们知道,在node中每个文件就是一个模块,在模块之间不会造成变量污染和命名冲突等问题。通过exports 或者 module.exports 导出一个模块,通过require 来引入一个模块 关于模块的介绍,可参考原先写的一篇博客node学习笔记-模块,这篇博客主要简单介绍了在模块引入时步骤及简单原理,模块在引入时,需要经历以下过程 路径解析 创建模块 尝试加载该模块 尝试加载该模块时 ...

张小杰 2802

Vivado 2023.1及更早版本永久License全功能解锁:HLS、System Generator等IP核使用详解

本文深入解析Vivado 2023.1及更早版本的全功能许可证,详细指导如何解锁HLS、System Generator等高级IP核。通过许可证类型对比、功能验证方法和实战应用指南,帮助FPGA开发者充分利用Vivado工具套件,提升复杂系统设计和算法加速的效率。

weixin_31286719的博客 384

<202505高项>《【VIP合集】 软考高项(第四版)十大知识域、五大过程组、ITTO输入输出工具、项目绩效域》

软考高项(第四版)十大知识域、五大过程组、ITTO输入输出工具、项目绩效域

Else 的博客 1858

[CommonJS 模块 - require/exports] 和 [ES6 模块 - import/export] 的用法

[CommonJS 模块 - require/exports] 和 [ES6 模块 - import/export] 用法

lorie_yy的博客 825

金融领域图注意力网络的创新应用

随着金融市场的日益复杂和数据量的爆炸式增长,传统的数据分析方法在处理金融数据的复杂关系和结构时面临诸多挑战。图注意力网络(Graph Attention Network,GAT)作为一种新兴的深度学习技术,能够有效处理图结构数据,挖掘数据中的潜在关系。本文的目的在于深入探讨图注意力网络在金融领域的创新应用,涵盖风险评估、投资决策、欺诈检测等多个方面。通过理论分析、算法实现和实际案例展示,为金融从业者和研究者提供全面的技术参考,推动图注意力网络在金融领域的广泛应用。

AI云原生与云计算技术学院 722

require.js模块化整理

本文是对自己JS学习的一个总结和一些碎片化学习的整理,主要是关于模块化的以及require.js。后面可能会写个小插件的或者源码阅读的博文。 如果有同学不幸看到本人的这篇博文,对此实属抱歉。你可以去看原著,我这里只是自己的整理。 文章参照阮一峰老师的博文:Javascript模块化编程(三):require.js的用法 (注:原著真的很清楚详细,如果你看不懂有两种可能:zs不够或层次未到。我...

qq_36458054的博客 420

DISM进行系统修复,进度条卡在63.2%的解决方法

一时用不了软件,安装修复的时候也出现问题 DISM一直卡在63.2%,等了好久时间,直接强制退出寻找最终的解决方案

码农研究僧的博客 1万+

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

前端技术总结(前端技术地图)

了解到的前端新技术总结 在最近的一个月内,快速的了解一下。 不要求都精通(不可能),但要全部了解一下。 然后找其中一个深入学习一下。 本文对整个前端包括node端涉及到的技术进行一个梳理,对各个知识点进行准确定位。 一、前端模块化 随着前端需求复杂度不断增加,一个公司内的前端开发人员也迅速增加,前端需要和后端开发一样的模块化支持,来方便的引用外部的开源...

aae4581的博客 455

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

前端秋招笔试怎么准备?小米卷2考点全复盘与避坑指南

前端开发入门门槛低、精通门槛高,大厂笔试不仅考察基础概念,更看重对JavaScript核心机制、CSS布局原理、框架底层逻辑与工程化实践的综合理解。原型链与继承、this指向、闭包应用、事件循环中的微任务与宏任务,是区分候选人水平的关键考点;而盒模型、BFC、水平垂直居中方案,以及浏览器渲染流程中的重排与重绘优化,则是日常页面性能调优的必备基础。理解Vue/React响应式原理与虚拟DOM diff策略,掌握ES Module与CommonJS差异,能帮助开发者在真实项目中写出更高性能、更易维护的代码。面对

weixin_30587927的博客 478

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

2024前端面试实战:从小红书真题看核心考点与答题策略

前端面试不只是考察API记忆,更关注对JavaScript核心机制、框架原理与性能优化实战的理解。从闭包与事件循环的底层推导,到Vue3响应式与React Hooks的状态管理设计,再到长列表渲染、浏览器缓存等性能优化策略,这些技术点共同构成了内容型产品前端工程师的能力模型。在真实业务场景中,面试官会围绕信息流、详情页等场景考察候选人的问题拆解与工程落地能力。掌握这些基础知识与原理,不仅有助于应对面试,也能为复杂前端工程的设计与优化提供指导。基于2024年面试季高频题目,这里整理了一份实战向的前端面试核心考

weixin_32570803的博客 336

前端学习规划

HTML5:CSS3:JavaScript:渲染机制:事件循环:安全机制:存储方案:HTTP/HTTPS:WebSocket:WebRTC:打包工具:任务管理:代码质量:自动化:部署策略:监控体系:加载优化:运行时优化:渲染优化:React:Vue:Angular:移动端:桌面端:小程序:数据流模式:异步处理:持久化:Node.js基础能力:数据库:API设计:BFF层(Backend For Frontend)聚合层:性能优化:安全控制:函数计算:边缘计算:Web与原生通信:原生功能调用:Hybrid A

zxz86的博客 923

Vue 完整版系统知识文档

《Vue全栈开发实战手册》摘要 本手册系统整合Vue2/Vue3全栈知识体系,涵盖基础语法、组件开发、状态管理、工程化等核心内容,适合从入门到精通的完整学习路径。主要特点: 基础核心 详解MVVM架构和响应式原理(Vue2的Object.defineProperty vs Vue3的Proxy) 完整模板语法规则与16种内置指令解析 组件系统核心:通信机制(8种方案)、插槽、动态组件、递归组件 进阶实战 状态管理:Vuex/Pinia完整解决方案 路由开发:动态路由、权限控制、懒加载 工程化:Webpack

专注 Java 后端开发,分享基础语法、JVM、并发、Spring 全家桶、微服务、分布式、性能优化等实战干货。坚持输出高质量技术笔记,用简单语言讲清复杂原理,助力每一位 Java 开发者稳步进阶。 402

Animate.css:CSS动画标准化实践与工程化落地指南

CSS动画是现代Web界面体验的核心能力之一,其本质基于@keyframes规则与animation属性的协同工作。理解transform和opacity等合成层友好属性的渲染原理,是实现60fps流畅动效的技术基础。Animate.css并非简单动画集合,而是经过大规模项目验证的CSS动画工程化标准——它通过命名空间隔离、浏览器兼容性兜底、可组合链式触发等设计,将抽象动效转化为语义化class,显著提升团队协作效率与交付稳定性。本文聚焦于Animate.css在真实业务场景中的集成策略、性能优化要点及与H

2411

白骑士的JavaScript教学高级篇之模块化 4.1.3 CommonJS模块(require, module.exports)

在深入了解ES6模块化系统之前,JavaScript社区主要使用CommonJS作为模块化方案。CommonJS广泛应用于Node.js环境,它通过‘require‘和‘module.exports‘提供了简单而有效的模块化机制。虽然ES6模块已经成为现代JavaScript的主流,但理解CommonJS依然非常重要,特别是在处理旧版代码或Node.js项目时。

JeremyTC的博客 1203

【JS】797- 手写CommonJS 中的 require函数

前言 来自于圣松大佬的文章《手写CommonJS 中的 require函数》什么是 CommonJS ?node.js 的应用采用的commonjs模块规范。每一个文件就是一个模块,拥有...

pingan8787 840

CommonJS 和 RequireJS 的实现原理

requirejs 导入模块的方式实际就是创建脚本标签,一切的模块都需要经过这个方法创建。commonjs是通过module.exports导出模块,用require引入一个模块,原理:闭包。requirejs是通过define定义导出模块,用require引入模块。require.js 实现异步加载的源码。

subsistent的博客 689

CommonJS、requirejs、ES6的对比

CommonJS CommonJS就是为JS的表现来制定规范,因为js没有模块的功能所以CommonJS应运而生,它希望js可以在任何地方运行,不只是浏览器中。 CommonJS是nodejs也就是服务器端广泛使用的模块化机制。 该规范的主要内容是,模块必须通过module.exports 导出对外的变量或接口,通过 require() 来导入其他模块的输出到当前模块作用域中。 根据这个规范,每个文件就是一个模块,有自己的作用域,文件中的变量、函数、类等都是对其他文件不可见的。 如果...

weixin_42716945的博客 1295
上一篇: 突破github的100M单个大文件上传限制
下一篇: 整理nodejs中的exports 和 module.exports的关系
Wang's Blog
博客等级 码龄12年 7433粉丝 2421原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值