ホームページ > 記事 > ウェブフロントエンド > Node.js の module-alias について詳しく学ぶ (いくつかの落とし穴メソッドを共有)
この記事では、node.js のモジュール エイリアスを理解し、モジュール エイリアスの原理と、モジュール エイリアスの一般的な問題 (落とし穴) を紹介します。みんなに!
まず、module-alias
とは何かということを紹介する必要がありますが、その公式 Web サイトのリンクは次のとおりです (公式 Web サイトのアドレス https:// github.com/ilearnio/ module-alias)。
簡単に言うと、module-alias
は node
環境でのパス エイリアス機能を提供します。一般に、フロントエンド開発者は、webpack
の alias
構成、typescript
の paths
構成などに精通している可能性があります。これらはすべて、軍隊を提供します。エイリアス、関数。コード開発プロセス中のパスのエイリアスは yyds です。そうしないと、この ../../../../xx
パスを見たときに間違いなく発狂するでしょう。
webpack
を使用してパッケージ化されたプロジェクト自体は、ソース コード内のパス エイリアスの設定からパッケージ化されたコードへの変換プロセスを処理しますが、単純に使用する場合は、 typescript
コンパイルされたプロジェクト。 typescript
は通常、コンパイル プロセス中に paths
内のパス エイリアスの構成を処理できますが、パッケージ化されたコードは 変更されません。原因 パッケージ化されたコードにはパス エイリアス設定
がまだ残っています。typescript によってコンパイルされたコードを見てください: <pre class="brush:php;toolbar:false">"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);</pre>
これが
"paths": { "@/*": [ "src/*" ] }
typescript によってコンパイルされたコードでは、@ 記号がまだ存在していることがわかりますが、コードの実行中など、 では @ 記号が許可されています。 node 、
require はパス内のこのシンボルを正しく認識できないため、対応するモジュールが見つかり、例外がスローされます。
これは
module-alias
module-aliasの紹介
module-alias
2 つのパス エイリアス設定メソッドをサポートしますpackage.json の
_moduleAliases 属性を使用して、提供された API インターフェイス
addAlias、
addAliases
"_moduleAliases": { "@": "./src" }
を構成します##、構成を追加します
<pre class="brush:js;toolbar:false;">moduleAlias.addAliases({
&#39;@&#39; : __dirname + &#39;./src&#39;,
});</pre>
2。プロジェクトの開始時に最初にライブラリをインポートします:
通常、パス エイリアス プロジェクト エントリを構成するには package.json
を使用します
Toこのライブラリを使用してください。 module-alias の原理の概要
_resolveFilename
はパス エイリアスの変換を実現します。簡単に言うと、ネイティブの _resolveFilename
メソッド呼び出しをインターセプトし、パス エイリアスを変換します。ファイルの実際のパスが取得されると、元の _resolveFilename
メソッドが呼び出されます。 以下はそのソース コードで、基本的に 2 つの部分に分かれています: パス エイリアス変換ネイティブ
_resolveFilename
call
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 ピット上にステップ
プロジェクトは通常、typescript
から js
コードに変換されますが、パッケージ化されないことがよくあります。通常、プロジェクトにパッケージ化する必要はありませんが、少し冗長に思えます。このとき、module-alias
が役に立ちます。 しかし、このプロジェクトは少し特殊です。プロジェクトでは多層コード編成方法を使用しています。最も外側の層にはグローバル
package.json
があり、内部パッケージには独自の package.json
は、簡単に言えば、monorepo
コード編成メソッドを使用しており、
。 module-alias は package.json で構成されたパス エイリアスを適切に解決できません
これが多層プロジェクトの編成方法に問題があるとは予想していませんでした公式 Web サイト module-alias/register に使用方法の説明があります:
しかし、実際には支払いませんでした当時この説明に注意していれば、この罠にはまらなかったでしょう。次回からは説明書をよく読む必要がありますが、これほど長い説明書では、それほど注意深く読まない可能性が高くなります。 。 。やっぱり、こんな簡単な使い方で問題なさそうですよね
既然踩坑了,就有必要了解一下踩坑的原因,避免反复踩坑才好。可以详细了解下module-alias
中init
方法的实现。为了节省篇幅,省略了部分细节
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 について詳しく学ぶ (いくつかの落とし穴メソッドを共有)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。