नोड में.जेएस मैं आवश्यकता के माध्यम से लोड किए गए मॉड्यूल का रास्ता कैसे प्राप्त कर सकता हूं जो कि * नहीं * मेरा है (यानी कुछ नोड_मॉडल में)


94

मुझे एक मॉड्यूल की आवश्यकता है जो npm के माध्यम से स्थापित किया गया था। मैं उस मॉड्यूल में एक .js फ़ाइल अधीनस्थ का उपयोग करना चाहता हूं (इसलिए मैं इसमें एक कंस्ट्रक्टर विधि को उप-वर्ग कर सकता हूं)। मैं मॉड्यूल का कोड संशोधित नहीं कर सकता (ठीक है, नहीं करना चाहता), इसलिए इसका __dirname निकालने की जगह नहीं है।

मैं निम्नलिखित प्रश्न से अवगत हूं, लेकिन यह एक मॉड्यूल के पथ को प्राप्त करने के बारे में है, जिस पर किसी का कोड नियंत्रण है (इसलिए, __dirname समाधान है): Node.js में मैं `this` मॉड्यूल का पथ कैसे बता सकता हूं?

~~~

इससे भी बेहतर होगा कि मॉड्यूल की भरी हुई मॉड्यूल जानकारी प्राप्त करें


जहाँ आप आवश्यकता ('modulename') के साथ मॉड्यूल को बिना किसी त्रुटि के लोड कर सकते हैं?
फितूर

क्या आप इसे बेहतर तरीके से समझा सकते हैं? कुछ कोड?
गेब्रियल ललमास

जवाबों:


130

यदि मैं आपके प्रश्न को सही ढंग से समझता हूं, तो आपको आवश्यकता का उपयोग करना चाहिए। हल () :

एक मॉड्यूल के स्थान को देखने के लिए आंतरिक आवश्यकता () मशीनरी का उपयोग करें, लेकिन मॉड्यूल लोड करने के बजाय, बस हल किए गए फ़ाइलनाम को वापस लौटाएं।

उदाहरण: var pathToModule = require.resolve('module');


13
यह उत्तर सभी नोड मॉड्यूल के साथ मज़बूती से काम नहीं करता है। मेरा जवाब देखिए।
जेसन

61

आवश्यकता है । हल () एक आंशिक उत्तर है। स्वीकृत उत्तर कई नोड मॉड्यूल के लिए काम कर सकता है, लेकिन उन सभी के लिए काम नहीं करेगा।

require.resolve("moduleName")आपको वह निर्देशिका नहीं देता जहाँ मॉड्यूल स्थापित है; यह आपको mainमॉड्यूल में विशेषता में परिभाषित फ़ाइल का स्थान देता है package.json

यह हो सकता है moduleName/index.jsया यह हो सकता है moduleName/lib/moduleName.js। बाद के मामले में, path.dirname(require.resolve("moduleName"))एक ऐसी निर्देशिका वापस कर देंगे जिसे आप नहीं चाहते या अपेक्षा कर सकते हैं:node_modules/moduleName/lib

एक विशिष्ट मॉड्यूल के लिए पूरा रास्ता पाने का सही तरीका फ़ाइल नाम को हल करके है:

let readmePath = require.resolve("moduleName/README.md");

यदि आप केवल मॉड्यूल के लिए निर्देशिका चाहते हैं (हो सकता है कि आप बहुत अधिक path.join()कॉल करने जा रहे हों ), तो हल करें package.json- जो हमेशा परियोजना की जड़ में होना चाहिए - और पास करें path.dirname():

let packagePath = path.dirname(require.resolve("moduleName/package.json"));

1
बहुत चतुर उत्तर, package.jsonफ़ाइल का पता लगाकर । क्या आपको path.join('moduleName', 'package.json')Windows के संगत होने के लिए उपयोग नहीं करना चाहिए ?
जोहो पिमेंटेल फरेरा

2
@ JoãoPimentelFerreira require.resolveमंच अज्ञेयवादी है, ठीक उसी तरह जैसे requireकि इसका उपयोग करने की आवश्यकता नहीं हैpath.join
गोपीकृष्ण S

1
const path = require('path');उपयोग करने से पहले जोड़ना मत भूलना path.dirname
गोटो 0

