Search code examples
javascriptdesign-patternsimportrevealing-module-pattern

Converting single file revealing module pattern javascript to multi-file using import


I am new to JS design patterns and have not used much of require or import. I have a single module which contains multiple functions and private variables, which is packaged into a module. Currently everything is in one file but splitting it into multiple files would be good practice and provide better clarity. The simplified view of the module's pattern looks something like this:

let Module = () => {
  //some private variables
  let private1,
      private2;

  //some public functions
  function addDatatoPrivate1 (data) {
    private1 = processData(data);
  }

  function addDatatoPrivate2 (data) {
    private2 = processData(data);
  }

  //private function processData
  function processData(data) {
    return data.trim();
  }

  return {
    addDatatoPrivate1: addDatatoPrivate1,
    addDatatoPrivate2: addDatatoPrivate2,
  }
}

I would like to split up the functions into multiple files i.e. separate file for addDatatoPrivate1, addDatatoPrivate2 and processData. In addition I would like to have the variables private1 and private2 be available for other methods in the Module privately. How do I go about splitting the code into multiple files and then how to use import to get the different components of the module to package into one.

The eventual aim is to have something which a user can load into their own project and use something like d3js or jQuery. For example, with the code as above anyone can simply assign the module to a variable and use it like so:

  let moduleInstance = Module();
  moduleInstance.addDatatoPrivate1(' some data here ');
  moduleInstance.addDatatoPrivate2(' some data here2 ');

Solution

  • You could use ES6 modules.

    Steps:

    1. Create the module file, let's say the file name is 'someModule.js' and add your code in it and export the methods using ES6 export.
       //some private variables
        let private1,
            private2;
    
        //some public functions
        function addDatatoPrivate1 (data) {
          private1 = processData(data);
        }
    
        function addDatatoPrivate2 (data) {
          private2 = processData(data);
        }
    
        //private function processData
        function processData(data) {
          return data.trim();
        }
    
        return {
          addDatatoPrivate1: addDatatoPrivate1,
          addDatatoPrivate2: addDatatoPrivate2,
        }
    
        export {
            processData,
            addDatatoPrivate1,
            addDatatoPrivate2,
        }
    
    

    Now the user of the module can import the module like below.

    Using ES6 object destructuring

     import {addDatatoPrivate1, addDatatoPrivate2, processData} from './someModule'
    
      addDatatoPrivate1(' some data here ');
      addDatatoPrivate2(' some data here2 ');
    

    OR using wild card (*)

    import * as moduleInstance from './someModule'
    
    moduleInstance.addDatatoPrivate1(' some data here ');
    moduleInstance.addDatatoPrivate2(' some data here2 ');
    

    It's not possible to export a variable privately. Anything exported from module is public by default.

    If you want to create separate module for each then you could do something like below.

    We could use ES6 default export to avoid object destructuring.

    module1.js

    
     function processData(data) {
        return data.trim();
     }
    
    
     export default processData;
    

    module2.js

     import processData from './module1';
     //some private variables
     let private1;
    
    //some public functions
    function addDatatoPrivate1 (data) {
        private1 = processData(data);
    }
    
    export default addDatatoPrivate1;
    

    module3.js

    import processData from './module1';
    
    //some private variables
    let private2;
    
    
    function addDatatoPrivate2 (data) {
        private2 = processData(data);
    }
    
    export default addDatatoPrivate2;
    

    And then you can include these module and some other file.

    import addDatatoPrivate1 from './module2';
    import addDatatoPrivate2 from './module3';
    
    addDatatoPrivate1(' some data here ');
    addDatatoPrivate2(' some data here2 ');
    

    or you could export all of you method in one file so other can import it and use.

    index.js

    import addDatatoPrivate1 from './module2';
    import addDatatoPrivate2 from './module3';
    
    export {
       addDatatoPrivate1,
       addDatatoPrivate2
    }