Is it possible to import modules from all files in a directory, using a wildcard?

前端 未结 13 2035
陌清茗
陌清茗 2020-11-22 04:25

With ES6, I can import several exports from a file like this:

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

However, I like the orga

相关标签:
13条回答
  • 2020-11-22 04:34

    You can use async import():

    import fs = require('fs');
    

    and then:

    fs.readdir('./someDir', (err, files) => {
     files.forEach(file => {
      const module = import('./' + file).then(m =>
        m.callSomeMethod();
      );
      // or const module = await import('file')
      });
    });
    
    0 讨论(0)
  • 2020-11-22 04:34

    This is not exactly what you asked for but, with this method I can Iterate throught componentsList in my other files and use function such as componentsList.map(...) which I find pretty usefull !

    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 讨论(0)
  • 2020-11-22 04:36

    Great gugly muglys! This was harder than it needed to be.

    Export one flat default

    This is a great opportunity to use spread (... in { ...Matters, ...Contacts } below:

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

    Then, to run babel compiled code from the command line (from project root /):

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

    Export one tree-like default

    If you'd prefer to not overwrite properties, change:

    // imports/collections/index.js
    import Matters from './Matters';     // import default as 'Matters'
    import Contacts from './Contacts';
    
    export default {   // export default
      Matters,
      Contacts,
    };
    

    And the output will be:

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

    Export multiple named exports w/ no default

    If you're dedicated to DRY, the syntax on the imports changes as well:

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

    This creates 2 named exports w/ no default export. Then change:

    // imports/test.js
    import { Matters, Contacts } from './collections';
    
    console.log(Matters, Contacts);
    

    And the output:

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

    Import all named exports

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

    Notice the destructuring import { Matters, Contacts } from './collections'; in the previous example.

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

    In practice

    Given these source files:

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

    Creating a /myLib/index.js to bundle up all the files defeats the purpose of import/export. It would be easier to make everything global in the first place, than to make everything global via import/export via index.js "wrapper files".

    If you want a particular file, import thingA from './myLib/thingA'; in your own projects.

    Creating a "wrapper file" with exports for the module only makes sense if you're packaging for npm or on a multi-year multi-team project.

    Made it this far? See the docs for more details.

    Also, yay for Stackoverflow finally supporting three `s as code fence markup.

    0 讨论(0)
  • 2020-11-22 04:37

    The current answers suggest a workaround but it's bugged me why this doesn't exist, so I've created a babel plugin which does this.

    Install it using:

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

    then add it to your .babelrc with:

    {
        "plugins": ["wildcard"]
    }
    

    see the repo for detailed install info


    This allows you to do this:

    import * as Things from './lib/things';
    
    // Do whatever you want with these :D
    Things.ThingA;
    Things.ThingB;
    Things.ThingC;
    

    again, the repo contains further information on what exactly it does, but doing it this way avoids creating index.js files and also happens at compile-time to avoid doing readdirs at runtime.

    Also with a newer version you can do exactly like your example:

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

    works the same as the above.

    0 讨论(0)
  • 2020-11-22 04:39

    If you are using webpack. This imports files automatically and exports as api namespace.

    So no need to update on every file addition.

    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;
    

    For Typescript users;

    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 讨论(0)
  • 2020-11-22 04:39

    I was able to take from user atilkan's approach and modify it a bit:

    For Typescript users;

    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
    });
    
    }));
    
    0 讨论(0)
提交回复
热议问题