काश यह जवाब पूरी तरह से सच होता! मैं सफलतापूर्वक कुछ ऐसा हल कर सकता हूं, require.resolve('@scope/module')जिससे मुझे कुछ पसंद /path/to/@scope/module/dist/index.jsआए, हालांकि अगर मैं require.resolve('@scope/module/package.json')इसे चलाने की कोशिश करता हूं तो यह एक MODULE_NOT_FOUNDत्रुटि है। मैं नोड 14.4.0 में हूं, और जिस मॉड्यूल को मैं हल करने की कोशिश कर रहा हूं, वह "type": "module"अपने पैकेज exportsमें है package.json। इसे किसी ऐसे क्षेत्र के साथ शामिल करें जिसमें शामिल नहीं है । यकीन नहीं होता कि इसके साथ कुछ करना है ...
trusktr

मुझे समस्या मिली: जब एक मॉड्यूल होता है type: module, तो स्पष्ट package.jsonरूप से exportsक्षेत्र में स्पष्ट रूप से उजागर करना पड़ता है । मैंने सोचा था कि नोड की नई ईएसएम सुविधा requireहमेशा की तरह पथ को हल करने से अवरुद्ध नहीं हुई , लेकिन यह स्पष्ट है।
trusktr

3

FYI करें, require.resolveकॉमनजेएस के अनुसार मॉड्यूल पहचानकर्ता को लौटाता है। नोड.जेएस में यह फ़ाइल नाम है। में webpack इस एक संख्या है।

में webpack स्थिति, यहाँ मेरी समाधान मॉड्यूल पथ पता लगाने के लिए है:

const pathToModule = require.resolve('module/to/require');
console.log('pathToModule is', pathToModule); // a number, eg. 8
console.log('__webpack_modules__[pathToModule] is', __webpack_modules__[pathToModule]);

फिर __webpack_modules__[pathToModule]मुझे इस तरह से जानकारी मिली:

