web-dev-qa-db-ja.com

ワイルドカードを使用して、ディレクトリ内のすべてのファイルからモジュールをインポートすることは可能ですか?

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

各ファイルにはデフォルトのエクスポートが1つ含まれ、各モジュールにはそのファイルと同じ名前が付けられているという理解された規則を使用して、またはそれに似たもの。

これは可能ですか?

195
Joe Frambach

これは可能ではないと思いますが、モジュール名の解決はモジュールローダー次第なので、これをサポートするローダー実装があるかもしれません。

それまでは、lib/things/index.jsに中間の「モジュールファイル」を含めることができます

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

そしてそれはあなたができるようになるでしょう

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

すでに答えで提供されているテーマの単なる変形ですが、これはどうですか。

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'
102
Jed Richards

現在の答えは回避策を示唆していますが、なぜこれが存在しないのか私は悩んでいたので、これを行う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;

繰り返しになりますが、 repo にはそれが何をするのかについてのより詳しい情報が含まれていますが、こうすることでindex.jsファイルを作成することを避け、実行時にreaddirsを避けるためにコンパイル時にも起こります。

また、新しいバージョンでもあなたの例のようにすることができます。

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

上記と同じ働きをします。

58
Downgoat

グググママグカップ!これは必要以上に困難でした。

フラットデフォルトを1つエクスポートする

これは spread...の下の{ ...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: '[email protected]',
};
// 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);

それから (プロジェクトルート/から)コマンドライン からbabelでコンパイルされたコードを実行します。

$ 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: '[email protected]' }

ツリー風のデフォルトを1つエクスポートする

プロパティを上書きしたくない場合は、次のように変更します。

// 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: '[email protected]' } }

複数の名前付きエクスポートをデフォルトなしでエクスポート

もしあなたが _ dry _ に献身的であれば、インポートの構文も変わります。

// 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: '[email protected]' }

名前付きエクスポートをすべてインポートする

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

前の例の destructuringimport { 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: '[email protected]' }

実際には

これらのソースファイルを考えます。

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

すべてのファイルをまとめるために/myLib/index.jsを作成すると、インポート/エクスポートの目的が無効になります。 index.jsの「ラッパーファイル」を介してインポート/エクスポートを介してすべてをグローバルにするよりも、最初にすべてをグローバルにする方が簡単です。

特定のファイルが必要な場合は、自分のプロジェクトのimport thingA from './myLib/thingA';を使用してください。

モジュールのエクスポートを含む「ラッパーファイル」を作成するのは、npm用にパッケージ化している場合、または複数年に渡るマルチチームプロジェクトの場合にのみ意味があります。

ここまで来た?詳細は docs を参照してください。

また、Stackoverflowのyayはついにコードフェンスのマークアップとして3をサポートしました。

4
Michael Cole

私はそれらを構築するためにそれらを構築するために私は数回(特に多数のファイル(例えばASTノード)にデータを分割する巨大なオブジェクトを構築するために)を使いました他の人が使えるようにnpmに追加されました。

使用法(現在エクスポートファイルを使用するにはbabelを使用する必要があります):

$ 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()
2
Jamesernator

@ Bergiの回答に対する他のアプローチ

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

受け入れられた質問に似ていますが、作成するたびにインデックスファイルに新しいモジュールを追加する必要なしにスケーリングできます。

./ 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'
1
Nicolas

Async import()を使うことができます。

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')
  });
});
1
mr_squall

あなたは同様にrequireを使うことができます:

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

それから、動的にロードされたコントローラであなたのmoduleHolderを使ってください:

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

これはあなたが要求したものではありませんが、この方法で私は他のファイルの中の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
FlyingZipper