node.js এর () ক্যাশে প্রয়োজন - অবৈধ করা সম্ভব?


325

নোড.জেএস ডকুমেন্টেশন থেকে:

মডিউলগুলি প্রথমবার লোড হওয়ার পরে তা ক্যাশে করা হয়। এর অর্থ (অন্যান্য জিনিসগুলির মধ্যে) যা প্রতিটি কল ('foo') প্রয়োজন হয় ঠিক একই জিনিসটি ফিরে আসবে, যদি এটি একই ফাইলটিতে সমাধান হয়।

এই ক্যাশেটি অবৈধ করার কোনও উপায় আছে কি? অর্থাত্ ইউনিট পরীক্ষার জন্য, আমি প্রতিটি পরীক্ষায় একটি তাজা বস্তুতে কাজ করা চাই।


8
এনপিএম মডিউল github.com/gajus/require-new
গাজুস

একজন প্রহরী সহ আরও একটি এনপিএম মডিউল: npmjs.com/package/updated-require
জর্জি ফুয়েন্তেস গঞ্জালেজ

এটি বিভিন্ন সুযোগ জন্য প্রয়োজন ব্যবহার না করেই ফাইল বিষয়বস্তু ক্যাশে এবং এটি Eval সম্ভব stackoverflow.com/questions/42376161/...
lonewarrior556

উত্তর:


304

বিজ্ঞপ্তি নির্ভরতা থাকা সত্ত্বেও আপনি কোনও সমস্যা ছাড়াই প্রয়োজনীয় কোডে একটি প্রবেশটি সর্বদা নিরাপদে মুছতে পারেন। কারণ আপনি যখন মুছবেন, আপনি কেবল ক্যাশেড মডিউল অবজেক্টের একটি রেফারেন্স মুছবেন, মডিউল অবজেক্টটি নিজেই নয়, মডিউল অবজেক্টটি GCed হবে না কারণ বিজ্ঞপ্তি নির্ভরতাগুলির ক্ষেত্রে এখনও এই মডিউল অবজেক্টটিকে রেফারেন্স করে কোনও অবজেক্ট রয়েছে।

মনে করুন আপনার কাছে রয়েছে:

লিপি a.js:

var b=require('./b.js').b;
exports.a='a from a.js';
exports.b=b;

এবং স্ক্রিপ্ট বি.জেএস:

var a=require('./a.js').a;
exports.b='b from b.js';
exports.a=a;

যখন তুমি কর:

var a=require('./a.js')
var b=require('./b.js')

তুমি পাবে:

> a
{ a: 'a from a.js', b: 'b from b.js' }
> b
{ b: 'b from b.js', a: undefined }

এখন আপনি যদি আপনার বি.জেএস সম্পাদনা করেন:

var a=require('./a.js').a;
exports.b='b from b.js. changed value';
exports.a=a;

এবং কর:

delete require.cache[require.resolve('./b.js')]
b=require('./b.js')

তুমি পাবে:

> a
{ a: 'a from a.js', b: 'b from b.js' }
> b
{ b: 'b from b.js. changed value',
  a: 'a from a.js' }

===

উপরেরগুলি সরাসরি নোড.জেএস চলমান থাকলে বৈধ is যাইহোক, যেমন টুলস তাদের নিজস্ব মডিউল ক্যাশে সিস্টেমের আছে, ব্যবহার করা হয় তবে বিদ্রূপের বিষয় রূপে গ্রহণ , সঠিক বিবৃতি হবে:

jest.resetModules();

2
আপনি দয়া করে ব্যাখ্যা করতে পারেন কেন প্রথমবারের জন্য { ... a: undefined}প্রয়োজন হয় b.js? আমি সমান আশা করি 'a from a.js'। আপনাকে ধন্যবাদ
ইরা

1
একটি অপরিজ্ঞাত কেন?
জেফ পি চকো

4
দেরীতে জবাব, তবে আমি যা জড়ো করি তা থেকে b[a]প্রথমবারের সাথে একটি বৃত্তাকার নির্ভরতা নির্ধারিত হয়। ঘুরে ফিরে a.jsপ্রয়োজন b.jsযা প্রয়োজন a.jsa.jsএখনও পুরোপুরি লোড exports.aকরা হয়নি এবং এখনও সংজ্ঞায়িত করা হয়নি, তাই b.jsকিছুই হয় না।
নিক 10110

