Rumah  >  Artikel  >  hujung hadapan web  >  Ketahui lebih lanjut tentang alias modul dalam node.js (kongsi beberapa kaedah perangkap)

Ketahui lebih lanjut tentang alias modul dalam node.js (kongsi beberapa kaedah perangkap)

青灯夜游
青灯夜游ke hadapan
2021-12-20 11:05:495415semak imbas

Artikel ini akan membawa anda melalui alias-modul dalam node.js, memperkenalkan prinsip alias-modul, dan masalah biasa (pit) alias-modul saya harap ia akan membantu semua orang!

Ketahui lebih lanjut tentang alias modul dalam node.js (kongsi beberapa kaedah perangkap)

Pertama sekali, adalah perlu untuk memperkenalkan apa itu module-alias Ini adalah pautan laman web rasminya (alamat laman web rasmi https://github.com/ilearnio/. alias modul).

Ringkasnya, module-alias menyediakan fungsi alias laluan dalam persekitaran node. Pembangun bahagian hadapan umum mungkin biasa dengan konfigurasi webpack alias, konfigurasi typescript paths, dll. Ini semua menyediakan fungsi alias tentera. Alias ​​laluan ialah yyds semasa pembangunan kod, jika tidak, anda pasti akan menjadi gila apabila anda melihat laluan ../../../../xx ini.

Projek yang dibungkus menggunakan webpackwebpack itu sendiri akan mengendalikan proses penukaran daripada konfigurasi alias laluan dalam kod sumber kepada kod berpakej Walau bagaimanapun, jika projek itu hanya disusun menggunakan typescript, walaupun typescript Konfigurasi alias laluan dalam paths boleh diproses secara normal semasa proses penyusunan, tetapi tidak akan menukar kod berpakej, menyebabkan konfigurasi alias laluan masih wujud dalam kod berpakej. Lihat proses typescriptKod tersusun:

"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);

Berikut ialah kandungan konfigurasi tsconfig.json

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

Anda boleh melihat bahawa simbol @ masih wujud dalam kod yang disusun oleh typescript , bagaimanapun, apabila kod sedang berjalan, contohnya, jika ia dibenarkan dalam node, require tidak dapat mengecam simbol ini dengan betul dalam laluan, menyebabkan modul yang sepadan ditemui dan pengecualian akan dilemparkan .

Ini juga module-alias tujuan perpustakaan ini.

Pengenalan kepada modul-alias

Daripada laman web rasmi, hanya memerlukan dua langkah untuk menggunakan perpustakaan ini, yang sebenarnya sangat mudah.

1. Konfigurasi alias laluan: module-alias Menyokong dua kaedah konfigurasi alias laluan

  • Tambah atribut package.json dalam _moduleAliases untuk konfigurasi

    "_moduleAliases": {
        "@": "./src"
    }
  • Tambah konfigurasi addAliasaddAliasesaddPath

    moduleAlias.addAliases({
      '@'  : __dirname + './src',
    });
    melalui antara muka API yang disediakan
  • ,
,

2. Pada permulaan projek Mula-mula import perpustakaan: require(module-alias/register) Sudah tentu, jika anda memilih untuk menggunakan kaedah API, anda perlu mengimport fungsi yang sepadan untuk pemprosesan

Secara amnya, kami menggunakan laluan alias titik masuk projek package.json yang dikonfigurasikan dalam . Gunakan perpustakaan ini. require(module-alias/register)

Pengenalan kepada prinsip modul-alias

melaksanakan penukaran alias laluan dengan mengatasi kaedah module-alias pada objek global Module, semudah mudah Maksudnya, dengan memintas panggilan kaedah _resolveFilename asli, tukar alias laluan, dan kemudian panggil kaedah _resolveFilename asal selepas mendapatkan laluan sebenar fail. _resolveFilename

Berikut ialah kod sumbernya, yang pada asasnya dibahagikan kepada dua bahagian: laluan alias penukaran asli

panggilan _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)
}
Di sebalik perkara yang kelihatan mudah, selalunya terdapat perangkap .

modul-alias perangkap

Secara amnya kami akan menggunakan perpustakaan

dalam projek node, kerana projek module-alias biasanya bermula daripada node ditukar kepada typescript kod, tetapi ia selalunya tidak dibungkus kerana pembungkusan biasanya tidak diperlukan dalam projek js, yang nampaknya agak berlebihan. Inilah masanya node perlu naik ke atas pentas. module-alias

Tetapi projek ini agak luar biasa Kami menggunakan kaedah organisasi kod berbilang lapisan dalam projek Lapisan paling luar mempunyai

global, dan pakej dalam mempunyai package.jsonnya sendiri secara ringkasnya, kami menggunakan package.json kaedah organisasi kod, monorepo masalah timbul daripada ini.

modul-alias tidak dapat menyelesaikan alias laluan yang dikonfigurasikan dengan betul dalam pakej.json

Pada mulanya saya tidak menjangka ia akan menjadi masalah dengan cara berbilang lapisan projek dianjurkan. tidak akan masuk ke dalam perangkap ini Sila baca arahan dengan teliti lain kali Ya, tetapi dengan manual arahan yang begitu panjang, terdapat kebarangkalian yang tinggi bahawa anda tidak akan membacanya dengan berhati-hati. . . Lagipun, nampaknya tidak akan ada masalah dengan kaedah penggunaan yang begitu mudah

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

Atas ialah kandungan terperinci Ketahui lebih lanjut tentang alias modul dalam node.js (kongsi beberapa kaedah perangkap). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:juejin.cn. Jika ada pelanggaran, sila hubungi admin@php.cn Padam