(function(module, exports, __webpack_require__) {

    eval("module.exports = (__webpack_require__(6))(85);\n\n//////////////////\n// 
    WEBPACK FOOTER\n// delegated ./node_modules/echarts/lib/echarts.js from dll-reference vendor_da75d351571a5de37e2e\n// module id = 8\n// module chunks = 0\n\n//# sourceURL=webpack:///delegated_./node_modules/echarts/lib/echarts.js_from_dll-reference_vendor_da75d351571a5de37e2e?");

    /***/
})

यह पता चला कि मुझे पिछली dll बिल्ड फ़ाइल (तेज़ बिल्ड स्पीड के लिए) से पुरानी स्क्रिप्ट की आवश्यकता थी, ताकि मेरी अपडेट की गई मॉड्यूल फ़ाइल मेरी अपेक्षा के अनुरूप काम न करे। अंत में मैंने अपनी dll फ़ाइल को फिर से बनाया और मेरी समस्या का समाधान किया।

Ref: हल फ़ाइल पथ (नोड) पाने के लिए उपयोग करनाrequire.resolve


2

मुझे आशा है कि मैं आपकी आवश्यकताओं को सही ढंग से समझता हूं: कुछ मॉड्यूल की प्रविष्टि बिंदु फ़ाइल प्राप्त करने के लिए। मान लें कि आप jugglingdbमॉड्यूल का प्रवेश बिंदु प्राप्त करना चाहते हैं :

node
> require('module')._resolveFilename('jugglingdb')
'/usr/local/lib/node_modules/jugglingdb/index.js'

जैसा कि आप देख सकते हैं कि मॉड्यूल के बारे में इस तरह की जानकारी प्राप्त करने के लिए यह "आधिकारिक" तरीका नहीं है, इसलिए इस फ़ंक्शन का व्यवहार संस्करण से संस्करण में बदल सकता है। मैंने इसे नोड स्रोत में पाया है: https://github.com/joyent/node/blob/master/lib/module.js#L280


2

@Anatoliy समाधान के अनुसार, MacOS XI में लुकअप रास्तों को करते पाया गया है

require('module')._resolveLookupPaths('myModule')

इसलिए मुझे हल किए हुए लुकअप रास्ते मिलते हैं

[ 'myModule',
  [ '/Users/admin/.node_modules',
    '/Users/admin/.node_libraries',
    '/usr/local/lib/node' ] ]

जहांकि

require('module')._resolveFilename('myModule')

मैं वैसे भी जिस मॉड्यूल की तलाश में था, उसे हल नहीं करूंगा, वास्तव में पागल बात यह है कि _loadमॉड्यूल को हल नहीं करेगा:

> require('module')._load('myModule')
Error: Cannot find module 'myModule'
    at Function.Module._resolveFilename (module.js:440:15)
    at Function.Module._load (module.js:388:25)
    at repl:1:19
    at sigintHandlersWrap (vm.js:32:31)
    at sigintHandlersWrap (vm.js:96:12)
    at ContextifyScript.Script.runInContext (vm.js:31:12)
    at REPLServer.defaultEval (repl.js:308:29)
    at bound (domain.js:280:14)
    at REPLServer.runBound [as eval] (domain.js:293:12)
    at REPLServer.<anonymous> (repl.js:489:10)

requireवसीयत करते समय :

> require('myModule')

लेकिन मेरे पास यह मॉड्यूल नहीं है

myProject/node_modules/
myProject/node_modules/@scope/
/usr/local/lib/node_modules/
/usr/local/lib/node_modules/@scope
/usr/local/lib/node_modules/npm/node_modules/
/usr/local/lib/node_modules/npm/node_modules/@scope
$HOME/.npm/
$HOME/.npm/@scope/

तो यह मॉड्यूल कहाँ है ???

पहले मुझे एक $ sudo /usr/libexec/locate.updatedb कॉफ़ी करनी थी उसके बाद कुछ कॉफ़ी मैंने की locate myModuleया बेहतर कीlocate myModule/someFile.js

et voilà, यह पता चलता है कि यह मेरी परियोजना के मूल फ़ोल्डर में था अर्थात मेरे प्रोजेक्ट रूट फ़ोल्डर के बाहर:

$pwd
/Users/admin/Projects/Node/myProject
$ ls ../../node_modules/myModule/

तो आप rm -rf ../../node_modules/myModule/एक ताजा और से बचने नहीं कर सकते npm install

मैं तर्क दे सकता हूं कि किसी ने npmभी मेरे प्रोजेक्ट रूट फ़ोल्डर की तुलना में अन्य जगहों पर मॉड्यूल की तलाश में मेरे कंप्यूटर को स्कैन करने का निर्देश नहीं दिया था जहां उसे चलाने या डिफ़ॉल्ट मॉड्यूल खोज पथ में होना चाहिए था।


1

यह वह चीज है जो आप खोज रहे हैं, जांचें:

require.main.filename


1

जेसन का जवाब सबसे अच्छा जवाब था, जब तक कि Node.js ESM और exportsफील्ड सामने नहीं आया।

अब जब नोड एक exportsफ़ील्ड के साथ पैकेजों का समर्थन करता है जो डिफ़ॉल्ट रूप से फ़ाइलों package.jsonको रिज़ोल्वेबल होने से रोकेगा जब तक कि पैकेज लेखक स्पष्ट रूप से उन्हें उजागर करने का निर्णय नहीं लेता है, जेसन के उत्तर में चाल उन पैकेजों के लिए विफल हो जाएगी जो स्पष्ट रूप से उजागर नहीं करते हैं package.json

एक पैकेज resolve-package-pathहोता है जिसे ट्रिक कहते हैं।

इसका उपयोग कैसे करें:

const resolvePkg = require('resolve-package-path')

console.log(resolvePkg('@some/package'))

जो कुछ आउटपुट देगा

/path/to/@some/package/package.json

पैकेज के exportsक्षेत्र में क्या है, इसकी परवाह किए बिना ।


मुझे संदेह है कि एक बार एक लेखक जानबूझकर मॉड्यूल की सामग्री का हिस्सा निर्यात कर रहा है, आप शकीर मैदान पर भी हैं, क्योंकि अब लेखक ने औपचारिक रूप से अपने सार्वजनिक इंटरफ़ेस को परिभाषित किया है। मुझे लगता है कि, उन चीजों के अधिक आक्रामक रूप से परिणामी होने की प्रवृत्ति है, जो स्पष्ट रूप से निर्यात नहीं होती हैं, क्या ऐसा नहीं होगा?
जेसन

@ जेसन स्रोत फ़ाइलों के लिए सही है, लेकिन package.json फ़ाइलें दूर नहीं जा रही हैं। मुझे ऐसा कोई कारण नहीं दिख रहा है जिसे आयात से छिपाया जाना चाहिए।
trusktr
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.