Целью было создать приложение с модульной и гибкой архитектурой (ну скорее просто разбиение приложение не логические части), с простым и понятным описанием зависимостей между частями приложения и уменьшить зависимость кода от структуры приложения.
Модуль
В данном случае, это логически отдельная часть приложения, включающая в себя набор компонентов:
- ngModule;
- Controller;
- FIlter;
- Directive;
- Service;
- Template;
- Configs — содержат config() и run() методы для текущего ngModule.

Проблема
При использовании RequrieJS, файлы приложения чаще всего подключаются как-то так:
require('modules/foo/controller/foo-controller.js'); require('modules/foo/service/foo-service.js'); require('modules/foo/directive/foo-controller.js'); require('text!modules/foo/templates/foo.html'); require('modules/bar/directive/bar-controller.js');
Здесь есть явные минусы:
- Код очень зависит от структуры проекта;
- Код очень зависит от названий модулей;
- Достаточно много нужно писать руками.
Решение
Были написаны RequireJS плагины для загрузки компонентов модуля.
К примру есть такая структура приложения (кстати, очень похожая на структуру бандлов в Symfony2):
app |-modules | |-menu | | |-controller | | | |-menu-controller.js | | |-menu.js | | | |-user | |-controllers | | |-profile.js | |-resources | | |-configs | | | |-main.js | | | | | |-templates | | | |-user-profile.html | | |-directives | | |-user-menu | | |-user-menu.js | | |-user-menu.html | |-src | | |-providers | | | |-profile-information.js | | |-factory | | |-guest.js | |-user.js | |-application.js |-boot.js
В данном случаем у нас есть 2 модуля: user и menu. Файлы /app/modules/menu/menu.js и /app/modules/user/user.js — скрипты с инициализацией angularJS модулей. Все остальное — думаю понятно.
Теперь нужно задать конфигурацию для подключения всех компонентов. Делается это с помощью requirejs.config:
requirejs.config({ baseUrl: '/application', paths: { 'text': '../bower_components/requirejs-text/text', // Structure plugins: 'base': '../bower_components/requirejs-angualr-loader/src/base', 'template': '../bower_components/requirejs-angualr-loader/src/template', 'controller': '../bower_components/requirejs-angualr-loader/src/controller', 'service': '../bower_components/requirejs-angualr-loader/src/service', 'module': '../bower_components/requirejs-angualr-loader/src/module', 'config': '../bower_components/requirejs-angualr-loader/src/config', 'directive': '../bower_components/requirejs-angualr-loader/src/directive', 'filter': '../bower_components/requirejs-angualr-loader/src/filter' }, structure: { prefix: 'modules/{module}', module: { path: '/{module}' }, template: { path: '/resources/views/{template}', }, controller: { path: '/controllers/{controller}' }, service: { path: '/src/{service}' }, config: { path: '/resources/configs/{config}' }, directive: { path: '/resources/directives/{directive}/{directive}' }, filter: { path: '/resources/filters/{filter}' } } });
Все пути каждого компонента определены в рамках модуля. Поле structure.prefix — путь к корню модуля, после baseUrl.
Теперь, если мы хотим подключить файл /app/modules/user/user.js из:
1. /app.js:
require('module!user')
2. /app/modules/user/controllers/profile.js:
require('module!@')
В рамках одного модуля — имя модуля можно не писать, достаточно символа ‘@’. Тем самым, если придется переименовать модуль — не нужно будет менять код.
Теперь, если мы хотим подключить файл /app/modules/user/controllers/profile.js из:
1. /app.js:
require('controller!user:profile')
До двоеточия — название модуля, после двоеточия — название контроллера.
2. /app/modules/user/user.js:
require('controller!profile')
В рамках одного модуля — имя модуля можно не писать, достаточно указать только название контроллера. Так же, если контроллер лежит на уровень ниже, то возможно подключать так:
require('controller!additional/path/to/profile')
Точно так же и для всех других компонентов.
Результат
Получилось очень гибкая структура приложения с поддержкой разделения кода на модули и с минимальной зависимостью кода от структуры проекта даже если придется перенести какой либо компонент из одного модуля в другой — то практически ничего менять не придется. И лишнего кода так же стало меньше.
Так же не возникает никаких проблем при сброке проекта. В тестовом приложение есть пример собранного проекта в папке /build и Gruntfile для сборки, но в нем нету ничего не обычного.
Ссылки:
- Репозиторий с плагинами — requirejs-angular-loader. Устанавливать можно с помощью bower;
- Репозиторий с тестовым приложением — tuchk4/requirejs-angular-loader-bootstrap.
Данный подход используем в большом корпоративном приложении, поддержка и развитие данного подхода будет поддерживаться и развиваться.
ссылка на оригинал статьи http://habrahabr.ru/post/216469/
Добавить комментарий