Pull to refresh

Comments 27

Да только смысла особого в этой прослойке нет, и без нее получается не больше кода и при этом сохраняется исходный API самого Angular.
Это же совершенно не то, о чем статья. Очень сильная зависимость кода от структуры проекта. angularAMD — ленивая загрузка модулей приложения, где модуль — это контроллер, в котором описаны все зависимости. Реализован как обертка над angular, что не очень хорошо.
В статье описан способ как сделать структуру приложения гибче, и уменьшить зависимость кода от структуры приложения и названия модулей.
Тем более плагины, о которых написано в статье могут использоваться в паре с angularAMD. Получится ленивая загрузка + гибкость структуры и уменьшение кода в описании зависимостей.
А какой вообще смысл от использования RequireJS если у вас уже есть AngularJS? В нем уже реализованы модули, и при использовании AngularJS вы от них никуда не денетесь. Вот и получается лишняя обертка для каждого скрипта. А что касается асихронной загрузки, то когда дело дойдет до продакшена вы все равно будете исользовать RequireJS Optimizer чтобы получить один js файл.
Когда продакшн — да, проект собирается. А во время разработки очень удобно хранить все в отдельный файлах, грубо говоря — один класс = один файл. Тем более загрузка файлов в с помощью RequireJS — на много удобнее, чем менеджить все нужные скрипты в head теге. Так ведь будет всего лишь один подключенный скрипт, а все другие зависимости будут указаны уже внутри скриптов.

Так ведь нету никаких противоречий с модулями AngularJS. Каждый модуль (как на диаграмме в начале статьи) — и есть AngularJS модуль. Суть в том, что он находится в отдельной директории вместе со всеми своими компонентами. А плагины для RequireJS упрощают загрузку модулей, компонентов, уменьшают зависимость кода от структуры проекта и названия модулей, и структура становится более гибкой.
А во время разработки очень удобно хранить все в отдельный файлах, грубо говоря — один класс = один файл.

Само собой, и Вам ничего не мешает так же делать при помощи AngularJS.

Тем более загрузка файлов в с помощью RequireJS — на много удобнее, чем менеджить все нужные скрипты в head теге.

Вы явно забыли про конфиг для RequireJS, в не работы не намного меньше.

Так ведь нету никаких противоречий с модулями AngularJS.

Никто не говори про противоречия, всего лишь лишний код, в который нужно теперь обарачивать каждое объявление любой сущности AngularJS, которые и так принадлежат какому-либо модулю AngularJS.
Само собой, и Вам ничего не мешает так же делать при помощи AngularJS.

Каждый файл и содержит какой либо из компонентов ангулара. Вас смущает то, что он обернут в define функцию?

Вы явно забыли про конфиг для RequireJS, в не работы не намного меньше.

В котором чаще всего описываются пути для вендоров. Пути для юзер сркиптов — очень редко.

Это же на на много удобнее, писать в коде require('relative/path/to/script'); чем писать все это в head теге, да еще и учитывать последовательность подключения.

К примеру у нас приложение есть несколько модулей. Каждый модуль — отдельная часть приложения: projects, emails, advertising и так далее. И уже в самом модуле описаны все зависимости. В RequireJS есть два способ описания зависимостей — передавать параметры в define функцию, или просто реквайрить скрипты внутри функции, в таком случае это будет похоже на CommonJS. И так явно удобнее, чем пихать все head или через менеджить через какие либо утилиты бекенда.

И я еще раз говорю, модуль — логически отдельная часть, которая содержит ngModule и его компоненты — контрллеры, директивы, фильтры, сервисы и так далее. Плагины для RequireJS позволяют максимально отвязать код, от структуры проекта и возможность переносить один компонент из одного модуля в другой без особых изменений в коде (но такие сутации достаточно редкие).
Вы путаете систему модулей и ленивую их подрузку. Это все же разные функции. Что бы не париться о том, в каком порядке подключать файлы, у все уже в самом angular есть ленивое подключение модулей. Поэтому настроить сборку проекта даже при условии что у вас даже фильтры каждый будет в своем файле не так уж и проблематично. Опять же можно автоматизировать все настолько, что сборщик будет сам определять зависимости модулей, выставлять все в нужном порядке и собирать. Причем для разработки можно пересобирать только измеенный модуль и использовать кэш. Хотя на самом деле даже если вы будете собирать все просто конкатенацией всех js файлов в один, то тоже ничего не поломается.

