# ModuleJS

### Введение
ModuleJS — это модульное управление JavaScript, совместимое со спецификациями CMD, AMD и UMD.

### Установка

```
npm i silis-modulejs
```

### Размер файла
|Имя файла|Размер файла|Описание файла|
|--|--|--|
|module.min.js.zip|1.18 кБ|Сжатый JavaScript-код + ZIP-сжатие для сред окружения с более высокими требованиями к сети|
|module.min.js|2.4 кБ|Сжатый JavaScript-код, используется в производственной среде|
|module.js|7.3 кБ|Исходный JavaScript-код, используется для разработки и тестирования|

### Определение модуля

1. Определение модуля
```
define(function(){
    ...
})
```

2. Определение псевдонима модуля
```
define("myModule.js", [], function(){
    ...
})
```

### Экспорт модуля

1. Экспорт модуля через `return`
```
define(function(){
    return ... // Экспортирование модулей любого типа данных
})
```

2. Экспорт модуля через `exports`

- По умолчанию зависит от экспорта `exports`
```
define(function(require, exports, module){
    exports.sayHello = ...
})
```

- Указание зависимого экспорта для экспорта модуля

```
define(["exports"], function(exports){
    exports.sayHello = ...
})
```

3. Экспорт модуля через `module.exports`

- По умолчанию экспортирование модуля зависит от `module.exports`
```
define(function(require, exports, module){
    module.exports = ...
})
```

- Указание зависимости `module.exports` для экспорта модуля

```
define(["exports"], function(exports){
    module.exports = ...
})
```

4. Экспорт модуля через глобальную переменную

```
(
    (typeof window === "object" && window) ||
    (typeof global === "object" && global)
).myModule = ... // Экспортирование модулей любого типа данных
```### Импорт модуля

1. Синхронный импорт модуля

- Синхронный импорт одного модуля
```
var myModule = require("myModule.js");
```
или
```
var myModule = require("myModule.js", false);
```

- Синхронный импорт нескольких модулей
```
var myModule1 = require("myModule1.js");
var myModule2 = require("myModule2.js");
```
или
```
var myModule1 = require("myModule1.js", false);
var myModule2 = require("myModule2.js", false);
```

2. Асинхронный импорт модуля

- Асинхронный импорт одного модуля
```
require("myModule.js", function(myModule){
    ...
});
```
или
```
var myModulePromise = require("myModule.js", true);
myModulePromise.then(function(myModule){
    ...
});
```

- Асинхронный импорт нескольких модулей
```
require(["myModule1.js"...], function(myModule1...){
    ...
});
```
или
```
var myModulesPromise = require(["myModule1.js"...], true);
myModulesPromise.then(function(modules){
    var myModule1 = modules[0];
    ...
});
```

### Взаимозависимый модуль

1. Импортировать взаимозависимые модули заранее
```javascript
define(["dependentModule1.js"...], function(dependentModule1...){
    var mainModule = {
        subModule1: dependentModule1
    };

    return mainModule;
});
```

2. Импортировать синхронизирующийся взаимозависимый модуль после отправки

```
define(function(){
    var mainModule = {
        subModule1: require("dependentModule1.js")
    };

    return mainModule;
});
```

3. Импортировать асинхронные взаимозависимые модули после отправки
```
define(function(){
    var mainModule = {};

    return require(["dependentModule1.js"...], function(dependentModule1...){
        mainModule.dependentModule1 = dependentModule1;
        return mainModule;
    });
});
```

### Пример спецификации AMD

> Спецификация AMD относится к асинхронному определению модулей (Asynchronous Module Definition), то есть модуль загружается асинхронно.Спецификация AMD определяет модули:

```javascript
define(function() {

    return function(text) {
        setTimeout(function() {
            document.body.innerText = text;
        }, 100);
    }

});
```

Файл кода: `/example/print-amd-module.js`

```javascript
define(["print-amd-module.js"], function(print) {

    return {
        sayHello: function() {
            print("Привет, модуль, определённый моей спецификацией AMD");
        }
    }

});
```

Файл кода: `/example/hello-amd-module.js`

Асинхронная загрузка модулей, определённых спецификацией AMD:

```html
<html>
    <head>
        <script>
            require(["hello-amd-module.js"], function(helloAmdModule) {
                helloAmdModule.sayHello();
            });
        </script>
    </head>
    <body>
        Асинхронная загрузка модуля...
    </body>
</html>
```

Файл кода: `/example/async-load-amd-module-example.html`

### Пример спецификации CMD

Спецификация CMD относится к общему определению модулей, то есть модуль загружается синхронно.

Определение модуля в спецификации CMD:

```javascript
define(function(require, exports, module) {

    module.exports = function(text) {
        setTimeout(function() {
            document.body.innerText = text;
        }, 100);
    };

});
```

Файл кода: `/example/print-cmd-module.js`

```javascript
define(function(require, exports, module) {

    exports.sayHello = function() {
        var print = require("print-cmd-module.js");
        print("Привет, модуль, определённый моей спецификацией CMD");
    };

});
```

Кодовый файл: `/example/hello-cmd-module.js`

Синхронная загрузка модулей, определённых спецификацией CMD:

```html
<html>
    <head>
        <script>
            var helloCmdModule = require(["hello-cmd-module.js"]);
            helloCmdModule.sayHello();
        </script>
    </head>
    <body>
        Загрузка синхронного модуля...
    </body>
</html>
```> Кодовый файл: /example/sync-load-cmd-module-example.html


### Пример спецификации CMD

```
((root, factory) => {
    if (typeof define === "function" && define.amd) {
        // AMD
        define(["dependentModule1", "dependentModule2"...], factory);
    } else if (typeof exports === 'object') {
        // CommonJS
        module.exports = factory(require("dependentModule1"), require("dependentModule2")...);
    } else {
        root.currentModule = factory(root.dependentModule1, root.dependentModule2);
    }
})(
    (typeof window == "object" && window) || (typeof global == "object" && global),
    (dependentModule1, dependentModule2...) => {
        // todo
    }
)
```