Thursday, November 3, 2016

require.js first steps

Very often, we have to split a solid application to the set of simple modules. And of course, such modules can have dependencies. In such situations we have to manage dependencies somehow. For example we can have module A which is using modules B and C. And module B use modules D and E. So we have to load this modules in order:
  <script src="js/E.js"></script>
  <script src="js/D.js"></script>
  <script src="js/B.js"></script>
  <script src="js/C.js"></script>
  <script src="js/A.js"></script>

RequireJS - one of the tools for managing such situations. Using is we will have just to load main file and requirejs itself:
<script data-main="js/A"  src="http://requirejs.org/docs/release/2.3.2/comments/require.js"></script>


Let's create a simple application without require.js and after that let's re-write it with it.
In our application we will have 2 entities: User and Department. 2 tools: Validator and Logger. And main file which is using them all.

1. Without require.js. 

We are just creating separate js files and after all w will have to list them in proper order in html file.

1.1 User object 

function User(id, name) {
  this.id=id;
  this.name=name;
  this.toString = function() {
     return name;
  }
}


1.2 Department object

function Department(id, name) {
 this.users=[];
 this.id=id;
 this.name=name;

 this.addUser = function(user) {
   this.users.push(user);
 };

 this.getUsers = function() {
   return this.users;
 };
 
}


1.3 Validator object 

function hasAttribute(object, attribute) {
   return object.hasOwnProperty(attribute);
}

function isValid(object) {
  return hasAttribute(object, "name") && hasAttribute(object, "id");
}



1.4 Logger

function idNameFormat(object) {
  return "["+object.id+"]"+object.name;
}

function logUser(user) {
  console.log("user:"+idNameFormat(user));
}

function logDepartment(department) {
  console.log("department:"+idNameFormat(department)+" users:"+department.getUsers().toString());
}


1.5. Main script

We are just creating several objects, validating them and printing them using logger. 

function run() {
   var user1=new User(1, "Joe");
   var user2=new User(2, "Black");

   var dep1=new Department(1, "IT");
   dep1.addUser(user1);
   dep1.addUser(user2);

   if (isValid(user1) && isValid(user2) && isValid(dep1)) {
      logUser(user1);
      logUser(user2);
      logDepartment(dep1);
   } else {
      console.log("errors in validation");
   }
   
}

1.6 HTML file 

All our modules has to be listed in a proper order otherwise our application will not work.

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
</head>

<body>

  <script src="js/validator.js"></script>
  <script src="js/user.js"></script>
  <script src="js/department.js"></script>
  <script src="js/logger.js"></script>
  <script src="js/main.js"></script>
  
  <script>
    run();
  </script>
</body>

</html>


2. Now let's rewrite application using require.js

2.1. User

We are defining User function and returning it.

define(function () {

    function User(id, name) {
        this.id = id;
        this.name = name;

        this.toString = function () {
            return this.name;
        };
    }

    return User;
});


2.2. Department

The same as with User.

define(function () {

    function Department(id, name) {
        this.users = [];
        this.id = id;
        this.name = name;

        this.addUser = function (user) {
            this.users.push(user);
        };

        this.getUsers = function () {
            return this.users;
        };
    }

    return Department;

});

2.3 Validator

Here we have private method "hasAttribute" and public method "isValid".

define(function () {

    function hasAttribute(object, attribute) {
        return object.hasOwnProperty(attribute);
    }

    return {
        isValid: function (object) {
            return hasAttribute(object, "name") && hasAttribute(object, "id");
        }
    }

});


2.4 Logger

Here we also have private method and 2 public methods.

define(function () {
        function idNameFormat(object) {
            return "[" + object.id + "]" + object.name;
        }

        return {
            logUser: function (user) {
                console.log("user:" + idNameFormat(user));

            },
            logDepartment: function (department) {
                console.log("department:" + idNameFormat(department) + ". users:" + department.getUsers().toString());
            }
        }
    }
);


2.5 Main

Here we have most interesting thing: we are getting dependencies using require.js

require(["user", "department", "logger", "validator"], function (User, Department, Logger, Validator) {
    console.log("Hello world!");

    var user1 = new User(1, "Joe");
    var user2 = new User(2, "Black");

    var dep1 = new Department(1, "IT");
    dep1.addUser(user1);
    dep1.addUser(user2);

    if (Validator.isValid(user1) && Validator.isValid(user2) && Validator.isValid(dep1)) {
        Logger.logUser(user1);
        Logger.logUser(user2);
        Logger.logDepartment(dep1);
    } else {
        console.log("errors in validation");
    }


});


2.6. HTML file

Here we just have to point to our main file ("js/main.js"  - file ending ".js" can be omitted) and path to require.js(url).


<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
</head>

<body>

  <script data-main="js/main"  src="http://requirejs.org/docs/release/2.3.2/comments/require.js"></script>

</body>

</html>

3.  Execution.


logger.js:8 user:[1]Joe
logger.js:8 user:[2]Black
logger.js:12 department:[1]IT. users:Joe,Black

4. The end. 

Development with  RequireJS makes part of application modular and reusable.

No comments:

Post a Comment