深入了解node.js中的module-alias(分享一些避坑方法)

2023-05-16

本篇文章带大家了解一下node.js中的module-alias,介绍一下module-alias原理、module-alias的一个常见问题(坑),希望对大家有所帮助!

首先有必要介绍一下module-alias是什么,这里有其官网链接(官网地址 https://github.com/ilearnio/module-alias)。

简单点说,module-alias提供了在node环境下的路径别名功能。一般前端开发可能会比较熟悉webpackalias配置、typescriptpaths配置等,这些都是提供了陆军别名的功能。路径别名在代码开发过程中是yyds,不然你看到这种../../../../xx路径时,是肯定会抓狂的。

使用webpack打包的项目webpack本身会处理源代码中路径别名的配置到打包后代码的转换过程,但是如果单纯使用typescript进行编译的项目,虽然typescript在编译过程中可以正常处理paths中路径别名的配置,但是并不会改变打包后的代码,造成在打包后的代码中仍然存在路径别名配置,看一个经过typescript编译后的代码:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
require("./module-alias-register");
var commands_1 = require("@/commands");
var package_json_1 = require("../package.json");
(0, commands_1.run)(package_json_1.version);

这里是tsconfig.json的配置内容

"paths": {
  "@/*": [
    "src/*"
  ]
}

可以看到在经过typescript编译后的代码中,仍然存在@符号,然而当代码运行的过程中,比如允许在node中,require并不能正常识别路径里的这个符号,导致找不到相应模块而抛出异常。

这也是module-alias这个库存在的目的。

module-alias介绍

从官网上看,这个库使用方法只需要两步,真的已经是极简状态了。

1、路径别名配置:module-alias支持两种路径别名配置方式

  • package.json中增加_moduleAliases属性进行配置

    "_moduleAliases": {
        "@": "./src"
    }
  • 通过提供的API接口addAliasaddAliasesaddPath,增加配置

    moduleAlias.addAliases({
      '@'  : __dirname + './src',
    });

2、在项目启动时首先导入该库:require(module-alias/register)即可,当然选择使用API方式的需要导入对应的函数进行处理

一般我们都是使用package.json中配置路径别名 + 项目入口处require(module-alias/register)来使用这个库。

module-alias原理介绍

module-alias通过覆写了全局对象Module上的方法_resolveFilename来实现路径别名的转换,简单来说就是通过拦截原生的_resolveFilename方法调用,进行路径别名的转换,当获取到文件的真实路径后,再调用原声的_resolveFilename方法。

下面是其源代码,基本上分为两部分:路径别名转换+原生_resolveFilename调用

var oldResolveFilename = Module._resolveFilename
Module._resolveFilename = function (request, parentModule, isMain, options) {
  for (var i = moduleAliasNames.length; i-- > 0;) {
    var alias = moduleAliasNames[i]
    if (isPathMatchesAlias(request, alias)) {
      var aliasTarget = moduleAliases[alias]
      // Custom function handler
      if (typeof moduleAliases[alias] === 'function') {
        var fromPath = parentModule.filename
        aliasTarget = moduleAliases[alias](fromPath, request, alias)
        if (!aliasTarget || typeof aliasTarget !== 'string') {
          throw new Error('[module-alias] Expecting custom handler function to return path.')
        }
      }
      request = nodePath.join(aliasTarget, request.substr(alias.length))
      // Only use the first match
      break
    }
  }

  return oldResolveFilename.call(this, request, parentModule, isMain, options)
}

看似简单的背后,往往也会踩坑

module-alias踩坑

一般我们会在node项目中使用module-alias库,因为node项目一般会从typescript转换成js代码,但是往往并不会进行打包处理,因为node项目中一般也确实不需要打包,显得有些冗余。这时候就需要module-alias上场了。

但是这个项目有点不一般,我们在项目中使用了多层代码组织方式,最外层有全局的package.json, 内层包有自己的package.json, 简单说是使用了monorepo的代码组织方式,问题也就是由此而来

module-alias无法正常解析在package.json中配置的路径别名

刚开始确实没想到是多层项目组织方式的问题,官网对module-alias/register使用有一段说明:

但是当时确实也是没有注意到这块说明,要不然也不会踩这个坑了,下次看使用说明要仔细了,不过这么长的使用说明,大概率还是不会看的这么仔细。。。毕竟看起来这么简单的使用方法,好像似乎是不会出什么问题的吧

module-alias/register流程

既然踩坑了,就有必要了解一下踩坑的原因,避免反复踩坑才好。可以详细了解下module-aliasinit方法的实现。为了节省篇幅,省略了部分细节

function init (options) {
  // 省略了部分内容
  var candidatePackagePaths
  if (options.base) {
    candidatePackagePaths = [nodePath.resolve(options.base.replace(/\/package\.json$/, ''))]
  } else {
    // There is probably 99% chance that the project root directory in located
    // above the node_modules directory,
    // Or that package.json is in the node process' current working directory (when
    // running a package manager script, e.g. `yarn start` / `npm run start`)
    // 重点看这里!!!
    candidatePackagePaths = [nodePath.join(__dirname, '../..'), process.cwd()]
  }
  var npmPackage, base
  for (var i in candidatePackagePaths) {
    try {
      base = candidatePackagePaths[i]
      npmPackage = require(nodePath.join(base, 'package.json'))
      break
    } catch (e) { // noop }
  }
  // 省略了部分内容
  var aliases = npmPackage._moduleAliases || {}
  for (var alias in aliases) {
    if (aliases[alias][0] !== '/') {
      aliases[alias] = nodePath.join(base, aliases[alias])
    }
  }
  // 省略了部分内容
}

可以看重点部分,如果我们没有给base参数,module-alias默认会从../../目录和当前目录下找寻package.json文件,而且../..目录下的package.json文件的优先级比当前目录下的优先级还要高,这里的优先级设置似乎和正常的优先级逻辑有点差别,一般都会让当前目录的优先级比较高才比较符合正常逻辑,所以会导致加载的不是当前目录下的package.json文件,而导致找不到路径别名配置而出错。

关于这点似乎有不少人踩坑了,还有人提了issues,但是似乎暂时并没有人回应。

解决办法

通过API方式注册路径别名,或者手动调用init方法,传入base参数,指定package.json文件.

似乎只有踩坑了,才会更深入的了解

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入了解node.js中的module-alias(分享一些避坑方法) 的相关文章

  • 8个编写JS代码的小技巧和窍门

    下面js教程栏目给大家介绍8个编写javascript代码的技巧和窍门 有一定的参考价值 xff0c 有需要的朋友可以参考一下 xff0c 希望对大家有所帮助 推荐教程 xff1a JavaScript视频教程 1 生成指定区间内的数字 有
  • 浅谈css z-index应用

    做过页面布局的同学对z index属性应该是很熟悉了 xff0c z index是针对网页显示中的一个特殊属性 因为显示器是显示的图案是一个二维平面 xff0c 拥有x轴和y轴来表示位置属性 为了表示三维立体的概念如显示元素的上下层的叠加顺
  • jquery中怎样将类数组对象转换为数组对象

    相关推荐 xff1a jQuery视频教程 类数组对象的定义 xff1a 所谓 34 类数组对象 34 就是一个常规的Object对象 xff0c 如 34 p 34 但它和数组对象非常相似 xff1a 具备length属性 xff0c 并
  • 理解对象原型和原型链

    本篇文章带大家介绍一下JavaScript中的对象原型和原型链 有一定的参考价值 xff0c 有需要的朋友可以参考一下 xff0c 希望对大家有所帮助 对象原型 相信大家都这样用过 map xff1a let arr 61 0 1 2 le
  • JavaScript中处理异步的几种方式

    在网站开发中 xff0c 异步事件是项目必然需要处理的一个环节 xff0c 也因为前端框架的兴起 xff0c 通过框架实现的 SPA 已经是快速建构网站的标配了 xff0c 一部获取数据也就成了不可或缺的一环 xff1b 本文来就讲一讲 J
  • 软件测试 | 测试开发 | 一种基于目标检测实现黑花屏分类任务的方案

    背景 视频帧的黑 花屏的检测是视频质量检测中比较重要的一部分 xff0c 传统做法是由测试人员通过肉眼来判断视频中是否有黑 花屏的现象 xff0c 这种方式不仅耗费人力且效率较低 为了进一步节省人力 提高效率 xff0c 一种自动的检测方法
  • VSCode使用Git进行版本控制

    相关推荐 xff1a vscode基础教程 Visual Studio Code 使用Git进行版本控制 本来认为此类教程 xff0c 肯定是满网飞了 今天首次使用VS Code的Git功能 xff0c 翻遍了 所有中文教程 xff0c 竟
  • 使用Llama Logs实时可视化Node错误

    本篇文章给大家介绍一下Node开发神器 Llama Logs xff0c 使用Llama Logs实时可视化Node错误 有一定的参考价值 xff0c 有需要的朋友可以参考一下 xff0c 希望对大家有所帮助 相关推荐 xff1a node
  • JS中的工厂函数和构造函数

    当谈到JavaScript语言与其他编程语言相比时 xff0c 你可能会听到一些令人困惑东西 xff0c 其中之一是工厂函数和构造函数 工厂函数 所谓工厂函数 xff0c 就是指这些内建函数都是类对象 xff0c 当你调用他们时 xff0c
  • 如何使用 map 代替纯 JavaScript 对象?

    JavaScript 普通对象 key 39 value 39 可用于保存结构化数据 但是我发现很烦人的一件事 xff1a 对象的键必须是字符串 xff08 或很少使用的符号 xff09 如果用数字作键会怎样 xff1f 在这种情况下没有错
  • 深入浅析Service Workers

    本篇文章给大家介绍一下JavaScript API Service Workers 有一定的参考价值 xff0c 有需要的朋友可以参考一下 xff0c 希望对大家有所帮助 相关推荐 xff1a 编程入门 service worker 是什么
  • javascript中的modules、import和export

    在互联网的洪荒时代 xff0c 网站主要用 HTML和 CSS 开发的 如果将 JavaScript 加载到页面中 xff0c 通常是以小片段的形式提供效果和交互 xff0c 一般会把所有的 JavaScript 代码全都写在一个文件中 x
  • 分享Atom入坑需要安装的一些插件

    本篇文章给大家推荐一些Atom入坑必备插件 有一定的参考价值 xff0c 有需要的朋友可以参考一下 xff0c 希望对大家有所帮助 相关推荐 xff1a atom使用教程 Atom作为Javascript CSS HTML等前端编辑器利器
  • angular中使用jsencrypt插件

    本篇文章给大家介绍一下angular中jsencrypt插件的使用方法 有一定的参考价值 xff0c 有需要的朋友可以参考一下 xff0c 希望对大家有所帮助 相关推荐 xff1a angular教程 angular使用jsencrypt插
  • 使用 Node 处理 I/O 密集型任务

    下面本篇文章给大家介绍一下使用 nodejs 多线程 处理高并发任务的方法 有一定的参考价值 xff0c 有需要的朋友可以参考一下 xff0c 希望对大家有所帮助 相关推荐 xff1a nodejs视频教程 摩尔定律 摩尔定律是由英特尔联合
  • 软件测试 | 测试开发 | Android App 保活服务的配置与禁用

    Android应用保活是应用 系统 用户三个角色相互影响的产物 几乎每一款应用都希望自己能实现永久保活 xff0c 并通过保活实现消息推送 信息上报等等交互行为 xff1b 几乎所有的系统厂商都想把应用关在笼子里 xff0c 通过控制应用的
  • JavaScript中拷贝数组的14个小技巧

    相关推荐 xff1a javascript视频教程 数组拷贝经常被误解 xff0c 但这并不是因为拷贝过程本身 xff0c 而是因为缺乏对 JS 如何处理数组及其元素的理解 JS 中的数组是可变的 xff0c 这说明在创建数组之后还可以修改
  • JavaScript中的内存管理

    相关推荐 xff1a javascript视频教程 大多数时候 xff0c 我们在不了解有关内存管理的知识下也只开发 xff0c 因为 JS 引擎会为我们处理这个问题 不过 xff0c 有时候我们会遇到内存泄漏之类的问题 xff0c 这个只
  • 详解bootstrap自定义侧边导航栏的方法

    本篇文章给大家介绍一下bootstrap自定义侧边导航栏的方法 有一定的参考价值 xff0c 有需要的朋友可以参考一下 xff0c 希望对大家有所帮助 bootstrap自带的响应式导航栏是向下滑动的 xff0c 有时满足不了个性化的需求
  • 使用VSCode调试Golang工程

    本篇文章给大家介绍一下使用VSCode调试Golang工程的方法 有一定的参考价值 xff0c 有需要的朋友可以参考一下 xff0c 希望对大家有所帮助 推荐学习 xff1a vscode教程 关键字 最简单的调试攻略多项目调试 适用个人开

随机推荐

  • 深入解析JavaScript中的作用域

    本篇文章带大家深入理解JavaScript作用域 有一定的参考价值 xff0c 有需要的朋友可以参考一下 xff0c 希望对大家有所帮助 这篇文章称为笔记更为合适一些 xff0c 内容来源于 你不知道的JavaScript xff08 上卷
  • 12个提升程序员软技能与效率的开发工具(转载)

    本篇文章给大家推荐12个提升程序员软技能与效率的开发工具 有一定的参考价值 xff0c 有需要的朋友可以参考一下 xff0c 希望对大家有所帮助 大家好 xff0c 我是你们的 猫哥 xff0c 那个不喜欢吃鱼 又不喜欢喵 的超级猫 这一期
  • 一文了解Nodejs中的模块化和事件循环

    本篇文章带大家了解一下Nodejs中的模块化和事件循环 有一定的参考价值 xff0c 有需要的朋友可以参考一下 xff0c 希望对大家有所帮助 5 20出了一款线上Ide xff0c 能够在浏览器上边运行 Node js WebContai
  • 浅谈php输出数组的4种方法

    在之前的文章 PHP数组学习之一维数组如何创建和初始化 xff08 代码详解 xff09 和 PHP数组学习之二维数组创建方法浅析 中我们通过代码实例介绍了一维数组和二维数组的定义方法 xff0c 简单易懂 既然数组创建并初始化了 xff0
  • 浅谈PHP遍历数组之for循环语句

    数组是一个非常基础和重要的数据结构 xff0c 当我们创建好一个数组后 xff0c 就需要去操作它 xff1b 而数组最常见的一个操作就是循环遍历 PHP中支持多种遍历数组的方法 xff0c 今天我们就来学习如何利用for循环语句来遍历数组
  • 软件测试 | 测试开发 | Python中日志异步发送到远程服务器

    背景 在Python中使用日志最常用的方式就是在控制台和文件中输出日志了 logging模块也很好的提供的相应 的类 使用起来也非常方便 但是有时我们可能会有一些需求 如还需要将日志发送到远端 或者直接写入数 据库 这种需求该如何实现呢 S
  • 笔记本外接显示器闪烁问题

    笔记本外接显示器闪烁问题 最简单的一个解决方法 xff1a 就是不要把显示器和笔记本的电源插到同一个排插上
  • 8种CSS实现loading加载特效的小技巧(分享)

    本篇文章给大家分享8种CSS实现loading加载特效的小技巧 xff0c 希望对大家有所帮助 xff01 为什么会写这种文章呢 xff1f 平时开发的时候 xff0c 我们遇到加载 xff0c 要么是UI框架中自带 xff0c 要么就是百
  • 值得收藏的26个css面试题,增强你的CSS基础!

    CSS在网页设计中非常流行 xff0c 可以减少结构内容中的复杂性和重复 本篇文章给大家分享26个基于css的面试题 xff0c 可以增强你的CSS基础 xff0c 快来学习吧 xff08 学习视频分享 xff1a css视频教程 xff0
  • JavaScript中关于“this”的7个有趣面试题,你能全答对吗?

    相关推荐 xff1a 2021年大前端面试题汇总 xff08 收藏 xff09 在 JavaScript 中 xff0c this 是函数调用上下文 正是由于 this 的行为很复杂 xff0c 所以在 JavaScript 面试中 xff
  • 分享几种实用的Node.js调试方法,快来收藏吧!!

    本篇文章给大家介绍Nodejs调试的几种方式 有一定的参考价值 xff0c 有需要的朋友可以参考一下 xff0c 希望对大家有所帮助 相关推荐 xff1a nodejs 教程 第一种 1 打开 vscode 内置终端 xff0c 右上角选择
  • 聊聊在VSCode中怎么点击DOM 自动定位到相应代码行?

    如何在 Vue 项目中 xff0c 通过点击 DOM 自动定位VSCode中的代码行 xff1f 下面本篇文章就来给大家分享一个插件 xff0c 并聊聊实现原理 xff0c 快来收藏吧 xff01 现在大型的 Vue项目基本上都是多人协作开
  • 一文深入了解 Node 中的事件循环

    Node js是单线程的语言 xff0c 是通过事件循环处理非阻塞I O操作的 下面本篇文章带大家详细了解 Node 中的事件循环 xff0c 希望对大家有所帮助 xff01 Node js 做为 JavaScript 的服务端运行时 xf
  • 深入解析vue中的key,看看key到底能拿来干嘛!

    key到底有什么用途 xff1f 下面本篇文章给大家深度解析一下vue中的key xff0c 看看key到底能拿来干嘛 xff0c 希望对大家有所帮助 xff01 vue中关于key的深度解析 key到底有什么用途 先来看官方解释 key属
  • 一文聊聊Node.js中的模块路径解析

    本篇文章带大家了解一下Node js中的模块路径解析 xff0c 介绍一下Node模块路径解析方法 xff0c 希望对大家有所帮助 xff01 require案例 当前有一个项目当前项目路径 Users rainbow Documents
  • 聊聊node中怎么借助第三方开源库实现网站爬取功能

    本篇文章给大家介绍一下node中借助第三方开源库轻松实现网站爬取功能的方法 xff0c 希望对大家有所帮助 xff01 nodejs实现网站爬取功能 第三方库介绍 request 对网络请求的封装 cheerio node 版本的 jQue
  • Angular中非父子组件间怎么通讯

    Angular中非父子组件间怎么通讯 xff1f 本篇文章给大家介绍一下Angular非父子组件之间通过服务通讯的方法 xff0c 希望对大家有所帮助 xff01 其实提到父子组件之间传值 xff0c 对我们来说 xff0c 再熟悉不过了
  • 软件测试 | 测试开发 | Django+Celery框架自动化定时任务开发

    本章介绍使用DjCelery即Django 43 Celery框架开发定时任务功能 xff0c 在Autotestplat平台上实现单一接口自动化测试脚本 业务场景接口自动化测试脚本 App自动化测试脚本 Web自动化测试脚本等任务的定时执
  • 认识一下vue中的$attrs和$listeners属性,聊聊用法

    本篇文章带大家了解一下vue中封装组件利器 xff1a attrs listeners属性 xff0c 看看它们的用法 xff0c 希望对大家有所帮助 xff01 多级组件嵌套需要传递数据时 xff0c 通常使用的方法是通过vuex 但仅仅
  • 深入了解node.js中的module-alias(分享一些避坑方法)

    本篇文章带大家了解一下node js中的module alias xff0c 介绍一下module alias原理 module alias的一个常见问题 xff08 坑 xff09 xff0c 希望对大家有所帮助 xff01 首先有必要介