• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • dedecms
  • ecshop
  • z-blog
  • UcHome
  • UCenter
  • drupal
  • WordPress
  • 帝国cms
  • phpcms
  • 动易cms
  • phpwind
  • discuz
  • 科汛cms
  • 风讯cms
  • 建站教程
  • 运营技巧
您的位置:首页 > CMS教程 >建站教程 > Node.js深入学习之浅析require函数中怎么添加钩子

Node.js深入学习之浅析require函数中怎么添加钩子

作者:站长图库 字体:[增加 减小] 来源:互联网

站长图库向大家介绍了Node.js深入学习,require函数添加钩子等相关知识,希望对您有所帮助

如何为 Node 的 require 函数添加钩子?下面本篇文章就来带大家了解一下require函数中添加钩子的方法,希望对大家有所帮助!


Node.js深入学习之浅析require函数中怎么添加钩子


Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境。早期的 Node.js 采用的是 CommonJS 模块规范,从 Node v13.2.0 版本开始正式支持 ES Modules 特性。直到 v15.3.0 版本 ES Modules 特性才稳定下来并与 NPM 生态相兼容。


Node.js深入学习之浅析require函数中怎么添加钩子


本文将介绍 Node.js 中 require 函数的工作流程、如何让 Node.js 直接执行 ts 文件及如何正确地劫持 Node.js 的 require 函数,从而实现钩子的功能。接下来,我们先来介绍 require 函数。

require 函数

Node.js 应用由模块组成,每个文件就是一个模块。对于 CommonJS 模块规范来说,我们通过 require 函数来导入模块。那么当我们使用 require 函数来导入模块的时候,该函数内部发生了什么?这里我们通过调用堆栈来了解一下 require 的过程:


Node.js深入学习之浅析require函数中怎么添加钩子


由上图可知,在使用 require 导入模块时,会调用 Module 对象的 load 方法来加载模块,该方法的实现如下所示:

// lib/internal/modules/cjs/loader.jsModule.prototype.load = function(filename) {  this.filename = filename;  this.paths = Module._nodeModulePaths(path.dirname(filename));   const extension = findLongestRegisteredExtension(filename);   Module._extensions[extension](this, filename);  this.loaded = true;  // 省略部分代码};

注意:本文所引用 Node.js 源码所对应的版本是 v16.13.1

在以上代码中,重要的两个步骤是:

步骤一:根据文件名找出扩展名;

步骤二:通过解析后的扩展名,在 Module._extensions 对象中查找匹配的加载器。

在 Node.js 中内置了 3 种不同的加载器,用于加载 node、json 和 js 文件。node 文件加载器

// lib/internal/modules/cjs/loader.jsModule._extensions['.node'] = function(module, filename) {  return process.dlopen(module, path.toNamespacedPath(filename));};

json 文件加载器

// lib/internal/modules/cjs/loader.jsModule._extensions['.json'] = function(module, filename) {    const content = fs.readFileSync(filename, 'utf8');    try {        module.exports = JSONParse(stripBOM(content));    } catch (err) {        err.message = filename + ': ' + err.message;        throw err;    }};

js 文件加载器

// lib/internal/modules/cjs/loader.jsModule._extensions['.js'] = function(module, filename) {  // If already analyzed the source, then it will be cached.  const cached = cjsParseCache.get(module);  let content;  if (cached?.source) {    content = cached.source;    cached.source = undefined;  } else {    content = fs.readFileSync(filename, 'utf8');  }  // 省略部分代码  module._compile(content, filename);};

下面我们来分析比较重要的 js 文件加载器。通过观察以上代码,我们可知 js 加载器的核心处理流程,也可以分为两个步骤:

步骤一:使用 fs.readFileSync 方法加载 js 文件的内容;

步骤二:使用 module._compile 方法编译已加载的 js 代码。

那么了解以上的知识之后,对我们有什么用处呢?其实在了解 require 函数的工作流程之后,我们就可以扩展 Node.js 的加载器。比如让 Node.js 能够运行 ts 文件。

// register.jsconst fs = require("fs");const Module = require("module");const { transformSync } = require("esbuild"); Module._extensions[".ts"] = function (module, filename) {  const content = fs.readFileSync(filename, "utf8");  const { code } = transformSync(content, {    sourcefile: filename,    sourcemap: "both",    loader: "ts",    format: "cjs",  });  module._compile(code, filename);};

在以上代码中,我们引入了内置的 module 模块,然后利用该模块的 _extensions 对象来注册我们的自定义 ts 加载器。

其实,加载器的本质就是一个函数,在该函数内部我们利用 esbuild 模块提供的 transformSync API 来实现 ts -> js 代码的转换。当完成代码转换之后,会调用 module._compile 方法对代码进行编译操作。

看到这里相信有的小伙伴,也想到了 Webpack 中对应的 loader,想深入学习的话,可以阅读 多图详解,一次性搞懂Webpack Loader 这篇文章。

地址:https://mp.weixin.qq.com/s/2v1uhw2j7yKsb1U5KE2qJA

篇幅有限,具体的编译过程,我们就不展开介绍了。下面我们来看一下如何让自定义的 ts 加载器生效。要让 Node.js 能够执行 ts 代码,我们就需要在执行 ts 代码前,先完成自定义 ts 加载器的注册操作。庆幸的是,Node.js 为我们提供了模块的预加载机制:

$ node --help | grep preload  -r, --require=... module to preload (option can be repeated)

即利用 -r, --require 命令行配置项,我们就可以预加载指定的模块。了解完相关知识之后,我们来测试一下自定义 ts 加载器。首先创建一个 index.ts 文件并输入以下内容:

// index.tsconst add = (a: number, b: number) => a + b; console.log("add(a, b) = ", add(3, 5));

然后在命令行输入以下命令:

node -r ./register.js index.ts

当以上命令成功运行之后,控制台会输出以下内容:

add(a, b) =  8

很明显我们自定义的 ts 文件加载器生

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Node.js深入学习之浅析require函数中怎么添加钩子

相关文章

  • PHP开发微信授权登录教程
  • 如何使用PHP原生来导出Excel和CSV文件
  • vue-cli-service不是内部或外部命令怎么解决
  • 详解Laravel前端工程化之mix
  • Photoshop制作梦幻光点效果的艺术字教程
  • MacOS下PHP7.1升级到PHP7.4.15的方法
  • PS打造缝线文字效果
  • 做seo排名时你的侧重点是什么
  • PHP如何设置过期时间的session
  • 详解mysql double master的配置方法

文章分类

  • dedecms
  • ecshop
  • z-blog
  • UcHome
  • UCenter
  • drupal
  • WordPress
  • 帝国cms
  • phpcms
  • 动易cms
  • phpwind
  • discuz
  • 科汛cms
  • 风讯cms
  • 建站教程
  • 运营技巧

最近更新的内容

    • 使用thinkphp3.2.3开发微信授权登录详细教程
    • Photoshop打造快速坠入水的文字特效
    • 柒比贰主题网格风格四缩略图对齐样式代码
    • YII怎么输出sql语句?
    • laravel-admin怎么使用wang-editor富文本插件
    • Photoshop制作卡通风格的3D立体字教程
    • AI绘制质感电池图标
    • Dede网站布局搜索引擎优化优化技能汇总
    • 10个值得收藏的CSS实用小技巧
    • Photoshop制作立体有机玻璃文字效果

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有