Avec ES6, je peux importer plusieurs exportations à partir d'un fichier comme celui-ci:
import {ThingA, ThingB, ThingC} from 'lib/things';
Cependant, j'aime bien avoir un module par fichier. Je me retrouve avec des importations comme ceci:
import ThingA from 'lib/things/ThingA';
import ThingB from 'lib/things/ThingB';
import ThingC from 'lib/things/ThingC';
J'aimerais pouvoir faire ça:
import {ThingA, ThingB, ThingC} from 'lib/things/*';
ou quelque chose de similaire, avec la convention comprise que chaque fichier contient une exportation par défaut et que chaque module porte le même nom que son fichier.
Est-ce possible?
Je ne pense pas que cela soit possible, mais autant que la résolution des noms de modules revienne aux chargeurs de modules, une implémentation de chargeur qui prend en charge cela pourrait.
Jusque-là, vous pourriez utiliser un "fichier de module" intermédiaire à lib/things/index.js
qui ne contient que
export * from 'ThingA';
export * from 'ThingB';
export * from 'ThingC';
et cela vous permettrait de faire
import {ThingA, ThingB, ThingC} from 'lib/things';
Les réponses actuelles suggèrent une solution de contournement, mais le fait que cela n’existe pas, m’a énervé, j’ai donc créé un plugin babel
qui le fait.
Installez-le en utilisant:
npm i --save-dev babel-plugin-wildcard
puis ajoutez-le à votre .babelrc
avec:
{
"plugins": ["wildcard"]
}
voir le repo pour des informations d'installation détaillées
Cela vous permet de faire ceci:
import * as Things from './lib/things';
// Do whatever you want with these :D
Things.ThingA;
Things.ThingB;
Things.ThingC;
là encore, le repo contient des informations supplémentaires sur ce qu’il fait exactement, mais le faire de cette façon évite de créer des fichiers index.js
et se produit également au moment de la compilation pour éviter de faire readdir
s à l’exécution.
Également avec une version plus récente, vous pouvez faire exactement comme votre exemple:
import { ThingsA, ThingsB, ThingsC } from './lib/things/*';
fonctionne comme ci-dessus.
Je les ai utilisées plusieurs fois (notamment pour construire des objets volumineux fractionnant les données en plusieurs fichiers (par exemple, AST noeuds)), afin de les construire, j’ai créé un petit script (que je viens d’ajouter à npm pour que tout le monde puisse l’utiliser).
Utilisation (actuellement, vous devrez utiliser babel pour utiliser le fichier d'exportation):
$ npm install -g folder-module
$ folder-module my-cool-module/
Génère un fichier contenant:
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
Ensuite, vous pouvez simplement consommer le fichier:
import * as myCoolModule from "my-cool-module.js"
myCoolModule.foo()
Juste une autre approche de la réponse de @ Bergi
// lib/things/index.js
import ThingA from './ThingA';
import ThingB from './ThingB';
import ThingC from './ThingC';
export default {
ThingA,
ThingB,
ThingC
}
Les usages
import {ThingA, ThingB, ThingC} from './lib/things';
Super muglys gugly! C'était plus difficile que nécessaire.
C'est une excellente occasion d'utiliser spread (...
dans { ...Matters, ...Contacts }
ci-dessous:
// 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);
Ensuite, pour exécutez le code compilé par babel à partir de la ligne de commande (à partir de la racine du projet /):
$ 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]' }
Si vous préférez ne pas écraser les propriétés, modifiez:
// imports/collections/index.js
import Matters from './Matters'; // import default as 'Matters'
import Contacts from './Contacts';
export default { // export default
Matters,
Contacts,
};
Et le résultat sera:
$ npx babel-node --presets @babel/preset-env imports/test.js
{ Matters: { hello: 'World', something: 'important' },
Contacts: { hello: 'Moon', email: '[email protected]' } }
Si vous êtes dédié à DRY , la syntaxe des importations change également:
// imports/collections/index.js
// export default as named export 'Matters'
export { default as Matters } from './Matters';
export { default as Contacts } from './Contacts';
Cela crée 2 exportations nommées avec aucune exportation par défaut. Puis changez:
// imports/test.js
import { Matters, Contacts } from './collections';
console.log(Matters, Contacts);
Et la sortie:
$ 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);
Notez le destructuringimport { Matters, Contacts } from './collections';
dans l'exemple précédent.
$ npx babel-node --presets @babel/preset-env imports/test.js
{ Matters: [Getter], Contacts: [Getter] }
{ hello: 'World', something: 'important' } { hello: 'Moon', email: '[email protected]' }
Étant donné ces fichiers source:
/myLib/thingA.js
/myLib/thingB.js
/myLib/thingC.js
La création d'un /myLib/index.js
pour regrouper tous les fichiers annule le but de l'importation/exportation. En premier lieu, il serait plus facile de tout rendre global que de le faire via import/export via "fichiers wrapper" index.js.
Si vous voulez un fichier particulier, import thingA from './myLib/thingA';
dans vos propres projets.
La création d'un "fichier wrapper" avec des exportations pour le module n'a de sens que si vous empaquetez pour npm ou sur un projet multi-équipes pluriannuel.
Fait ça si loin? Voir le docs pour plus de détails.
Aussi, yay pour Stackoverflow supportant finalement trois `s comme balisage de clôture de code.
Semblable à la question acceptée, mais cela vous permet d’échelle sans avoir à ajouter un nouveau module au fichier d’index chaque fois que vous en créez un:
./ 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'
Vous pouvez utiliser async import ():
import fs = require ('fs');
et alors:
fs.readdir('./someDir', (err, files) => {
files.forEach(file => {
const module = import('./' + file).then(m =>
m.callSomeMethod();
);
// or const module = await import('file')
});
});
Vous pouvez aussi utiliser 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)
}
}
Puis utilisez votre moduleHolder avec des contrôleurs chargés dynamiquement:
loadModules(DIR)
for (const controller of moduleHolder) {
controller(app, db)
}
Ce n’est pas exactement ce que vous aviez demandé mais, avec cette méthode, je peux naviguer dans componentsList
dans mes autres fichiers et utiliser une fonction telle que componentsList.map(...)
que je trouve assez utile!
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;