কোনও ওয়াইল্ডকার্ড ব্যবহার করে কোনও ডিরেক্টরিতে সমস্ত ফাইল থেকে মডিউলগুলি আমদানি করা সম্ভব?


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/*';

বা বোঝা যায় এমন কনভেনশনের সাথে অনুরূপ কিছু যা প্রতিটি ফাইলে একটি ডিফল্ট রফতানি থাকে এবং প্রতিটি মডিউলকে তার ফাইল হিসাবে একই নাম দেওয়া হয়।

এটা কি সম্ভব?


এটা সম্ভব. Babeljs.io/docs/learn-es2015 এর জন্য অনুগ্রহ করে মডিউল ডকুমেন্টেশন দেখুন ... "lib / math" থেকে "আমদানি {যোগ, পাই"; গৃহীত উত্তরটি আর বৈধ নয়। এটি আপডেট করুন।
এডুয়ার্ড জ্যাকো

6
@ ক্রেসলি আমি মনে করি না আপনি প্রশ্নটি বুঝতে পেরেছেন। ডক্সে, 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না।
ফ্রেমবট

2
এইচএম, export * fromকাজ করা উচিত। আপনি চেষ্টা করেছেন …from './ThingA'নাকি export ThingA from …? আপনি কোন মডিউল লোডার ব্যবহার করছেন?
বার্গি 21

7
হ্যাঁ, প্রতিটি থিংএ.জেস, থিংবি.জেএস, প্রতিটি রফতানির নামে রফতানি হলে আপনার আসল উত্তরটি কার্যকর হয়েছিল। চিহ্নিত করা.
ফ্রেমবট

1
আপনার কি সূচি ফাইলটি নির্দিষ্ট করতে হবে বা আপনি কেবলমাত্র ফোল্ডারটি নির্দিষ্ট করতে পারেন এবং পরিবর্তে index.js লোড হবে?
জর্জিটোন

1
@ জর্জিটোন: এটি আপনি যে মডিউল লোডারটি ব্যবহার করছেন তার উপর নির্ভর করে তবে হ্যাঁ সাধারণত ফোল্ডারের পথই যথেষ্ট be
বার্গি

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'

@ ওল্ফবিটারের উত্তরটি দেখতে চান? নিশ্চিত না কেন তিনি দাবি করেছেন যে প্রথম বন্ধনী কাজ করে না।
বার্গি

@ বার্গি হ্যাঁ রাজি, আমি মনে করি না যে ভলফিটারকে ES6 বৈধ বলে মনে হচ্ছে। হতে পারে তিনি বাবেলের একটি পুরানো সংস্করণ ব্যবহার করছেন, বা অন্য কোনও ট্রান্সপ্লার?
জেদ রিচার্ডস

এটি কীভাবে স্থানান্তরিত হচ্ছে? ডিরেক্টরি আমদানি করা index.jsআমার পক্ষে সমাধান হয় না । আমি সিস্টেমজেএস + ব্যাবেল ব্যবহার করছি
জেসনসভাও

2
আপনি কেবল এর export ThingA from './ThingA'পরিবর্তে টাইপ করতে পারবেন নাexport {default as ThingA} from './ThingA'
পেট্র পেলার

1
এটি কি তিনটি কাঁপানোর সুবিধা নেয়? আমি যদি './things' থেকে {থিংএ import আমদানি করি তবে থিংবি এবং থিংসিকেও বান্ডলে যুক্ত করা হবে?
জর্জিও

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এবং রানটাইমের সময় এড়াতে সংকলন সময়ে ঘটে happens

আরও নতুন সংস্করণ দিয়ে আপনি ঠিক নিজের উদাহরণের মতো করতে পারেন:

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

উপরের মত একই কাজ করে।


3
সতর্কতা, এই প্লাগইনটিতে আমার খুব সমস্যা হচ্ছে having সমস্যাগুলি সম্ভবত এর অভ্যন্তরীণ ক্যাচিং থেকে আসে, আপনি যখন আপনার কোডটি নিখুঁত হবে তখন আপনার চুলগুলি টেনে আনবেন, তবে আপনার স্ক্রিপ্টটি সঠিকভাবে কাজ করবে না কারণ আপনি ফাইল যুক্ত করেছেন ./lib/things;এবং এটি বাছাই করা হচ্ছে না। এটির কারণে সমস্যাগুলি হাস্যকর। আমি কেবল পরিস্থিতি প্রত্যক্ষ করেছি, যখন ফাইল পরিবর্তন করার সাথে import *বাবেল যুক্ত করা ফাইল বাছাই করে তোলে, তবে এটি আবার পরিবর্তন করে সমস্যা ফিরিয়ে দেয়, যেমন এটি পরিবর্তনের আগে থেকেই ক্যাশে পুনরায় ব্যবহার করে। সতর্কতার সাথে ব্যবহার করুন.
asukasz Zaroda

@ AsukaszZaroda বাবেলের একটি অভ্যন্তরীণ ক্যাশে রয়েছে ~/.babel.jsonযা এই অদ্ভুত আচরণের কারণ। এছাড়াও আপনি যদি কোনও প্রহরী বা হট রিলোডারের মতো ব্যবহার করছেন তবে আপনাকে নতুন ফাইলটি সংরক্ষণ করতে হবে যাতে এটি নতুন ডিরেক্টরি তালিকার সাথে
সংমিশ্রিত হবে

@ ডাউনগোট তাই বাবালের ক্যাশে মোছা বাদ দিয়ে কীভাবে এটি পরাভূত করবেন? এবং বিটিডব্লিউ। আপনার মন্তব্যটি সঠিক বলে আমি মনে করি না। আমি বাবেলের ক্যাচিং অক্ষম করেছি এবং সেই প্লাগইনটিতে এ জাতীয় বিশাল সমস্যা রয়েছে। সম্পূর্ণরূপে এটির সুপারিশ করবেন না
SOReader

1
বিটিডব্লিউ যে কারও কাছে আরও সমস্যা রয়েছে, যুক্ত করুন bpwc clear-cacheকারণ ওয়েবপ্যাক এবং অন্যান্য বিল্ড প্রক্রিয়াগুলি এখনও নিঃশব্দে ক্যাশে করবে
ডাউনগোট

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

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' } }

একাধিক নামযুক্ত রফতানি রফতানি করুন / কোনও ডিফল্ট নয়

আপনি যদি ডিআরওয়াইকে উত্সর্গীকৃত হন তবে আমদানির সিনট্যাক্সটিও পরিবর্তিত হয়:

// imports/collections/index.js

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

এটি 2 নামযুক্ত রফতানি তৈরি করে / কোনও ডিফল্ট রফতানি করে না। তারপরে পরিবর্তন করুন:

// 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সমস্ত ফাইল বান্ডিল করতে একটি তৈরি করা আমদানি / রফতানির উদ্দেশ্যকে পরাস্ত করে। ইন্ডেক্সের মাধ্যমে আমদানি / রফতানির মাধ্যমে সবকিছুকে বৈশ্বিক করার চেয়ে প্রথম স্থানে সবকিছুকে বৈশ্বিক করা সহজ হবে "র‍্যাপার ফাইলগুলি"।

আপনি যদি import thingA from './myLib/thingA';নিজের প্রকল্পগুলিতে একটি নির্দিষ্ট ফাইল চান ।

মডিউলের জন্য রফতানির সাথে একটি "র‍্যাপার ফাইল" তৈরি করা তখনই বোধগম্য হয় যদি আপনি এনএমপি বা বহু-বছরের বহু-টিম প্রকল্পে প্যাকেজিং করছেন।

এটি এতদূর তৈরি? আরও বিশদ জন্য ডক্স দেখুন ।

এছাড়াও, স্ট্যাকওভারফ্লোয়ের জন্য হাঁ শেষ অবধি তিনটি code গুলি কোড বেড়া মার্কআপ হিসাবে সমর্থন করে।


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
ডায়নামিক আমদানিগুলি দুর্দান্ত। প্রশ্নটি জিজ্ঞাসা করা হলে তারা নিশ্চিতভাবেই উপস্থিত ছিল না। উত্তর করার জন্য ধন্যবাদ.
ফ্রেমবট

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

আমার জন্য দুজনই কাজ করে না (ওয়েবপ্যাক ৪.৪৪, বাবেল 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

আমি ব্যবহারকারী আটিলকান এর পদ্ধতির কাছ থেকে নিতে এবং এটি কিছুটা পরিবর্তন করতে সক্ষম হয়েছি:

টাইপস্ক্রিপ্ট ব্যবহারকারীদের জন্য;

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

আপনি যদি এ, বি, সি-তে ডিফল্ট রফতানি না করেন তবে কেবল export export রফতানি করেন তবে তা করা সম্ভব

// 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) এবং তা থাকলেও এটি কার্যকর হবে না। (আমি এটি চেষ্টা করেছি, এবং এটি কার্যকর হয়নি))
জন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.