क्या वाइल्डकार्ड का उपयोग करके किसी निर्देशिका में सभी फाइलों से मॉड्यूल आयात करना संभव है?


256

ES6 के साथ, मैं इस तरह से एक फ़ाइल से कई निर्यात आयात कर सकता हूं:

import {ThingA, ThingB, ThingC} from 'lib/things';

हालाँकि, मुझे प्रति फ़ाइल एक मॉड्यूल रखने का संगठन पसंद है। मैं इस तरह से आयात को समाप्त करता हूं:

import ThingA from 'lib/things/ThingA';
import ThingB from 'lib/things/ThingB';
import ThingC from 'lib/things/ThingC';

मैं ऐसा करने में सक्षम होना पसंद करूंगा:

import {ThingA, ThingB, ThingC} from 'lib/things/*';

या ऐसा ही कुछ, इस समझ के साथ कि प्रत्येक फ़ाइल में एक डिफ़ॉल्ट निर्यात होता है, और प्रत्येक मॉड्यूल को उसकी फ़ाइल के समान नाम दिया गया है।

क्या यह संभव है?


यह संभव है। कृपया babel babeljs.io/docs/learn-es2015 ... के लिए मॉड्यूल दस्तावेज़ीकरण देखें ... "lib / गणित" से "आयात {योग, पीआई}" निर्देशित। स्वीकृत उत्तर कोई अधिक मान्य नहीं है। कृपया इसे अपडेट करें।
एडुआर्ड जैको

6
@kresli मुझे नहीं लगता कि आप इस सवाल को समझते हैं। डॉक्स में, lib/mathएक फ़ाइल है जिसमें कई निर्यात होते हैं। मेरे सवाल में, lib/math/एक निर्देशिका है जिसमें कई फाइलें हैं, जिनमें से प्रत्येक में एक निर्यात है।
फ्रंबोट

2
ठीक है मैं समझा। उस स्थिति में बर्गी सही है। क्षमा करें
एडुआर्ड जैको

जवाबों:


230

मुझे नहीं लगता कि यह संभव है, लेकिन मॉड्यूल नाम का संकल्प मॉड्यूल लोडर पर निर्भर है, इसलिए एक लोडर कार्यान्वयन हो सकता है जो इसका समर्थन करता है।

तब तक, आप उस पर एक मध्यवर्ती "मॉड्यूल फ़ाइल" का उपयोग कर सकते lib/things/index.jsहैं

export * from 'ThingA';
export * from 'ThingB';
export * from 'ThingC';

और यह आपको करने की अनुमति देगा

import {ThingA, ThingB, ThingC} from 'lib/things';

6
सहायता के लिए धन्यवाद। मैं के साथ इस काम कर प्राप्त करने में सक्षम था index.jsकी तरह लग रही: import ThingA from 'things/ThingA'; export {ThingA as ThingA}; import ThingB from 'things/ThingB'; export {ThingB as ThingB};। अन्य आवेश index.jsनहीं हिलता।
Frambot

2
हम्म, export * fromकाम करना चाहिए। क्या आपने कोशिश की …from './ThingA'या export ThingA from …? आप किस मॉड्यूल लोडर का उपयोग कर रहे हैं?
बरगी

7
हां, आपके मूल जवाब ने काम किया अगर प्रत्येक ThingA.js, ThingB.js, प्रत्येक को निर्यात नाम दिया गया। सटीक।
फ्राम्बोट

1
क्या आपको इंडेक्स फ़ाइल निर्दिष्ट करनी है या आप केवल फ़ोल्डर और index.js निर्दिष्ट कर सकते हैं बजाय लोड किया जाएगा?
जोर्जटोन

1
@Zorgatone: यह आपके द्वारा उपयोग किए जा रहे मॉड्यूल लोडर पर निर्भर करता है, लेकिन हां आमतौर पर फ़ोल्डर पथ पर्याप्त होगा।
बरगी

128

पहले से ही उत्तर में प्रदान की गई विषय पर एक बदलाव, लेकिन इस बारे में कैसे:

एक में Thing,

export default function ThingA () {}

में things/index.js,

export {default as ThingA} from './ThingA'
export {default as ThingB} from './ThingB'
export {default as ThingC} from './ThingC'

फिर अन्य सभी चीजों का उपभोग करने के लिए,

import * as things from './things'
things.ThingA()