Лично я считаю использование require.js в angular-based проектах избыточным. А по поводу ленивой подгрузки модулей, эта фича обещает быть реализованной в 2-ой версии angular (хотя договориться как и зачем пока не могут) и будет использовать систему модулей из ES6. Для ветки же 1.1 же ленивая подгрузка бесполезна, так как на момент запуска приложение оно должно быть полностью загружено.
А по поводу ленивой подгрузки модулей, эта фича обещает быть реализованной в 2-ой версии angular

Да, вот как раз пост. Там есть куча ссылок на интересные гугл доки.

We’ll see a less complex DI by eliminating the config phase, simplifying the syntax by using declarative-style ES6+ annotations instead of imperative. We’ll enjoy greater capabilities by integrating DI with module loading through ES6 Modules. We’ll also see the ability to lazily-load parts of our JS through child injectors.

Вот ссылка на пример.
Вы путаете систему модулей и ленивую их подрузку

Путаница скорее произошла в том, что ленивая подгрузка != ленивая инициализация.

Лично я не вижу ничего избыточного в использовании AngularJS в паре с RequireJS. И скорее всего, это тема для отдельного хабра топика и дискасса под ним.

А по поводу ленивой подгрузки модулей, эта фича обещает быть реализованной в 2-ой версии angular

И скорее всего, будет не совместимо с AngularJS v1.*
Часто в проекте не весь код для Angular. Могут быть какие-то модели, дополнительные сервисы и просто код, который необходимо использовать в приложении, но при этом код не должен быть зависим от Angular, а должен оставаться переносимым. В стратегической перспективе — это большое преимущество. В общем случае, require.js отвечает за внедрение каких-то общих, независимых от Angular, сервисов, а также «классов» и управление зависимостями на самом общем уровне, а Angular DI отвечает за внедрение «объектов», «экземпляров».

Использование require.js (ну и вообще, JS-модулей, будь то AMD, LMD, CommonJS modules, ES6 Harmony modules) и необходимость в нем никак не меняется с использованием модулей Angular.
Как я понял все модули подключаются сразу? То есть нет возможности в зависимости от роута грузить определенные директивы, фильтры, сервисы?
Да, здесь нету ленивой загрузки. Но она и не нужна, тем более в продакшене.
Во время разработки — все грузится сразу. С этим работают только разработчики.
В продакшене — весь проект минифицируется. Это в любом случае будет лучше.
Делал для себя небольшой загрузчик для angular с помощью requirejs. Он как раз работает на основе роутов. Надо попробоать сжать с помощью RequireJS Optimizer и посмотреть как он будет работать)

Но код для подключения зависимостей примерно так выглядит:

.state('docs',
      lazyLoadProvider.lazy({
        url: '/',
        templateUrl: '/core/views/docs_list.html',
        controller:  'controllers/DocsListCtrl',
        dependencies: [
          'directives/sidebar/sidebar',
          'directives/sidebar/sidebar-scroll-wrapper',
          'directives/breadcrumb/breadcrumbs',
          'directives/add-form/add-form',

          'services/sidebarListService'
        ]
      }))


На выходе он генерирует обычный для ngRoute, uiRoute — объект, с методом resolve в котором и происходит разрешение зависимостей, и пока они не разрешены, роут не срабатывает.

Правда есть минус, что приходится описывать все зависимости в параметре dependencies и нельзя сделать:


define(['myDirective', 'myService'], ....)
Второй раз промахнулся веткой. Хотя точно нажимал «ответить». Ответил Вам ниже.
Ну иногда, в больших приложениях, целые модули подгружаются в момент необходимости — таким образом, после оптимизации получается не один, а несколько файлов, представляющих целые куски системы. Но этот сценарий, скорее, исключение, большинство приложений — это просто один файл и все тут.
Надо попробоать сжать с помощью RequireJS Optimizer