আমি require.main.require(path)এখানে বর্ণিত হিসাবে ব্যবহার করে যদি এটি করার কোন উপায় ? stackoverflow.com/questions/10860244/...
Flion

186

আপনি যদি সর্বদা আপনার মডিউলটি পুনরায় লোড করতে চান তবে আপনি এই ফাংশনটি যুক্ত করতে পারেন:

function requireUncached(module) {
    delete require.cache[require.resolve(module)];
    return require(module);
}

এবং তারপরে requireUncached('./myModule')প্রয়োজনের পরিবর্তে ব্যবহার করুন।


6
এটি fs.watchফাইলের পরিবর্তনের জন্য শোনার পদ্ধতিটির সাথে একত্রে উপযুক্ত ।
ph3nx

2
ঝুঁকি কি?
স্কারাস

আমার একই প্রশ্ন, এই সমাধানটি ব্যবহার করার ঝুঁকি কী এবং গ্রহণযোগ্য উত্তর নয়?
রোটিমি-সেরা

1
এটা আসলে একই। কোডটি কীভাবে কাঠামোবদ্ধ করা হয়েছে তার উপর নির্ভর করে আপনি আবার এটিকে আরম্ভ করার চেষ্টা করার সময় জিনিসগুলি ক্র্যাশ হতে পারে। যাত্রা। যদি মডিউলটি কোনও সার্ভার শুরু করে এবং একটি পোর্ট শোনায়। পরের বার আপনি মডিউলটি সংযুক্ত করার পরে, এটি পোর্টটি ইতিমধ্যে খোলা হওয়ার পরে এটি ব্যর্থ হবে and
লুফ

133

হ্যাঁ, আপনি যে মডিউলটি অ্যাক্সেস করতে চান তার নাম require.cache[moduleName]যেখানে moduleNameরয়েছে তার মাধ্যমে আপনি ক্যাশে অ্যাক্সেস করতে পারবেন। কলিং দ্বারা একটি এন্ট্রি মুছে ফেলা হচ্ছে delete require.cache[moduleName]কারণ হবে requireপ্রকৃত ফাইল লোড করা হয়নি।

এইভাবে আপনি মডিউলটির সাথে সম্পর্কিত সমস্ত ক্যাশেড ফাইলগুলি সরিয়ে ফেলবেন:

/**
 * Removes a module from the cache
 */
function purgeCache(moduleName) {
    // Traverse the cache looking for the files
    // loaded by the specified module name
    searchCache(moduleName, function (mod) {
        delete require.cache[mod.id];
    });

    // Remove cached paths to the module.
    // Thanks to @bentael for pointing this out.
    Object.keys(module.constructor._pathCache).forEach(function(cacheKey) {
        if (cacheKey.indexOf(moduleName)>0) {
            delete module.constructor._pathCache[cacheKey];
        }
    });
};

/**
 * Traverses the cache to search for all the cached
 * files of the specified module name
 */
function searchCache(moduleName, callback) {
    // Resolve the module identified by the specified name
    var mod = require.resolve(moduleName);

    // Check if the module has been resolved and found within
    // the cache
    if (mod && ((mod = require.cache[mod]) !== undefined)) {
        // Recursively go over the results
        (function traverse(mod) {
            // Go over each of the module's children and
            // traverse them
            mod.children.forEach(function (child) {
                traverse(child);
            });

            // Call the specified callback providing the
            // found cached module
            callback(mod);
        }(mod));
    }
};

ব্যবহার হবে:

// Load the package
var mypackage = require('./mypackage');

// Purge the package from cache
purgeCache('./mypackage');

যেহেতু এই কোডটি একই সমাধানকারী ব্যবহার requireকরে, তাই আপনার যা প্রয়োজন তা কেবল নির্দিষ্ট করুন।


"ইউনিক্সকে তাদের ব্যবহারকারীদের বোকা কাজ করা থেকে বিরত করার জন্য ডিজাইন করা হয়নি, কারণ এটি চালাক জিনিসগুলি করা থেকেও বিরত রাখতে পারে।" - ডগ গুইন

