您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“node.js中的module-alias怎么用”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“node.js中的module-alias怎么用”這篇文章吧。
首先有必要介紹一下module-alias
是什么,這里有其官網(wǎng)鏈接(官網(wǎng)地址 https://github.com/ilearnio/module-alias)。
簡單點(diǎn)說,module-alias
提供了在node
環(huán)境下的路徑別名功能。一般前端開發(fā)可能會(huì)比較熟悉webpack
的alias
配置、typescript
的paths
配置等,這些都是提供了陸軍別名的功能。路徑別名在代碼開發(fā)過程中是yyds,不然你看到這種../../../../xx
路徑時(shí),是肯定會(huì)抓狂的。
使用webpack
打包的項(xiàng)目webpack
本身會(huì)處理源代碼中路徑別名的配置到打包后代碼的轉(zhuǎn)換過程,但是如果單純使用typescript
進(jìn)行編譯的項(xiàng)目,雖然typescript
在編譯過程中可以正常處理paths
中路徑別名的配置,但是并不會(huì)改變打包后的代碼,造成在打包后的代碼中仍然存在路徑別名配置,看一個(gè)經(jīng)過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
的配置內(nèi)容
"paths": { "@/*": [ "src/*" ] }
可以看到在經(jīng)過typescript
編譯后的代碼中,仍然存在@符號(hào),然而當(dāng)代碼運(yùn)行的過程中,比如允許在node
中,require
并不能正常識(shí)別路徑里的這個(gè)符號(hào),導(dǎo)致找不到相應(yīng)模塊而拋出異常。
這也是module-alias
這個(gè)庫存在的目的。
從官網(wǎng)上看,這個(gè)庫使用方法只需要兩步,真的已經(jīng)是極簡狀態(tài)了。
1、路徑別名配置:module-alias
支持兩種路徑別名配置方式
在package.json
中增加_moduleAliases
屬性進(jìn)行配置
"_moduleAliases": { "@": "./src" }
通過提供的API接口addAlias
、addAliases
、addPath
,增加配置
moduleAlias.addAliases({ '@' : __dirname + './src', });
2、在項(xiàng)目啟動(dòng)時(shí)首先導(dǎo)入該庫:require(module-alias/register)
即可,當(dāng)然選擇使用API方式的需要導(dǎo)入對(duì)應(yīng)的函數(shù)進(jìn)行處理
一般我們都是使用package.json
中配置路徑別名 + 項(xiàng)目入口處require(module-alias/register)
來使用這個(gè)庫。
module-alias
通過覆寫了全局對(duì)象Module
上的方法_resolveFilename
來實(shí)現(xiàn)路徑別名的轉(zhuǎn)換,簡單來說就是通過攔截原生的_resolveFilename
方法調(diào)用,進(jìn)行路徑別名的轉(zhuǎn)換,當(dāng)獲取到文件的真實(shí)路徑后,再調(diào)用原聲的_resolveFilename
方法。
下面是其源代碼,基本上分為兩部分:路徑別名轉(zhuǎn)換+原生_resolveFilename
調(diào)用
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) }
看似簡單的背后,往往也會(huì)踩坑
一般我們會(huì)在node
項(xiàng)目中使用module-alias
庫,因?yàn)?code>node項(xiàng)目一般會(huì)從typescript
轉(zhuǎn)換成js
代碼,但是往往并不會(huì)進(jìn)行打包處理,因?yàn)?code>node項(xiàng)目中一般也確實(shí)不需要打包,顯得有些冗余。這時(shí)候就需要module-alias
上場了。
但是這個(gè)項(xiàng)目有點(diǎn)不一般,我們在項(xiàng)目中使用了多層代碼組織方式,最外層有全局的package.json
, 內(nèi)層包有自己的package.json
, 簡單說是使用了monorepo
的代碼組織方式,問題也就是由此而來。
module-alias無法正常解析在package.json中配置的路徑別名
剛開始確實(shí)沒想到是多層項(xiàng)目組織方式的問題,官網(wǎng)對(duì)module-alias/register
使用有一段說明:
但是當(dāng)時(shí)確實(shí)也是沒有注意到這塊說明,要不然也不會(huì)踩這個(gè)坑了,下次看使用說明要仔細(xì)了,不過這么長的使用說明,大概率還是不會(huì)看的這么仔細(xì)。。。畢竟看起來這么簡單的使用方法,好像似乎是不會(huì)出什么問題的吧
既然踩坑了,就有必要了解一下踩坑的原因,避免反復(fù)踩坑才好??梢栽敿?xì)了解下module-alias
中init
方法的實(shí)現(xiàn)。為了節(jié)省篇幅,省略了部分細(xì)節(jié)
function init (options) { // 省略了部分內(nèi)容 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`) // 重點(diǎn)看這里?。。? 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 } } // 省略了部分內(nèi)容 var aliases = npmPackage._moduleAliases || {} for (var alias in aliases) { if (aliases[alias][0] !== '/') { aliases[alias] = nodePath.join(base, aliases[alias]) } } // 省略了部分內(nèi)容 }
可以看重點(diǎn)部分,如果我們沒有給base參數(shù),module-alias
默認(rèn)會(huì)從../../
目錄和當(dāng)前目錄下找尋package.json
文件,而且../..
目錄下的package.json
文件的優(yōu)先級(jí)比當(dāng)前目錄下的優(yōu)先級(jí)還要高,這里的優(yōu)先級(jí)設(shè)置似乎和正常的優(yōu)先級(jí)邏輯有點(diǎn)差別,一般都會(huì)讓當(dāng)前目錄的優(yōu)先級(jí)比較高才比較符合正常邏輯,所以會(huì)導(dǎo)致加載的不是當(dāng)前目錄下的package.json
文件,而導(dǎo)致找不到路徑別名配置而出錯(cuò)。
關(guān)于這點(diǎn)似乎有不少人踩坑了,還有人提了issues,但是似乎暫時(shí)并沒有人回應(yīng)。
通過API方式注冊路徑別名,或者手動(dòng)調(diào)用init
方法,傳入base參數(shù),指定package.json
文件.
以上是“node.js中的module-alias怎么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。