站长家园(原代码之家)(www.adminjie.com)网站源码,微信源码,游戏源码,商业源码分享平台。
当前位置:网站首页 技术文章 网络编程 正文

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

时间:2021-12-24 [网络编程]作者:fabuyuan 浏览:7 次

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

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

首先有必要介绍一下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使用有一段说明:

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

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

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 教程!!

以上就是深入了解node.js中的module-alias(分享一些避坑方法)的详细内容,更多请关注站长家园其它相关文章!

本文标签:  node.jsmodule-alias

转载请注明来源:深入了解node.js中的module-alias(分享一些避坑方法)

本文永久链接地址:https://www.adminjie.com/post/6766.html

免责声明:
本站所发布的一切资源仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。

附:
二○○二年一月一日《计算机软件保护条例》第十七条规定:为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬!鉴于此,也希望大家按此说明研究软件!

版权声明:
一、本站致力于为软件爱好者提供国内外软件开发技术和软件共享,着力为用户提供优资资源。
二、本站提供的部分源码下载文件为网络共享资源,请于下载后的24小时内删除。如需体验更多乐趣,还请支持正版。
三、我站提供用户下载的所有内容均转自互联网。如有内容侵犯您的版权或其他利益的,若有侵犯你的权益请:提交版权证明文件到邮箱 2225329873#qq.com(#换为@) 站长会进行审查之后,情况属实的会在三个工作日内为您删除。

  • 站长家园(原代码之家)会员升级
  • 最新文章
    • 什么是docker hub

      什么是docker hub

      dockerhub是Docker网维护的一个公共仓库,其中已经包括了数量超过2650000的镜像;大部分需求都可以通过在DockerHub中直接下载镜像来...

    • mysql怎样in查询操作排序

      mysql怎样in查询操作排序

      在mysql中,可利用“ORDERBY”子句配合SELECT语句in查询来操作排序,语法为“select*from表名where字段值in(排序1,排...

    • docker能用yum命令吗

      docker能用yum命令吗

      docker能用yum命令,docker容器内安装yum的方法:1、通过“apt-getupdate”更新apt-get指令;2、通过“apt-getins...

    • 如何解决docker telnet不通的问题

      如何解决docker telnet不通的问题

      dockertelnet不通的解决办法:1、查看配置文件;2、修改nginx配置文件的端口为80;3、重新加载即可。本文操作环境:centOS6.8系统、Do...

    • css怎样改变一个图片高度和宽度

      css怎样改变一个图片高度和宽度

      在css中,可以使用width和height属性来改变一个图片高度和宽度,只需要给图片元素添加“width:宽度值;height:高度值;”样式即可。width...

    热门文章