আমি মনে করি যে সুস্পষ্ট অনাবৃত মডিউল লোড করার জন্য কোনও উপায় হওয়া উচিত ছিল


17
মাত্র ডগের উদ্ধৃতিতে +1। আমি
পোনি

1
দুর্দান্ত উত্তর! আপনি যদি পুনরায় লোডিং সক্ষম করে একটি নোড রেপেল শুরু করতে চান তবে এই টুকরোটিটি দেখুন
gleitz

1
অসাধারণ. আমি এই require.uncacheফাংশন যোগ করতে হবে । `` `// দেখুন github.com/joyent/node/issues/8266 Object.keys (মডিউল.কমস্ট্রাক্টর__প্যাথ ক্যাসে) .এফ (ফাংশন (কে)) {যদি (k.indexOf (মডিউলনাম)> 0) মডিউল.কমস্ট্রাক্টর মুছুন ._পাথচ্যা [কে];}); `` `বলুন যে আপনার একটি মডিউল প্রয়োজন, তারপরে এটি আনইনস্টল করুন, তারপরে একই মডিউলটি পুনরায় ইনস্টল করুন তবে একটি ভিন্ন সংস্করণ ব্যবহার করেছেন যার প্যাকেজটিতে আলাদা মূল স্ক্রিপ্ট রয়েছে, পরবর্তী প্রয়োজনীয়তা ব্যর্থ হবে কারণ মূল স্ক্রিপ্টটি উপস্থিত নেই কারণ এটি ক্যাশেডModule._pathCache
বেনটেল

বিষ্ঠা। আমার মন্তব্য ভয়ানক। আমি এই মন্তব্যে খুব সুন্দরভাবে কোড যুক্ত করতে পারিনি এবং সম্পাদনা করতে খুব দেরি হয়েছে, তাই আমি উত্তর দিয়েছি। @ বেন বারকে যদি আপনি আপনার প্রশ্নটির সামান্য স্নিপেটটি যুক্ত করতে নিজের প্রশ্নটি সম্পাদন করতে পারেন তবেrequire.uncache
বেন্তেল ২

ধন্যবাদ @ বেন্টায়েল, আমি এটি আমার উত্তরে যুক্ত করেছি।
বেন বারকে ২৪

39

এর জন্য একটি সহজ মডিউল রয়েছে ( পরীক্ষার সাথে )

আমাদের কোডটি পরীক্ষা করার সময় আমাদের এই সঠিক সমস্যাটি ছিল ( ক্যাশেড মডিউলগুলি মুছে ফেলা যাতে তারা তাজা অবস্থায় পুনরায় প্রয়োজন হতে পারে ) তাই আমরা বিভিন্ন স্ট্যাকওভারফ্লো প্রশ্নাবলী এবং উত্তরগুলিতে লোকদের সমস্ত পরামর্শ পর্যালোচনা করেছি এবং একটি সাধারণ নোড.জেএস মডিউল রেখেছি ( পরীক্ষার সাথে ):

https://www.npmjs.com/package/ ডেস্ক

যেমনটি আপনি প্রত্যাশা করবেন, প্রকাশিত এনএমপি প্যাকেজ এবং স্থানীয়ভাবে সংজ্ঞায়িত মডিউল উভয়ের জন্যই কাজ করে । উইন্ডোজ, ম্যাক, লিনাক্স ইত্যাদি

স্থিতি তৈরি করুন codecov.io কোড জলবায়ু রক্ষণাবেক্ষণযোগ্যতা নির্ভরতা স্থিতি ডিভিনিডেন্সিগুলি স্থিতি

কিভাবে? ( ব্যবহার )

ব্যবহার বেশ সহজ:

ইনস্টল

এনপিএম থেকে মডিউলটি ইনস্টল করুন:

npm install decache --save-dev

আপনার কোডে এটি ব্যবহার করুন:

// require the decache module:
const decache = require('decache');

// require a module that you wrote"
let mymod = require('./mymodule.js');

// use your module the way you need to:
console.log(mymod.count()); // 0   (the initial state for our counter is zero)
console.log(mymod.incrementRunCount()); // 1