या सिर्फ कुछ चीजों का सेवन करने के लिए,

import {ThingA,ThingB} from './things'

वाना @ wolfbiter के जवाब पर एक नज़र है? निश्चित नहीं है कि वह दावा करता है कि कोष्ठक काम नहीं करता है।
बेर्गी

@Bergi हाँ सहमत हूँ, मुझे नहीं लगता कि wolfbiter का वैध ES6 है। हो सकता है कि वह बैबल के पुराने संस्करण का उपयोग कर रहा हो, या कोई अन्य ट्रांसपिलर?
जेड रिचर्ड्स

यह कैसे ट्रांसपोंड किया जा रहा है? एक निर्देशिका आयात करना index.jsमेरे लिए हल नहीं होता है। मैं
jasonszhao

2
क्या आप export ThingA from './ThingA'इसके बजाय टाइप नहीं कर सकतेexport {default as ThingA} from './ThingA'
पेट्र पेलर

1
क्या यह तीन झटकों का फायदा उठाता है? यदि मैं '' ./things 'से {ThingA} आयात करता हूं, तो क्या ThingB और ThingC को बंडल में भी जोड़ा जाएगा?
जियोर्जियो

75

वर्तमान उत्तर एक वर्कअराउंड का सुझाव देते हैं, लेकिन यह मुझे परेशान करता है कि यह मौजूद क्यों नहीं है, इसलिए मैंने एक babelप्लगइन बनाया है जो ऐसा करता है।

इसका उपयोग करके इसे स्थापित करें:

npm i --save-dev babel-plugin-wildcard

फिर इसे अपने .babelrcसाथ जोड़ें :

{
    "plugins": ["wildcard"]
}

विस्तृत जानकारी के लिए रेपो देखें


यह आपको ऐसा करने की अनुमति देता है:

import * as Things from './lib/things';

// Do whatever you want with these :D
Things.ThingA;
Things.ThingB;
Things.ThingC;

फिर से, रेपो में आगे की जानकारी है कि यह वास्तव में क्या करता है, लेकिन इसे इस तरह से करने से index.jsफाइलें बनाने से बचा जाता है और readdirरन -टाइम पर एस करने से बचने के लिए संकलन-समय पर भी होता है।

इसके अलावा एक नए संस्करण के साथ आप अपना उदाहरण बिल्कुल पसंद कर सकते हैं:

 import { ThingsA, ThingsB, ThingsC } from './lib/things/*';

उपरोक्त के समान ही काम करता है।


3
चेतावनी, मैं इस प्लगइन के साथ गंभीर मुद्दों पर चल रहा हूँ। समस्याएं शायद इसकी आंतरिक कैशिंग से आती हैं, आप अपने बालों को बाहर खींच रहे होंगे, जब आपका कोड सही होगा, लेकिन आपकी स्क्रिप्ट ठीक से काम नहीं करेगी क्योंकि आपने फ़ाइल को जोड़ा है ./lib/things;और इसे उठाया नहीं जा रहा है। इसके कारण होने वाली समस्याएं हास्यास्पद हैं। मैंने अभी स्थिति देखी है, जब फ़ाइल को बदलने के साथ फ़ाइल को import *जोड़ा हुआ फ़ाइल लेने के लिए बैबिल बनाता है, लेकिन इसे वापस बदलना, समस्या वापस लाता है, जैसे कि यह परिवर्तन से पहले कैश का पुन: उपयोग करता है। सावधानी से प्रयोग करें।
औकाज़ ज़रोदा

@ AnukaszZaroda babel में एक आंतरिक कैश है ~/.babel.jsonजिसके कारण यह अजीब व्यवहार करता है। इसके अलावा अगर आप वॉचर या हॉट रीलोडर की तरह इस्तेमाल कर रहे हैं तो आपको नई फाइल को सेव करना होगा ताकि यह नई डायरेक्टरी लिस्टिंग के साथ
रीकॉम्पलेक्ट हो जाए

@Downgoat तो बाबेल के कैश को हटाने के अलावा इसे कैसे दूर किया जाए? और btw। मुझे नहीं लगता कि आपकी टिप्पणी सही है। मेरे पास बैबिल की कैशिंग अक्षम है और उस प्लगइन के साथ इतनी बड़ी समस्याएं थीं। पूरी तरह से यह सिफारिश नहीं
SOReader

