ホームページ  >  記事  >  ウェブフロントエンド  >  Node.js の module-alias について詳しく学ぶ (いくつかの落とし穴メソッドを共有)

Node.js の module-alias について詳しく学ぶ (いくつかの落とし穴メソッドを共有)

青灯夜游
青灯夜游転載
2021-12-20 11:05:495410ブラウズ

この記事では、node.js のモジュール エイリアスを理解し、モジュール エイリアスの原理と、モジュール エイリアスの一般的な問題 (落とし穴) を紹介します。みんなに!

Node.js の module-alias について詳しく学ぶ (いくつかの落とし穴メソッドを共有)

まず、module-alias とは何かということを紹介する必要がありますが、その公式 Web サイトのリンクは次のとおりです (公式 Web サイトのアドレス https:// github.com/ilearnio/ module-alias)。

簡単に言うと、module-aliasnode 環境でのパス エイリアス機能を提供します。一般に、フロントエンド開発者は、webpackalias 構成、typescriptpaths 構成などに精通している可能性があります。これらはすべて、軍隊を提供します。エイリアス、関数。コード開発プロセス中のパスのエイリアスは yyds です。そうしないと、この ../../../../xx パスを見たときに間違いなく発狂するでしょう。

webpack

webpack を使用してパッケージ化されたプロジェクト自体は、ソース コード内のパス エイリアスの設定からパッケージ化されたコードへの変換プロセスを処理しますが、単純に使用する場合は、 typescript コンパイルされたプロジェクト。 typescript は通常、コンパイル プロセス中に paths 内のパス エイリアスの構成を処理できますが、パッケージ化されたコードは 変更されません。原因 パッケージ化されたコードにはパス エイリアス設定 がまだ残っています。typescript によってコンパイルされたコードを見てください: <pre class="brush:php;toolbar:false">&quot;use strict&quot;; Object.defineProperty(exports, &quot;__esModule&quot;, { value: true }); require(&quot;./module-alias-register&quot;); var commands_1 = require(&quot;@/commands&quot;); var package_json_1 = require(&quot;../package.json&quot;); (0, commands_1.run)(package_json_1.version);</pre>これが

tsconfig.json## の設定です# コンテンツ

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

によってコンパイルされたコードでは、@ 記号がまだ存在していることがわかりますが、コードの実行中など、

では @ 記号が許可されています。 noderequire はパス内のこのシンボルを正しく認識できないため、対応するモジュールが見つかり、例外がスローされます。 これは module-alias

の目的でもあります。

module-aliasの紹介

公式サイトによると、このライブラリの利用方法はたったの2ステップで、実に非常に簡単です。

1. パス エイリアス設定:

module-alias

2 つのパス エイリアス設定メソッドをサポートします

package.json

  • 追加

    _moduleAliases 属性を使用して、提供された API インターフェイス addAliasaddAliases

  • addPath # を通じて
  • "_moduleAliases": {
        "@": "./src"
    }

    を構成します##、構成を追加します <pre class="brush:js;toolbar:false;">moduleAlias.addAliases({ &amp;#39;@&amp;#39; : __dirname + &amp;#39;./src&amp;#39;, });</pre>2。プロジェクトの開始時に最初にライブラリをインポートします:

    require(module-alias/register)
  • 、もちろん使用することを選択しますAPI メソッドは、処理のために対応する関数をインポートする必要があります

通常、パス エイリアス プロジェクト エントリを構成するには package.json を使用します

require(module-alias/register)

Toこのライブラリを使用してください。 module-alias の原理の概要

module-aliasグローバル オブジェクトのメソッドをオーバーライドすることによって

Module

_resolveFilename はパス エイリアスの変換を実現します。簡単に言うと、ネイティブの _resolveFilename メソッド呼び出しをインターセプトし、パス エイリアスを変換します。ファイルの実際のパスが取得されると、元の _resolveFilename メソッドが呼び出されます。 以下はそのソース コードで、基本的に 2 つの部分に分かれています: パス エイリアス変換ネイティブ _resolveFilenamecall

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] === &#39;function&#39;) {
        var fromPath = parentModule.filename
        aliasTarget = moduleAliases[alias](fromPath, request, alias)
        if (!aliasTarget || typeof aliasTarget !== &#39;string&#39;) {
          throw new Error(&#39;[module-alias] Expecting custom handler function to return path.&#39;)
        }
      }
      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 コードに変換されますが、パッケージ化されないことがよくあります。通常、プロジェクトにパッケージ化する必要はありませんが、少し冗長に思えます。このとき、module-alias が役に立ちます。 しかし、このプロジェクトは少し特殊です。プロジェクトでは多層コード編成方法を使用しています。最も外側の層にはグローバル package.json があり、内部パッケージには独自の package.json は、簡単に言えば、monorepo コード編成メソッドを使用しており、

問題はここから発生します

module-alias は package.json で構成されたパス エイリアスを適切に解決できませんこれが多層プロジェクトの編成方法に問題があるとは予想していませんでした公式 Web サイト module-alias/register に使用方法の説明があります:

しかし、実際には支払いませんでした当時この説明に注意していれば、この罠にはまらなかったでしょう。次回からは説明書をよく読む必要がありますが、これほど長い説明書では、それほど注意深く読まない可能性が高くなります。 。 。やっぱり、こんな簡単な使い方で問題なさそうですよね

module-alias/register流程

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

function init (options) {
  // 省略了部分内容
  var candidatePackagePaths
  if (options.base) {
    candidatePackagePaths = [nodePath.resolve(options.base.replace(/\/package\.json$/, &#39;&#39;))]
  } 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&#39; current working directory (when
    // running a package manager script, e.g. `yarn start` / `npm run start`)
    // 重点看这里!!!
    candidatePackagePaths = [nodePath.join(__dirname, &#39;../..&#39;), process.cwd()]
  }
  var npmPackage, base
  for (var i in candidatePackagePaths) {
    try {
      base = candidatePackagePaths[i]
      npmPackage = require(nodePath.join(base, &#39;package.json&#39;))
      break
    } catch (e) { // noop }
  }
  // 省略了部分内容
  var aliases = npmPackage._moduleAliases || {}
  for (var alias in aliases) {
    if (aliases[alias][0] !== &#39;/&#39;) {
      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 について詳しく学ぶ (いくつかの落とし穴メソッドを共有)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。