// delete the cached module:
decache('./mymodule.js');

//
mymod = require('./mymodule.js'); // fresh start
console.log(mymod.count()); // 0   (back to initial state ... zero)

আপনার যদি কোনও প্রশ্ন থাকে বা আরও উদাহরণের প্রয়োজন হয় তবে দয়া করে একটি গিটহাব ইস্যু তৈরি করুন: https://github.com/dwyl/decache/issues


1
আমি এটি দেখছিলাম এবং টেস্টিংয়ের সময় এটি ব্যবহার করা আমার পক্ষে সত্যই দুর্দান্ত মনে হচ্ছে যাতে আমি নির্দিষ্ট শর্তে কোনও মডিউল আনলোড এবং পুনরায় লোড করতে পারি, তবে দুর্ভাগ্যক্রমে আমি কাজ করছি এবং আমার সংস্থা জিপিএল লাইসেন্স থেকে দূরে সরে গেছে। আমি এটি কেবল পরীক্ষার জন্য ব্যবহার করতে চাই তাই আমি এখনও এটি বিবেচনা করছি কারণ এটি এতটা সহায়ক বলে মনে হচ্ছে।
ম্যাট_জেডি

আপনার মতামতের জন্য @ ম্যাট_জেডি ধন্যবাদ আপনি কোন লাইসেন্স পছন্দ করবেন?
নেলসনিক

2
@ ম্যাট_জেডি আমরা এমআইটিতে লাইসেন্সটি আপডেট করেছি। আপনার কাজের জন্য শুভকামনা! :-)
নেলসোনিক

1
এই আশ্চর্যজনকভাবে কাজ! এই রেপোকে তারাযুক্ত এবং এই উত্তরটিকে সমর্থন করে v
অহল্ট

1
অত্যন্ত সুপারিশ করুন, আজকের হিসাবে সর্বশেষ v14.2.0 এ জরিমানা চলছে
থোমাজেলা

28

যে কেউ জাস্ট ব্যবহার করছেন এটি জুড়ে আসার জন্য, কারণ জাস্ট তার নিজস্ব মডিউল ক্যাশে করে, এর জন্য একটি বিল্ট-ইন ফাংশন রয়েছে - নিশ্চিত করুন jest.resetModulesরানগুলি যেমন। আপনার প্রতিটি পরীক্ষার পরে:

afterEach( function() {
  jest.resetModules();
});

প্রস্তাবিত অন্য উত্তরের মতো ডেস্ক ব্যবহার করার চেষ্টা করার পরে এটি পাওয়া গেছে। ধন্যবাদ অ্যান্টনি গারওয়ানকে

এখানে ফাংশন ডকুমেন্টেশন ।


1
এই নোটের জন্য আপনাকে অনেক ধন্যবাদ!
mjgpy3

2
godশ্বর এই সন্ধান করার আগে আমি কতক্ষণ পরীক্ষা করেছিলাম .... ধন্যবাদ!
টিয়াগো

16

সমাধানগুলি ব্যবহার করা হয়:

delete require.cache[require.resolve(<path of your script>)]

আমার মতো যারা এই ক্ষেত্রে কিছুটা নতুন রয়েছেন তাদের জন্য এখানে কিছু প্রাথমিক ব্যাখ্যা সন্ধান করুন:

মনে করুন example.jsআপনার ডিরেক্টরিতে মূল একটি ডামি ফাইল রয়েছে:

exports.message = "hi";
exports.say = function () {
  console.log(message);
}

তাহলে আপনি এটি require()পছন্দ করুন:

$ node
> require('./example.js')
{ message: 'hi', say: [Function] }

আপনি যদি এরপরে একটি লাইন যুক্ত করেন তবে example.js:

exports.message = "hi";
exports.say = function () {
  console.log(message);
}

exports.farewell = "bye!";      // this line is added later on

এবং কনসোলে চালিয়ে যান, মডিউলটি আপডেট হয় না:

> require('./example.js')
{ message: 'hi', say: [Function] }

আপনি যখন লফের উত্তরেdelete require.cache[require.resolve()] নির্দেশিত ব্যবহার করতে পারেন তখন :