1
आगे के मुद्दों वाले किसी भी व्यक्ति के लिए Btw, bpwc clear-cacheक्योंकि वेबपैक और अन्य निर्माण प्रक्रियाएँ अब भी चुपचाप कैश
करेंगी

यह एक महान विचार है, लेकिन मैं इसे या तो काम करने में सक्षम नहीं था। संभवतः मेरे प्रवाहित कोड के साथ एक संघर्ष है, मुझे यकीन नहीं है, लेकिन मुझे `ReferenceError: Foo परिभाषित नहीं किया गया 'कोई फर्क नहीं पड़ता कि मैंने आयात कैसे संरचित किया है।

13

बहुत बढ़िया मुगल! यह होना चाहिए की तुलना में कठिन था।

एक फ्लैट डिफ़ॉल्ट निर्यात करें

यह उपयोग करने के लिए एक महान अवसर है प्रसार ( ...में { ...Matters, ...Contacts }नीचे:

// imports/collections/Matters.js
export default {           // default export
  hello: 'World',
  something: 'important',
};
// imports/collections/Contacts.js
export default {           // default export
  hello: 'Moon',
  email: 'hello@example.com',
};
// imports/collections/index.js
import Matters from './Matters';      // import default export as var 'Matters'
import Contacts from './Contacts';

export default {  // default export
  ...Matters,     // spread Matters, overwriting previous properties
  ...Contacts,    // spread Contacts, overwriting previosu properties
};
// imports/test.js
import collections from './collections';  // import default export as 'collections'

console.log(collections);

फिर, कमांड लाइन (प्रोजेक्ट रूट /) से बेबल संकलित कोड चलाने के लिए :

$ npm install --save-dev @babel/core @babel/cli @babel/preset-env @babel/node 
(trimmed)

$ npx babel-node --presets @babel/preset-env imports/test.js 
{ hello: 'Moon',
  something: 'important',
  email: 'hello@example.com' }

एक पेड़ की तरह डिफ़ॉल्ट निर्यात करें

यदि आप गुणों को अधिलेखित नहीं करना चाहते हैं, तो परिवर्तन करें:

// imports/collections/index.js
import Matters from './Matters';     // import default as 'Matters'
import Contacts from './Contacts';

export default {   // export default
  Matters,
  Contacts,
};

और उत्पादन होगा:

$ npx babel-node --presets @babel/preset-env imports/test.js
{ Matters: { hello: 'World', something: 'important' },
  Contacts: { hello: 'Moon', email: 'hello@example.com' } }

कई नामित निर्यातों को निर्यात करें w / कोई डिफ़ॉल्ट नहीं

यदि आप DRY के लिए समर्पित हैं , तो आयात में सिंटैक्स भी बदलता है:

// imports/collections/index.js

// export default as named export 'Matters'
export { default as Matters } from './Matters';  
export { default as Contacts } from './Contacts'; 

यह 2 नामित निर्यात w / कोई डिफ़ॉल्ट निर्यात बनाता है। फिर बदलें:

// imports/test.js
import { Matters, Contacts } from './collections';

console.log(Matters, Contacts);

और आउटपुट:

$ npx babel-node --presets @babel/preset-env imports/test.js
{ hello: 'World', something: 'important' } { hello: 'Moon', email: 'hello@example.com' }

सभी नामित निर्यात आयात करें

// imports/collections/index.js

// export default as named export 'Matters'
export { default as Matters } from './Matters';
export { default as Contacts } from './Contacts';
// imports/test.js

// Import all named exports as 'collections'
import * as collections from './collections';

console.log(collections);  // interesting output
console.log(collections.Matters, collections.Contacts);

पिछले उदाहरण में विनाशकारी सूचना import { Matters, Contacts } from './collections';

$ npx babel-node --presets @babel/preset-env imports/test.js
{ Matters: [Getter], Contacts: [Getter] }
{ hello: 'World', something: 'important' } { hello: 'Moon', email: 'hello@example.com' }

प्रयोग में

इन स्रोत फ़ाइलों को देखते हुए:

/myLib/thingA.js
/myLib/thingB.js
/myLib/thingC.js

एक बनाना /myLib/index.jsसभी फाइलों को बंडल करने आयात / निर्यात के प्रयोजन को हरा दिया। पहली जगह में सब कुछ वैश्विक बनाना आसान होगा, सब कुछ आयात / निर्यात के माध्यम से वैश्विक करने के बजाय index.js "रैपर फ़ाइलों" के माध्यम से।

यदि आप import thingA from './myLib/thingA';अपनी खुद की परियोजनाओं में एक विशेष फ़ाइल चाहते हैं।

मॉड्यूल के लिए निर्यात के साथ "रैपर फ़ाइल" बनाना केवल तभी समझ में आता है जब आप npm के लिए पैकेजिंग कर रहे हैं या एक बहु-वर्षीय मल्टी-टीम प्रोजेक्ट पर।

इसे दूर किया? देखें डॉक्स अधिक जानकारी के लिए।

इसके अलावा, स्टैकओवरफ़्लो के लिए याय अंत में कोड बाड़ मार्कअप के रूप में तीन `का समर्थन करता है।