Скорее всего ен выйдет. Оптимайзер ищет строки:
require('/path/to/script');

И подключает их в проект.
Вот разница наглядно:
var scripts =[
  'modules/foo/foo',
  'modules/bar/bar',
  'modules/application/application'
];

for (var i =0 ; i < scripts.length; i++){
  require(scripts[i]);
}

И
require('modules/foo/foo');
require('modules/bar/bar');
require('modules/application/application');


А у Вас как раз зависимости описаны как первом примере.
Может получится если их все прописать в paths

paths: {
    sidebar: 'directives/sidebar/sidebar',
    sidebarScrollWrapper: 'directives/sidebar/sidebar-scroll-wrapper',
    breadcrumbs: 'directives/breadcrumb/breadcrumbs',
    add-form: 'directives/add-form/add-form',
}
Там есть то ли баг, то ли фича, но когда прописываешь компоненты в paths, и внутри этого компонента рекйварить другой компонент — но не будет работать относительный путь. Точнее будет, но считаться он будет от файла, где описан конфиг с paths.
Ох, благодаря этой фиче немало матов было во время первых внедрений require.js :)
Я дико извиняюсь, ну просто совсем мне не понятно для чего же нужно такое.

Допустим я разрабатываю приложение, состоящие из одного модуля. Я вполне себе не привязан к структуре директорий, так как DI в ангуляре по алиасам. В index.dev.html мне совсем не сложно добавить новый script, а в прод уйдет собранная и сжатая версия.

Допустим я разрабатываю многомодульное приложение. В принципе ситуация абсолютно такая же. Для модулей в ангуляре есть DI.

Неужели RequireJS стоит использовать только, чтобы не впихивать при разработке каждый раз новое вхождение script. Все же для меня RequireJS — это впервую очередь разруливание зависимостей, а уже только потом тулза, которая освобождает меня от захламления условного index.dev.html

Другое дело Backbone. Там наверняка must have.

Заранее спасибо тому, кто разъяснит :)
Для Backbone есть Marionette или Chaplin, каждый из которых имеет свою модульную систему. Думаю, не стоит путать модули конкретного приложения и модули JS в целом. Смысл есть для более-менее сложных проектов, при небольшом количестве зависимостей или когда приложение — всего один модуль — выигрыша либо не будет, либо будет незаметным. С другой стороны, привыкнув просто весь код аккуратно заворачивать в модули — обратно уже не тянет, код воспринимается более структурированным и контролируемым.
В добавок к предыдущим комментаторам, предлагаю взглянуть на Yeoman, а именно на его генератор для AngularJS, который в том числе умеет без проблем за вас вставлять вхождение нового скрипта в index.html. При этом, когда выполняется `grunt build`, все автоматически в 1 файл обфусцируется, конкатенируется и т.д.

Просто попробуйте. Использовали RequireJS на проекте с Backbone.js, здесь с AngularJS + Yeoman + Bower + Grunt это действительно не дает никакого выигрыша.

За статью спасибо.
С недавних пор использую browserify. Пишу весь клиентский код в стиле nodejs с его require-ами, а затем browserify пакует все это в один файл. Для dev режима есть поддержка sourcemaps. Таким образом одним пакетным менеджером (npm) убиваем двух зайцев.
У RequireJS один из способов подключения файлов как раз очень похож на CommonJS. Для поиска всех require-ов используется Function.prototype.toString(). То есть перед вызовом функции define — все зависимоти будут подключены. Этот способ на много приятнее, чем описывать все зависимости первым аргументом в define функции.
Плюс 1 за такой подход. Используем исключительно такой метод — на дистанции поддерживать куда проще и исключаются баги с неверной последовательностью параметров в модуле.
Ну тут не суть важно, что использовать. Суть в том, что JS-модули в целом (AMD/CommonJS/ES6) вполне сочетаются с ng-модулями.
Sign up to leave a comment.

Articles