> delete require.cache[require.resolve('./example.js')]
true
> require('./example.js')
{ message: 'hi', say: [Function], farewell: 'bye!' }

সুতরাং ক্যাশেটি পরিষ্কার হয়ে গেছে এবং require()বর্তমানের সমস্ত মান লোড করে ফাইলটির সামগ্রী আবার ক্যাপচার করে।


আইএমএইচও এটি সবচেয়ে উপযুক্ত উত্তর
পীযূষ কাটারিয়া

5

রিওয়ায়ার এই ব্যবহারের ক্ষেত্রে দুর্দান্ত, আপনি প্রতিটি কলের সাথে একটি নতুন উদাহরণ পান। নোড.জেএস ইউনিট পরীক্ষার জন্য সহজ নির্ভরতা ইনজেকশন।

রিওয়ায়ার মডিউলগুলিতে একটি বিশেষ সেটার এবং গেটর যুক্ত করে যাতে আপনি আরও ভাল ইউনিট পরীক্ষার জন্য তাদের আচরণটি পরিবর্তন করতে পারেন। আপনি পারে

প্রক্রিয়া ফাঁস যেমন মডিউলটির মধ্যে প্রাইভেট ভেরিয়েবল ওভাররাইড ভেরিয়েবলের মতো অন্যান্য মডিউল বা গ্লোবালগুলির জন্য মক্স ইনজেক্ট করুন। রিওয়ায়ারটি ফাইলটি লোড করে না এবং নোডের প্রয়োজনীয় প্রক্রিয়াটি অনুকরণ করতে সামগ্রীর সন্ধান করে না। আসলে এটি মডিউলটি লোড করার জন্য নোডের নিজস্ব প্রয়োজনীয়তা ব্যবহার করে। সুতরাং আপনার মডিউল আপনার পরীক্ষার পরিবেশে নিয়মিত পরিস্থিতিতে (আপনার পরিবর্তনগুলি বাদ দিয়ে) ঠিক ঠিক তেমন আচরণ করে।

সমস্ত ক্যাফেইন-আসক্তদের সুসংবাদ: পুনরায় কফি-স্ক্রিপ্টের সাথেও কাজ করে। মনে রাখবেন যে এক্ষেত্রে কফিস্ক্রিপ্টটি আপনার ডিভডিপেন্ডেন্সে তালিকাভুক্ত করা দরকার।


4

আমি লফের উত্তরে আরও একটি লাইন যুক্ত করব এবং প্যারামিটারের নামটি পরিবর্তন করব:

function requireCached(_module){
    var l = module.children.length;
    for (var i = 0; i < l; i++)
    {
        if (module.children[i].id === require.resolve(_module))
        {
            module.children.splice(i, 1);
            break;
        }
    }
    delete require.cache[require.resolve(_module)];
    return require(_module)
}

সুতরাং এই কাজ submodules মধ্যে কাজ করতে হয়? নিস! মডিউল.চিল্ডেন অ্যারে থেকে মডিউলটি সরিয়ে ফেলার একটি ছোট উপায় হ'ল একটি ফিল্টার ফাংশন ব্যবহার করে: মডিউল.চাইল্ডেন = মডিউল.children.filter (ফাংশন (শিশু) child রিটার্ন চাইল্ড.আইডি! == প্রয়োজনীয়.আরলভ (_মডিউল);}) ;
লুফ

4

হ্যাঁ, আপনি ক্যাশে অবৈধ করতে পারেন।

ক্যাশেটি প্রয়োজনীয় কোড নামে পরিচিত একটি বস্তুতে সংরক্ষণ করা হয় যা আপনি ফাইলের নাম অনুসারে সরাসরি অ্যাক্সেস করতে পারেন (যেমন - আপনি কোনও বিবৃতিতে ব্যবহার করবেন তার /projects/app/home/index.jsবিপরীতে )। ./homerequire('./home')

delete require.cache['/projects/app/home/index.js'];

আমাদের দলটি নীচের মডিউলটি দরকারী বলে খুঁজে পেয়েছে। মডিউলগুলির কয়েকটি গ্রুপকে অবৈধ করতে To

https://www.npmjs.com/package/node-resource


3

