modulerr
v0.1.2
Published
Modulerr.js is a small library which I developed in order to make modular JavaScript development easier
Downloads
4
Readme
#Modulerr.js
##What is this Modulerr thing...
Modulerr.js is a very small and compact library which I was inspired to create after my disappointment with other frameworks which were supposed to help me separate my JavaScript files. But still I needed them when deploying to production.
##Yeah, but why would I use it?
I have created Modulerr.js with three ideas in mind:
###1. Easy separation of JavaScript files/modules while developing
Your files will be loaded in the browser dynamically as one would expect. There is no asynchronous loading of scripts or other similar stuff as in other known frameworks. This stage of the library is purely development oriented in order to allow you to easily debug and configure your scripts. The configuration can happen by passing a single JSON object or a url of a JSON file. At this stage your application still needs Modulerr.js.
###2. Combining all the JavaScript modules into a single file
Combinerr.js will not only combine all the modules into a single file, it will combine them in a way which will no longer require you to deploy Modulerr.js to production.
###3. Simplicity!
I remember the struggle of searching through the endless documentation and after a while to find an absolutely new solution in some forum. I want to change that aswell. The settings of Modulerr.js are very basic and intuitive. Moreover, you can find all the documentation you need here. No property or function will be left uncovered.
##Installation
npm install modulerr
or simply clone this repository.
You can also npm install -g modulerr
in order to be able to use the combinerr from everywhere.
#Getting Started
##Modulerr.js
You can configure Modulerr.js by using its config object. It has the following functions:
- get - simply returns the currently set json config. Can be modified and set back on later.
var modulerrConfigJson = modulerr.config.get();
- set - sets the config object. Acceps a json object as a string or a pure json object. Also accepts a path to a file. An Ajax request will be sent for that file. In this case a callback is invoked when the script is loaded
modulerr.config.set('{
"main": "mainModule"
}');
//or
modulerr.config.set({
main: 'mainModule'
});
//or
modulerr.config.set('config.json', callback);
- apply - Applies the currently set config object to the module. This will load all modules, dependencies and settings.
###Configuring Modulerr.js
As you already know, you need to set a json object to the config, the object can have the following properties:
- basePath - The paths of all scripts will be relative to this path. Also this path is relative to the path of the modulerr.js file. Each module's relativePath will be relative to this, and the absolutPath will be relative to the path of the modulerr.js file. HINT: You can get the path by calling the modulePath function :
modulerr.modulePath();
- main - This is the entry point of your application. It must equal a name of a module(more about configuring modules below).
- autorun - When set to true will automatically execute the main module when the window loads. If no main module is specified this setting is ignored. Moreover, when combining the files later on, the main module will be also executed in a callback when the window loads.
- addScriptTags - By default is set to true. If set to false the scripts will not be injected into the browser, Modulerr.js will still try to resolve the modules.
- modules - An array of modules(which are once again json objects) each of which can have the following settings:
- name - The name will be used in many cases, so it is very important, also must be unique. When injecting modules into functions they are injected by their name, so it is recommended to keep them short. When injected into the browser a .js extension is added to the name of the module, so it must equal the name of the file also.
- main - This is the name of the function in the .js file which will be called when the value of the module is needed. By default it is the same as the name of the module, can be omitted.
- dependencies - An array of strings with the names of other modules which this module depends on. They will be loaded before the parent module and will be injected in the function if their name is passed as a parameter. NOTE: You can omit this field and simply add the dependencies to the parameters of the main functions of the modules.
- relativePath - The path where the module is located. This makes the module's path relative to the basePath.
- absolutePath - The path where the module is located. This makes the module's path relative to the modulePath which is the location of the modulerr.js file. You can get it as follows:
modulerr.modulePath();
. - addScriptTag - Tells Modulerr.js whether to insert a script tag for this module. Overrides the addScriptTags property.
- external - If set to true Modulerr.js will not try to resolve its value, instead you should set it.
- value - Used only when the module is external, if is a string will be evaluated with eval.
- combine - This property is used at the final stage of the application when you need to combine the files into one. If set to false it will not be added to the final file. For example, in the sample config below, we do not want to include angular.
- packages - The packages can be used to shorten the writing of numerous json objects for modules which are in the same folder. For example if you have first.js, second.js and third.js in the numbers folder, you
can create an object which has either relativePath or absolutePath which will be applied to all modules in the package and an array of names:
["first", "second", "third"]
. See example below:
Such configuration object looks like this:
{
"basePath": "js/",
"main": "entry",
"autorun": true,
"packages": [
{
"relativePath": "numbers/",
"names": ["first", "second", "third"]
}
],
"modules": [
{
"name": "angular",
"relativePath": "angular/"
"external": true,
"value": "window.angular",
"combine": false
},
{
"name": "app",
"dependencies": ["MainCtrl", "angular"]
},
{
"name": "MainCtrl",
"dependencies": ["angular"]
}
]
}
This configuration will work if our project stucture is as follows:
index.html
modulerr.js
--js/app.js
--js/MainCtrl.js
--js/angular/angular.js
--js/numbers/first.js
--js/numbers/second.js
--js/numbers/third.js
NOTE: All packages's modules are inserted after the originally defined modules and all of them are loaded into the browser in the order they are defined in. In the example above the modules will be added to the browser in the following order: angular, app, MainCtrl, first, second, third.
###Defining modules
Defining modules is as easy as creating a function. Every module has a different file. Every fail contains exactly one function which accepts a number of parameters. Every parameter is another module. The name of the function should either be the name of the respective module or the main. The function can return value. The returned value is injected into the other modules. For example, here is how to create a module which returns the constructor of an object:
//file obj.js
//config - {name: 'obj', main: 'objMain'}
function objMain() {
var obj = function () {
this.prop = undefined;
};
obj.prototype.someFunc = function () {
console.log('someFunc called');
};
return obj;
}
You can then use it in another module as follows:
//file objs.js
//config - {name: 'objs'}
function objs(obj) {
var objectsArr = [];
for(var i = 0; i < 5; i++) {
objectsArr.push(new obj());
}
return objectsArr;
}
###Starting up
The global modulerr object has the run function which will start resolving a chain of dependencies. Accepts the name of a module and whether to forcefully execute the function. The force parameter will resolve the chain even if the browser has not loaded. Usually this operation is queued for when the window is ready.
modulerr.run('main', false);
##Combinerr.js
Combinerr.js is a small script which by given configuration will combine all the scripts into one. What it will essentially do is get the main function from each module, wrap it around EEFI and assign the value of the EEFI to a variable with the same as the module. Also the parameters of the module's function will be removed. So, the following modules:
//mainModule.js
function mainModule(module1) {
return function () {
module1();
}
}
//module1.js
function module1() {
return function () {
console.log('module2');
}
}
Will result in the following combined script:
var module1 = (function module1 {
return function () {
console.log('module2');
}
}());
var mainModule = (function mainModule() {
return function () {
module1();
}
}());
If autorun is enabled the mainModule will be wrapped in a function which will be invoked when the window loads.
####Using Combinerr.js
Using Combinerr.js is fairly easy. You need to simply invoke the script from the command line as follows:
node combinerr.js pathToConfigFile|configAsJson outputPath.js pathTo-modulerr.js[optional]
or if you have installed it with the -g
flag(refer to the Installation section):
modulerr pathToConfigFile|configAsJson outputPath.js pathTo-modulerr.js[optional]
The first option is the json configuration which we talked about a little earlier(scroll up if you can't remember). You can have the very same configuration in a .json file and pass it to both Modulerr.js and Combinerr.js.
The output file in which the modules will be combined.
The path from where Modulerr.js will be taken. It is required only if the two scripts are in different folders.
##Demo application
You can find a real application developed using Modulerr.js on the following address: http://gngeorgiev-blog.herokuapp.com/using-modulerr-js-a-new-way-to-modular-javascript-development/
The files can be found in the root of this repo in the demo folder.
##Testing
Clone this repo, run npm install
and run npm test
. You will need karma and jasmine to run the tests.