10

आप async आयात () का उपयोग कर सकते हैं:

import fs = require('fs');

और फिर:

fs.readdir('./someDir', (err, files) => {
 files.forEach(file => {
  const module = import('./' + file).then(m =>
    m.callSomeMethod();
  );
  // or const module = await import('file')
  });
});

2
डायनेमिक इंपोर्ट अच्छा है। जब सवाल पूछा गया तो वे मौजूद नहीं थे। जवाब के लिए धन्यवाद।
Frambot

6

स्वीकृत प्रश्न के समान लेकिन यह आपको एक बार बनाए गए सूचकांक फ़ाइल में एक नया मॉड्यूल जोड़ने की आवश्यकता के बिना स्केल करने की अनुमति देता है:

./modules/moduleA.js

export const example = 'example';
export const anotherExample = 'anotherExample';

./modules/index.js

// require all modules on the path and with the pattern defined
const req = require.context('./', true, /.js$/);

const modules = req.keys().map(req);

// export all modules
module.exports = modules;

./example.js

import { example, anotherExample } from './modules'

यह मेरे लिए नहीं काम जब में उपनाम के रूप में आयात करने का प्रयास./example.js
tsujp

मेरे लिए न तो काम करता है न ही (वेबपैक 4.41, बेबल 7.7)
एडविन जोसर्ट

3