আমি একটি উত্তরের মন্তব্যে খুব সুন্দরভাবে কোড যুক্ত করতে পারিনি। তবে আমি @ বেন বারকয়ের উত্তরটি ব্যবহার করব এবং তারপরে এটি require.uncacheফাংশনে যুক্ত করব।

    // see https://github.com/joyent/node/issues/8266
    // use in it in @Ben Barkay's require.uncache function or along with it. whatever
    Object.keys(module.constructor._pathCache).forEach(function(cacheKey) {
        if ( cacheKey.indexOf(moduleName) > -1 ) {
            delete module.constructor._pathCache[ cacheKey ];
        }
    }); 

বলুন আপনার একটি মডিউল প্রয়োজন, তারপরে এটি আনইনস্টল করুন, তারপরে একই মডিউলটি পুনরায় ইনস্টল করুন তবে একটি ভিন্ন সংস্করণ ব্যবহার করেছেন যা এর প্যাকেজটিতে আলাদা মূল স্ক্রিপ্ট রয়েছে, পরবর্তী প্রয়োজনীয়টি ব্যর্থ হবে কারণ মূল স্ক্রিপ্টটি উপস্থিত নেই কারণ এটি ক্যাশে আছে Module._pathCache


3

আপনি 'অকার্যকর' বলতে যা বোঝায় তার থেকে আমি 100% নিশ্চিত নই, তবে requireক্যাশে সাফ করার জন্য আপনি নীচের বিবৃতিগুলি যুক্ত করতে পারেন :

Object.keys(require.cache).forEach(function(key) { delete require.cache[key] })

@ ড্যানক্রাম্বের মন্তব্য থেকে নেওয়া এখানে


2

requireUncached আপেক্ষিক পথ সহ: 🔥

const requireUncached = require => module => {
  delete require.cache[require.resolve(module)];
  return require(module);
};

module.exports = requireUncached;

অনুরোধ আপেক্ষিক পথের সাথে সংযুক্ত:

const requireUncached = require('../helpers/require_uncached')(require);
const myModule = requireUncached('./myModule');

1

দুটি পদক্ষেপের পদ্ধতি অনুসরণ করা আমার পক্ষে নিখুঁতভাবে কাজ করছে।

পরিবর্তন করার পরে Modelঅর্থাত ফাইল 'mymodule.js'পরিবর্তনশীল, আপনি precompiled মডেল মোছার প্রয়োজন নকুল মডেল প্রথম তারপর ব্যবহার করে এটি পুনরায় লোড প্রয়োজন-পুনঃলোড

Example:
        // Delete mongoose model
        delete mongoose.connection.models[thisObject.singular('mymodule')]

        // Reload model
        var reload = require('require-reload')(require);
        var entityModel = reload('./mymodule.js');

0

যদি এটি ইউনিট পরীক্ষার জন্য হয় তবে ব্যবহারের জন্য আরও একটি ভাল সরঞ্জাম হ'ল প্রক্সিওয়্যার । যতবারই আপনি মডিউলটি প্রক্সি করেন, এটি মডিউল ক্যাশেটিকে অকার্যকর করে দেবে এবং একটি নতুনকে ক্যাশে করবে। এটি আপনাকে পরীক্ষা করে নিচ্ছে এমন ফাইলের প্রয়োজনীয় মডিউলগুলি সংশোধন করার অনুমতি দেয়।


0

লোড করার পরে ক্যাশে থেকে মডিউল মুছতে আমি একটি ছোট মডিউল তৈরি করেছি। এটি পরবর্তী সময়ে মডিউলটির প্রয়োজন হলে পুনরায় মূল্যায়ন করতে বাধ্য করে। Https://github.com/bahmutov/require-and-forget দেখুন

// random.js
module.exports = Math.random()
const forget = require('require-and-forget')
const r1 = forget('./random')
const r2 = forget('./random')
// r1 and r2 will be different
// "random.js" will not be stored in the require.cache

পিএস: আপনি নিজেই মডিউলে "স্ব-ধ্বংস" রাখতে পারেন। Https://github.com/bahmutov/unload-me দেখুন

পিএসএস: নোডের সাথে আরও কৌশলগুলি আমার https://glebbahmutov.com/blog/hacking-node-require/ এ প্রয়োজন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.