मैंने उन्हें कई बार इस्तेमाल किया है (विशेष रूप से कई फ़ाइलों (जैसे एएसटी नोड्स) पर डेटा को विभाजित करने वाली विशाल वस्तुओं के निर्माण के लिए, उन्हें बनाने के लिए मैंने एक छोटी स्क्रिप्ट बनाई थी (जो मैंने अभी-अभी एनपीएम में जोड़ा है, इसलिए बाकी सभी को। इसका उपयोग कर सकते हैं)।

उपयोग (वर्तमान में आपको निर्यात फ़ाइल का उपयोग करने के लिए कोलाहल का उपयोग करना होगा):

$ npm install -g folder-module
$ folder-module my-cool-module/

एक फ़ाइल युक्त बनाता है:

export {default as foo} from "./module/foo.js"
export {default as default} from "./module/default.js"
export {default as bar} from "./module/bar.js"
...etc

तब आप केवल फ़ाइल का उपभोग कर सकते हैं:

import * as myCoolModule from "my-cool-module.js"
myCoolModule.foo()

खिड़कियों में सही ढंग से काम नहीं कर रहा है, एक विंडोज़ पथ (के रूप में पथ उत्पन्न करता है \` instead of / ) also as an improvment you may want to allow two options like --filename` && --dest। जहां बनाई गई फ़ाइल संग्रहित किया जाना चाहिए और जो नाम के तहत अनुरूपण अनुमति देने के लिए इसके अलावा करता युक्त फ़ाइल नामों के साथ काम नहीं .(जैसे user.model.js)
यूरी Scarbaci

2

@ बर्गी के जवाब के लिए एक अन्य दृष्टिकोण

// lib/things/index.js
import ThingA from './ThingA';
import ThingB from './ThingB';
import ThingC from './ThingC';

export default {
 ThingA,
 ThingB,
 ThingC
}

उपयोग

import {ThingA, ThingB, ThingC} from './lib/things';

यह काम नहीं करेगा। मैंने इसे केवल एक प्रतिक्रिया ऐप में आज़माया और यह वापस आ गया export '...' was not found in '....
हामिद मयेली

1

आप आवश्यकता के रूप में अच्छी तरह से उपयोग कर सकते हैं:

const moduleHolder = []

function loadModules(path) {
  let stat = fs.lstatSync(path)
  if (stat.isDirectory()) {
    // we have a directory: do a tree walk
    const files = fs.readdirSync(path)
    let f,
      l = files.length
    for (var i = 0; i < l; i++) {
      f = pathModule.join(path, files[i])
      loadModules(f)
    }
  } else {
    // we have a file: load it
    var controller = require(path)
    moduleHolder.push(controller)
  }
}

फिर गतिशील रूप से लोड नियंत्रक के साथ अपने मॉड्यूलहार्ड का उपयोग करें:

  loadModules(DIR) 
  for (const controller of moduleHolder) {
    controller(app, db)
  }

0

यह बिल्कुल वैसा नहीं है जैसा आपने पूछा है, लेकिन इस विधि से मैं componentsListअपनी अन्य फाइलों में थ्रैट कर सकता हूं और फ़ंक्शन का उपयोग कर सकता हूं, जैसे कि componentsList.map(...)मुझे बहुत उपयोगी लगता है!

import StepOne from './StepOne';
import StepTwo from './StepTwo';
import StepThree from './StepThree';
import StepFour from './StepFour';
import StepFive from './StepFive';
import StepSix from './StepSix';
import StepSeven from './StepSeven';
import StepEight from './StepEight';

const componentsList= () => [
  { component: StepOne(), key: 'step1' },
  { component: StepTwo(), key: 'step2' },
  { component: StepThree(), key: 'step3' },
  { component: StepFour(), key: 'step4' },
  { component: StepFive(), key: 'step5' },
  { component: StepSix(), key: 'step6' },
  { component: StepSeven(), key: 'step7' },
  { component: StepEight(), key: 'step8' }
];

export default componentsList;

0

यदि आप वेबपैक का उपयोग कर रहे हैं। यह स्वचालित रूप से फ़ाइलें आयात करता है और एपीआई नेमस्पेस के रूप में निर्यात करता है।

इसलिए हर फ़ाइल जोड़ पर अपडेट करने की आवश्यकता नहीं है।

import camelCase from "lodash-es";
const requireModule = require.context("./", false, /\.js$/); // 
const api = {};

requireModule.keys().forEach(fileName => {
  if (fileName === "./index.js") return;
  const moduleName = camelCase(fileName.replace(/(\.\/|\.js)/g, ""));
  api[moduleName] = {
    ...requireModule(fileName).default
  };
});

export default api;

टाइपस्क्रिप्ट उपयोगकर्ताओं के लिए;

import { camelCase } from "lodash-es"
const requireModule = require.context("./folderName", false, /\.ts$/)

interface LooseObject {
  [key: string]: any
}

const api: LooseObject = {}

requireModule.keys().forEach(fileName => {
  if (fileName === "./index.ts") return
  const moduleName = camelCase(fileName.replace(/(\.\/|\.ts)/g, ""))
  api[moduleName] = {
    ...requireModule(fileName).default,
  }
})

export default api

0

मैं उपयोगकर्ता atilkan के दृष्टिकोण से लेने और इसे थोड़ा संशोधित करने में सक्षम था:

टाइपस्क्रिप्ट उपयोगकर्ताओं के लिए;

require.context('@/folder/with/modules', false, /\.ts$/).keys().forEach((fileName => {
    import('@/folder/with/modules' + fileName).then((mod) => {
            (window as any)[fileName] = mod[fileName];
            const module = new (window as any)[fileName]();

            // use module
});

}));

-9

यदि आप A, B, C में डिफ़ॉल्ट निर्यात नहीं करते हैं, लेकिन सिर्फ {} निर्यात करते हैं, तो ऐसा करना संभव है

// things/A.js
export function A() {}

// things/B.js
export function B() {}

// things/C.js
export function C() {}

// foo.js
import * as Foo from ./thing
Foo.A()
Foo.B()
Foo.C()

1
यह मान्य जावास्क्रिप्ट नहीं है (आसपास कोई उद्धरण नहीं है ./thing) और यहां तक ​​कि अगर वहाँ थे, तो यह काम नहीं करेगा। (मैंने यह कोशिश की, और यह काम नहीं किया।)
जॉन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.