Сборщик проектов на Angular и RequireJS и некоторые мысли по сборке

    Что самое неудобное в сборщиках проекта? Правильно! То, что нужно сборку писать самому. Изучать grunt/gulp/webpack, шаманить с плагинами, думать, как разбить конфиг на модули, когда он вырастает до нескольких сотен строчек, потом несколько месяцев радоваться, что всё работает, а когда в проекте появляется критическое изменение, опять лезть в это болото.

    Мне тоже всё это порядком надоело, поэтому написал сборщик, лишенный этих недостатков. Его gulpfile.js выглядит так:

    var gulp = require('gulp');
    var arjs = require('arjs-builder')();
    
    gulp.task('build', arjs.build);
    gulp.task('test', arjs.test);
    gulp.task('default', arjs.run);
    

    Скопировали себе проект, и больше никогда туда не лезете, и навсегда забываете что такое сборка.
    Единственное, что придется выучить, — это три команды:

    gulp #компилит, поднимает локальные серверы
    gulp build #билдит проект
    gulp test #запускает тесты
    

    Открываете localhost:7000 и наслаждаетесь локальной версией сайта, а в папке build
    уже лежит сбилженная версия.

    — А как же темплейты, их же надо в js внедрять?
    — Конечно! Все внедрено как положено.
    — А я стили пишу на less, sass, stylus, их же надо компилить?
    — Пишите как писали, всё чудесным образом будет работать.
    — А картинки в CSS инклудить?
    — Так давно всё в CSS. All included как в пятизвездочном отеле.
    — А разбить сбилженный файл на модули?
    — Проверьте папку build. Всё по модулям? С уникальными именами, основанными на содержимом файла? Вот, а вы волновались!
    — А вот еще там что-то…
    — И это тоже работает.

    Но как такое возможно? Это мы и рассмотрим в статье. А в конце еще расскажу, почему всё-таки RequireJS

    Структура проекта


    Всегда чем-то приходится жертвовать. В нашем случае это ограничения, накладываемые на структуру проекта и непосредственно результат сборки. Но тут не плакать, а радоваться надо, потому что мы пожертвовали таким злом, как «мне нужна максимальная гибкость и контроль, я всё напишу сам». Оглянемся по сторонам и положа руку на сердце придем к выводу, что большинство разработчиков слабо представляют архитектуру фронтенда сингл-пейдж приложения, не говоря уже о том, как его правильно собирать (в один файл, по модулям, синхронно грузить, асинхронно, быстродействие никто не замерял, никто ничего не анализировал). Да и нужно ли это веб-разработчику? Ради этого он устраивался на работу?

    Ближе к теме. Сборщик предназначен для проектов, основанных на RequireJS и AngularJS. Впрочем, он работает с проектами и на чистом JS и теоретически с любыми другими фреймворками.

    Рабочая директория c вашим приложением будет иметь такую структуру:
    projects/
     ├──project1/
     ├──project2/
     ├──project3/
     ├──files/
     ├──vendor/
     ├──compiled/
     ├──build/
     ├──index.html
     ├──lib.js
     └──lib.css
    .bowerrc
    bower.json
    package.json
    gulpfile.js
    

    project1..3 — папки с проектами. Проект описывает обособленный раздел сайта или отдельный сайт. Проекты могут быть написаны на разных фреймворках или без них. Для проектов может использоваться как общий index.html так и собственный. В приложении среднего уровня будет минимум три проекта:
    • main — основной сайт
    • admin — админка
    • old-browser — заглушка для старых браузеров, написанная на самом примитивном JS

    В больших приложениях может появиться проект lib в котором будут собраны основные модули, использующиеся в других проектах (роутинг, авторизация, работа с ресурсами...).

    В отдельные проекты стоит выносить новую версию сайта (чтобы организовать плавный переход), сборки для A/B-тестирования, временные лендинг-пейджи и т. п.

    В files кладутся файлы, которые не будут вставляться в CSS (кандидаты на перенос на файловый сервер). Остальные — будут преобразованы в base64 и вставлены в стили, даже если это 2ГБ видео. Потому что проект описывает только интерфейс, контент должен браться из других мест.
    В vendor копируются библиотеки из bower.
    В compiled складываются временные файлы для локальной работы (стили, вендорные библиотеки).
    В build собранные проекты, готовые для заливки на сервер.

    Пример index.html можно найти здесь. Он, так же как gulpfile.js, не меняется никогда.
    — А как же мне добавить туда свой скрипт или подключить аналитику?
    — Через массив scripts в конфиге или в соответствующем модуле в проекте. В демо-приложение специально добавил пример с аналитикой и мета-тегами.
    Абстрактное маркетинговое агентство просит добавить Яндекс.Метрику, googleAnalitycs, googleTagManager, счетчики vkontakte, mailru, doubleClick..., и каждому нужно поместить свой скрипт в индекс, и чтобы повыше других, чтобы он там создал свой говно-айфрейм или говно-картинку в один пиксель. А не офигели ли вы, господа? Думаете можно просто так срать в индекс? Теперь все эти выскочки заключены в отдельный модуль и подключаются, только если в конфиге стоит разрешение. Мы же не хотим наблюдать кучу левых запросов при локальной разработке?

    В lib.js находятся микрофреймфорк самые необходимые методы, которые должны быть доступны до загрузки основного фреймворка. Такие как: определение браузера, локали пользователя, загрузка скриптов и проч. По идее, не должно быть необходимости менять этот файл, но пока не настолько его отладил, чтобы гарантировать это.

    Теперь рассмотрим упрощенную структуру отдельного проекта:
    _config/
     ├──default.yaml
     ├──dev.yaml
     └──production.yaml
    module1/
     ├──_tests
     ├──someFolder1/
     │   ├──some.js
     │   ├──style.sass
     │   └──template.html
     ├──someFolder2/
     └──config.js
    module2/
    module3/
    bootstrap.js
    requireconfig.js
    

    Пойдем с конца.
    requireconfig.js — подключает библиотечные файлы к проекту
    bootstrap.js — подключает файлы проекта. Стандартная схема работы require.js
    module1..3 — модули проекта. Во время сборки каждый модуль собирается в отдельный файл
    В _tests лежат тесты, относящиеся к файлам в текущей папке. В качестве тестов рассматриваются файлы, оканчивающиеся на spec.js.
    В config.js описываются зависимости соответствующего модуля
    someFolder может иметь любую структуру (главное, чтобы все зависимости были описаны)
    Если рядом с файлом скрипта лежит template.html или style.сss/.sass/.scss/.less/.stylus, то они будут добавлены в кеш шаблонов или скомпиленый файл стилей. Очень простое правило. Сборщик не тащит что попало, а берет только то, что относится к файлу скрипта в той последовательности, в которой загружаются скрипты.

    Самое интересное — _config
    Здесь хранятся конфигурации для различных окружений. Поддерживаются форматы json, json5, hjson, cson, yaml. Как только IDE начнут поддерживать json5, переведу все примеры на него и оставлю единственным поддерживаемым форматом. В default описываются общие для всех окружений настройки. Остальные конфиги намерживаются на дефолтный.

    Чтобы собрать проект с нужным конфигом нужно указать его имя первым параметром
    gulp --qa
    gulp build --production
    

    По умолчанию берется dev.

    Структура конфигурационного файла:
    {
        public: { ... }, //параметры, доступные в приложении через project.config
        localhost: {
            webserver: { ... }, //настройки локальных веб-серверов
            manifest: { ... } //подключаемые ресурсы для локальной работы
        },
        build: {
            /* общие настройки для всех модулей */
            ...
            manifest: { ... }, //подключаемые ресурсы для собранного проекта
            modules: { ... }, //индивидуальные настройки для каждого модуля, например чтобы vendor сжимался с параметром mangle: true, а стили основного модуля загружались бы отдельным файлом
            copy: { ... } //скопировать в билд какие-то файлы, например robots.txt
        },
        vendor: { ... }, //настройки для сборки вендоров. Например, можно собрать bootstrap или angularStrap со своим набором компонентов
    }
    

    Конфиг, вероятно, самое сложное, что есть в сборщике. Чтобы его представить, лучше посмотреть примеры приложений посложнее, попроще и документацию.

    Почему всё таки RequireJS?


    Конечно, чтобы модули загружались по мере необходимости, а не все разом… Скажет кто-то. Но нет.

    Собранный проект имеет такую структуру:
    vendor-f8acc4024d.js #800КБ
    vendor-9dcd7dad8d.css #100КБ
    common-95dafc6502.js #200КБ
    homepage-2979ff1937.js #30КБ
    news-ebf043aeac.js #10КБ
    ...
    

    Если пораскинуть мозгами, то можно прийти к выводу, что в любом проекте vendor (модуль с библиотечными компонентами) будет иметь самый большой вес около 1МБ (никак ни меньше 500КБ). При этом ленивую загрузку организовать не получится, т. к. все библиотеки должны быть загружены до старта проекта. Конечно, можно его разбить на файлы для каждой библиотеки, но тогда их загрузка забьет все потоки браузера и отложит загрузку остальных файлов проекта, что не принесет значительного выигрыша. Спасает то, что из всех модулей vendor меняется реже всего, поэтому почти всегда он будет браться из кеша.

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

    Следом идут 10—20 модулей для разделов и различной бизнес-логики. Они меняются часто, но весят копейки. Более того, в сумме их вес сравним с весом всех библиотек.

    Для ускорения загрузки и быстрого отображения элементов имеет смысл вынести стилевые файлы из вендора и главного модуля в отдельные модули (сборка позволяет настроить включение CSS в JS и порядок загрузки индивидуально для каждого модуля). В примере на рисунке ниже можно было бы вынести стили модуля payment, т. к. в них включены тяжелые иконки платежных систем.

    А теперь посмотрим, как будет происходить первая загрузка проекта (файлы имеют небольшой вес т. к. включен gzip):
    network

    Хорошо заметно, что пока грузится vendor, успевают загрузиться почти все ресурсы проекта. Т. е. в ленивой загрузке модулей нет никакого смысла. Более того, это замедлит работу сайта, т. к. придется ждать загрузки какого-нибудь 10КБ-го файла, если пользователь перейдет в другой раздел. Другими словами, ни для больших ни для маленьких проектов RequireJS НЕ НУЖЕН!

    Так зачем же он используется? Исключительно для разработки.

    Основное его преимущество в том, что можно легко подключать зависимости и заимствовать компоненты из разных проектов. Например, в админке используется тот же роутинг, те же ресурсы, та же обработка ошибок. Зачем копипастить, если можно просто подключить нужные модули из основного проекта? Это позволяет развертывать новые проекты максимально быстро.

    Второстепенное преимущество в том, что для локальной работы не нужен сборщик (только запущенный сервер). Скрипты не компилятся. Результат доступен моментально, а в больших проектах это многого стоит. А как же Babel, ES6, Coffee, TypeScript? А никак. Сборка создавалась для использования в больших и средних проектах в продакшене. Если у вас университетская исследовательская работа или домашняя страничка, зачем вам вообще сборка? А если всё это в серьезном проекте, да в продакшене… Положим еще раз руку на сердце, вы просто изучаете новые технологии за счет работодателя. По той же причине не поддерживаются никакие html-препроцессоры (хотя это сделать достаточно просто). JS и HTML знают любые веб-разработчики, в отличие от остальных технологий, которые сегодня популярны, а завтра о них все забыли.

    Так как же всё это запустить?


    Устанавливаете глобально bower и gulp:
    npm i -g bower
    npm i -g gulp
    

    Скачиваете упрощенный или полноценный демо проект, набираете в его папке команды:
    npm i
    bower i
    gulp
    

    Открываете localhost:7000, Любуетесь.

    Набираете:
    gulp build --production
    gulp
    

    Открываете localhost:7200, Любуетесь собранной версией для продакшена, которая появится в папке build

    Что-то не заработало?
    Значит npm не загрузил или коряво загрузил модули. Если проблема с Karma, убедитесь, что она и все её плагины находятся в одной папке node_modules. Если не находит node-sass, скорее всего вы недавно обновляли ноду — переустановите все плагины. Нет прав на изменение папки — попробуйте другую консоль. При установке сплошные ошибки, но всё работает/не работает — у вас Винда.

    Планы на будущее


    • Собирать билд можно будет вовсе без RequireJS. Сейчас лишние 17КБ терпимы (по сравнению с весом всего проекта).
    • Упрощение АПИ.
    • Поддержка других фреймворков (не в одиночку).
    • Быстродействие… Хотя и сейчас все процессы происходят в оперативной памяти, а livereload компилит только стили изменившегося модуля.
    • Поддержка многоязычных проектов.
    • Генерация документации из кода.
    • Написать статью об архитектуре проекта на AngularJS. Сейчас была затронута лишь общая структура, которая не объясняет какие модули должны быть в проекте и как они должны быть написаны.
    • Вообще, всё переписать на C++, избавившись от гульпа и проч. (вероятно, не в этой жизни)

    Спасибо за внимание, готов выслушать критику.
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 38

      +9
      Похоже, что вы просто придумали Webpack или Brunch, но менее навороченный в плане фич и возможностей. К тому же, не вполне понятно, зачем/причем тут вообще require.js в том или ином виде — SystemJS (плюс SystemJS Builder) и Webpack замечательно умеют работать с модулями самых разных форматов. Понятно, что там свои конфиги, но все равно неясна ниша этой разработки — немного похоже на brunch (но на базе gulp) и не предлагается ничего кардинально нового.

      И совершенно непонятен тезис насчет
      А как же Babel, ES6, Coffee, TypeScript? А никак. Сборка создавалась для использования в больших и средних проектах в продакшене. Если у вас университетская исследовательская работа или домашняя страничка, зачем вам вообще сборка? А если всё это в серьезном проекте, да в продакшене… Положим еще раз руку на сердце, вы просто изучаете новые технологии за счет работодателя.

      Что бы это вообще значило? То, что все вышеперечисленное — игрушки для студенческих поделок?
        –4
        Это более высокий уровень абстракции. Пользователю предлагается оптимальная структура проекта и оптимальный с точки зрения быстродействия результат сборки. Так же ему не придётся задумываться о поиске и настройке плагинов, т. к. всё что нужно включено в сборщик и настроено. Идея в том, чтобы фронтендщик установил однажды модуль и навсегда забыл о сборке.

        Если webpack или другая технология подойдёт лучше gulp в качестве основы и вы сможете объяснить как её настроить подобным образом — буду благодарен.

        Что касается Babel, ES6 и т. п. то действительно считаю баловством использование в продакшене языков не поддерживаемых основными браузерами. Изучать новые технологии нужно, но бежать впереди поезда не слишком эффективно.
          +4
          >Что касается Babel, ES6 и т. п. то действительно считаю баловством использование в продакшене языков не поддерживаемых основными браузерами.
          Так и bower с gulp'ом тогда баловство. Как там в 2007 было принято — склепал страничку на wordpress/joomla и в продакшен. Да и для 95% простых сайтов даже это перебор.
          >Это более высокий уровень абстракции. Пользователю предлагается оптимальная структура проекта и оптимальный с точки зрения быстродействия результат сборки.
          Webpack помимо всего прочего предплогает намного более высокое быстродействие чем browserify и прочие инструменты gulp экосистемы. Что весьма ощутимо при работе с React, например.
          Не обижайтесь, но использовать ваш велосипед среди базилиона аналогов, нет абсолютно никаких причин. Во многом из-за высокомерного, старперского подхода.
            0
            Так покажите проект на аналогичной технологии. Свой или любой, который нравится. Отовсюду слышу про Вебпак, Реакт, что там всё круто, но не видел ни одного проекта, архитектура которого покрутилась бы год-два в продакшене, чтобы можно было скачать и сразу клепать своё на основе.
              +2
              Так, ну React использует Facebook, Airbnb, Khan Academy, Filpboard как минимум (это первое, что приходит на ум). Вообще, есть целый тред на эту тему. Могу то же самое найти для Webpack, но я полагаю Вы тоже умеете пользоваться поиском.
                –4
                Имею в виду проекты где можно было бы посмотреть код и минимальную документацию к нему. Не думаю, что даже на своих технологиях Фейсбук, Гугл и т. п. смогут развернуть и поддерживать проекты без команды в 1000 высококлассных программистов.
                  0
                  давайте так, покажите мне проект на angularjs в опенсурсе на код которого было бы не стыдно смотреть. Я вот что-то не видел. А те что видел и подходят под описание закрыты NDA.

                  Почти все крутые штуки закрыты NDA.
                    0
                    Так я его и выложил в этой статье! Специально заморочился с примером github.com/tamtakoe/node-arjs-builder-seed
                    Основные вещи настроены, конфиги написаны, общая структура ясна, даже роутинг с ресурсами прикручены, хотя это уже углубление в архитектуру. Конечно, там есть код за который мне стыдно, но его не много и он не столь важен для понимания сути. Скачиваете, запускаете, всё сразу работает и готово к использованию.

                    Что такое NDA? Его используют аутсорсеры, или стартаперы (тот случай, когда все гонят и на развитие не хватает времени, так что сомневаюсь на счет крутых штук). При этом подобные ограничения накладываются на бизнес-логику и узкоспециализированные вещи. Архитектура — слишком обширное понятие — это опыт, который кочует из одной компании в другую, который содержит в себе наработки других людей, в т. ч. открыто опубликованных. Чтобы к тебе прикопались нужно доказать, что написание структуры, сборки и проч. было утверждено в плане разработки, что всё это написано сотрудниками с нуля в соответствии с этим планом (в т. ч. все исследования, переделки и проч.), написано в компании в рабочее время, а не дома, что большинство фишек не позаимствовано из открытых источников, что в этом есть исключительно интеллектуальная собственность компании и она понесла какой-то урон (компаниям важно чтобы с их ноу-хау все было в порядке, а все эти архитектуры им до лампочки). На деле, прицепиться не реально, поэтому писать статьи на общие темы и публиковать компоненты общего назначения можно совершенно безболезненно.
                      0
                      Так я его и выложил в этой статье!

                      вы выложили сид, темплейт проекта. Я так тоже могу: NG6-starter (немного пиара, извините, но это пожалуй лучший темплейт проекта который я пока видел, потому и помогаю его мэйнтейнить).

                      Мой же комментарий был к этой фразе:
                      Имею в виду проекты где можно было бы посмотреть код и минимальную документацию к нему.


                      То есть я говорил о реальных проектах которые можно посмотреть. Архитектура без проекта это просто теория, на практике все чуть подругому да и нагляднее. И нормальных проектов на angular на гитхабе днем с огнем не сыщешь (как и symfony2, reactjs и многие другие годные фреймворки).

                      Архитектура — слишком обширное понятие — это опыт

                      принцип единой ответственности, сегрегация интерфейсов, инверсия зависимостей и все клево. Добавим сюда в контексте ангуляра MVC (или MVA, кому как удобно, не забывая при этом про ViewModel которая только добавляется между View и Model), компоненты, идеи функционального программирования (javascript же) и получаем все что нужно для построения архитектуры UI приложения (angular в конце концов это UI фреймворк).

                      Абстрактно, архитектура приложения это весьма простая штука. Все сводится к балансу между приемлимым уровнем технического долга и удобству поддержки кода. А вот реальные примеры того как это проявляется, какие идеи используются и т.д. это намного интереснее.

                      А сборка проекта — это вообще минимальной важности штука. Оно конечно важно для наших процессов, что бы устранить как можно больше рутины и помогает разработчикам сосредоточиться на главном. Без разницы как оно организовано. Мне вот webpack не нравится но я могу настроить сборку проекта удобно за пару часов, и не париться, в то время как предыдущий свой темплейт проекта я собирал где-то пару дней, и до того уровня удобств которые предоставляют бандлеры типа system.js или webpack там было очень далеко.

                      AMD же по по моему весьма субъективному мнению смотрится в проектах с angular весьма ужасно, как минимум потому что у нас уже есть своя система модулей а синтаксис AMD самый объемный в плане необходимого написания кода. Я использую babel + es6 модули и… все просто работает и все просто удобно.
                        0
                        За NG6-starter огромное спасибо! Есть с чем сравнивать. Напишу о своих впечатлениях. Первое естественно негативное. Даже если опустить, что пару часов пытался его запустить github.com/AngularClass/NG6-starter/issues/65, то код, который увидел поверг в ужас. Тут и gulp и webpack и lodash'евский шаблонизатор и ES6 c Babel'лом и страшные конфиги. Чтобы весь этот стек поддерживать нужно знать уйму технологий. И, вообще, зачем весь этот сборочный хлам держать в каталоге приложения, а не в node-modules?

                        Из-за Babel livereload работает дольше. Как делать билд для продакшена (по модулям с md5 именами) так и не понял. Документация молчит.

                        Чем ES6-модули принципиально лучше AMD-модулей? На пару скобок меньше писать в каждом файле? Это из разряда, что плохому танцору всегда что-то мешает. Можно сравнить:
                        import angular from 'angular';
                        import uiRouter from 'angular-ui-router';
                        
                        let aboutModule = angular.module('about', [
                          uiRouter
                        ])
                        
                        .config(($stateProvider) => {
                          "ngInject";
                          $stateProvider
                            .state('about', {
                              url: '/about',
                              template: '<about></about>'
                            });
                        })
                        
                        export default aboutModule;
                        

                        define([
                        
                          'app'
                        
                        ], function(app) {
                        
                          app.config(function($stateProvider) {
                            $stateProvider
                              .state('about', {
                                url: '/about',
                                template: '<about></about>'
                              });
                          });
                        })
                        

                        Библиотечные зависимости типа uiRouter зачем-то тянутся в каждый компонент. В статье даже графиком проиллюстрировал, что все библиотеки лучше собирать в один файл и подключать ко всему проекту разом. Создавать для каждого компонента отдельный модуль излишне в Angular 1.x, потому что все сервисы в глобальной области видимости. Объявлять в конструкторе каждого контроллера его имя, вообще, суровый костыль. Из-за всех этих условий пришлось генератор компонентов написать, потому что создавать вручную — много мороки. Лучший генератор всех времен и народов — копи-паст. Надеюсь, они к этому придут.

                        Разбивать структуру на common и components — плохое решение (уже проходили). Сначала в common'е navbar, потом footer, потом news в footer, потом раздел news в components и всё — пересечение — половина компонентов в common перетечет. Лучше делать однородную структуру (+ с ней легче работать), разбитую по бизнес-логике, а не синтетически. А уже в каждом из ее компонентов делать вложенные, если нужно. Таким образом в user могут быть login и register, которые могут использоваться в том же navbar для отображения формы входа/регистрации.

                        Из хорошего могу отметить направленность на компонентный подход (тоже приду к этому). Но ребята явно бегут впереди лошади. Ангуляровцы всего неделю назад выкатили module.component. С этого момента можно только начать подумывать над подобной архитектурой. В противном случае всё выливается в кучу никому не нужных костылей. Проект явно исследовательский, продакшеном тут и не пахнет.

                        Еще страничка Browsersync ничего такая. Можно развивать это направление.

                        По поводу «архитектура без проекта — теория». Уверен что большинство темплейтов появились не из пустого место, а выросли из нескольких проектов, так что не просто теория :-)
                          0
                          Тут и gulp и webpack и lodash'евский шаблонизатор

                          gulp в качестве таск раннера, webpack — бандлер. FYI webpack это не замена gulp, это сборщик модулей и только. Что до lodash — это скафолдинг для генерации компонентов, что бы уменьшить количество рутины. С тем же успехом можно было бы использовать yoman но у меня еще руки не дошли вынести это все в yo (обсуждали в gitter). С прагматичной точки зрения решение более чем вменяемое на данный момент. Опять же пулреквесты мы приветствуем.

                          Из-за Babel livereload работает дольше

                          Инкрементные билды в плане. Справедливости ради вариант с systemjs + http2 (для разработки) работает пошустрее за счет кеширования.

                          Чтобы весь этот стек поддерживать нужно знать уйму технологий.

                          угу, gulp знают все, lodash — там только шаблончики подправить. Опять же я не знаю людей которые не работали с ледашевскими шаблонами, да и как бы для кодогенераии альтернатив не много. Что до webpack — я бы срадостью заменил это дело на jspm + system.js но на данный момент webpack справляется хорошо, а у jspm до сих пор есть небольшие проблемки (которые надеюсь скоро устранят).

                          Как делать билд для продакшена

                          Продакшен билды в плане. Я только на днях нашел время добавить ng-annotate, на следующей неделе планирую добавить prod настройки для webpack. В целом же в документации по webpack все это описано.

                          С этого момента можно только начать подумывать над подобной архитектурой.

                          С чего бы это? Компонентный подход потихоньку обкатывают уже начиная с angular 1.2. Я уже где-то год так делаю. В 1.5 они просто вкатили упрощенный вариант управления этим что бы упростить миграцию на angular2.

                          Чем ES6-модули принципиально лучше AMD-модулей?

                          Тем что они читабельнее и являются частью стандарта. У AMD преимуществе перед ними нет никаких (почти). Я сейчас готовлю маленький PR что бы чуть упростить управление модулями (я ng6-starter уже на 4-х проектах использую и конечно же у меня уже побольше всего понапридумано).

                          Можно сравнить:

                          нельзя. Вы забыли объявление модуля, зависимости и т.д. Вы же не используете один модуль на все приложение?

                          Я же например планирую переделать все это так:

                          import angular from 'angular';
                          import uiRouter from 'angular-ui-router';
                          
                          export default angular
                            .module('about', [
                              uiRouter
                            ])
                            .config(($stateProvider) => {
                              "ngInject";
                              $stateProvider
                                .state('about', {
                                  url: '/about',
                                  template: '<about></about>'
                                });
                            }).name;
                          


                          Разбивать структуру на common и components — плохое решение (уже проходили).

                          Я тоже проходил это и в итоге вернулся. Выношу туда все то что можно потом вынести в отдельный репозиторий (например фильтрики по датам и другие не привязанные к приложению UI компоненты). Причем чаще я все это просто выношу постфактум из components в common.

                          Что там куда перетекать должно мне лично не понятно. Либо у вас в common не независимые компоненты либо не знаю что еще. Достаточно просто указать зависимости от навбара в модуле news и все хорошо.

                          разбитую по бизнес-логике, а не синтетически

                          Все просто, в components application-specific UI компоненты, в common какие-то общие вещи не привязанные к конкретному приложению. Бизнес логика (сервисы) у меня сейчас вообще отдельно лежат, не привязываясь к компонентам и ангуляру в принципе.

                          Таким образом в user могут быть login и register

                          Ну так оно как-то так и должно быть. А вот контрол «repeat password» или «view password» можно уже положить в common. Или эта идея звучит бредово?

                          продакшеном тут и не пахнет.

                          2 проекта на этом шаблоне (естественно допиленные) в продакшене уже, все хорошо, полет нормальный, скорость разработки и поддержки кода по сравнению с другими шаблонами (своими и чужими) сильно выше.

                          Уверен что большинство темплейтов появились не из пустого место

                          Конечно же не из пустого места, но я говорил об архитектуре а не о структуре директиторий и т.д.
                            0
                            Или эта идея звучит бредово?
                            «repeat password» или «view password»… В моем случае директива поля ввода пароля с глазиком лежит в common/components/form/password как элемент абстрактной формы. Ничего бредового.

                            Инкрементные билды в плане...
                            В Вебпаке легко разбить билд на файлы и добавить хеш к имени, но при ограничении количества бандлов будет склеивать друг с другом наиболее мелкие, что негативно скажется на кешировании (редко меняющиеся зависимости могут оказаться в одном файле с часто меняющимися). Описывать структуру бандлов в конфиге, даже для среднего проекта с парой сотен зависимостей, чересчур. От ленивой загрузки так же придется отказаться. Во-первых, она не поддерживается Ангуляром (без костылей), во-вторых, на практике, даже в огромном проекте из нескольких разделов больше половины кода грузится сразу и остается 10-20 кусков-разделов, подгружаемые лениво, общий вес которых таков, что проще сразу загрузить и не морочить голову. Возможно, плохо читал документацию, но простого решения этой задачи Вебпаком не нашел.

                            Я же например планирую переделать все это так:
                            Пометил вещи, которых не должно быть в объявлении компонента:
                            import angular from 'angular';
                            import uiRouter from 'angular-ui-router'; //Зачем глобальные зависимости в каждом компоненте?
                            
                            export default angular
                              .module('about', [ //В крайнем случае включить uiRouter, ngResource и проч. в lib
                                uiRouter //и подключать везде его,
                              ]) //но и это попахивает костылем
                              .config(($stateProvider) => {
                                "ngInject"; //Лишнее
                                $stateProvider
                                  .state('about', {
                                    url: '/about',
                                    template: '<about></about>'
                                  });
                              }).name; //Зачем разработчику помнить, что нужно всегда экспортировать name?
                            

                            на днях нашел время добавить ng-annotate
                            Обязательно сделайте пример с одновременным использованием angular-bootstrap и angular-strap. У них пересекается сервис $tooltip и их совместное подключение разруливается исключительно ng-annotate.

                            Интересный проект. Буду следить, как развиваете компонентный подход и используете технологии типа webpack, systemjs, jspm, на которые пока серьезно не смотрел.
                              0
                              Зачем глобальные зависимости в каждом компоненте?

                              Ну как зачем, потому что это не глобальные зависимости а зависимости конкретного модуля. Я обычно если много похожих зависимостей появляется выношу это все дело в один модуль (app.deps например) но не люблю это делать.

                              //Лишнее

                              не уверен на 100% — пусть будет. Я добавил там ng-strict-di еще что бы детектить где надо это добавить. Сам же я добавляю метки для ngAnnotate почти всегда. Мне проще добавить метку чем расстраиваться что оно не подхватило это дело.

                              //Зачем разработчику помнить, что нужно всегда экспортировать name?

                              Потому что пока мы не на angular2 нам приходится за этим следить самостоятельно и экспортировать только имена модулей. Между прочим так сделано почти во всех крупных модулях для ангуляра.
                0
                Слышать то мало, надо вникать. У нас angular + webpack (babel, stylus, jade). Перешли с gulp на webpack и стали очень счастливыми людьми. Всё на продакшене, всё хорошо.
                  0
                  Можете показать код сборки (можно в личку, если секретно)
                  0
                  Сходу sellercrowd.com не совсем мой, но на react/webpack и в продакшене. Ну а позиция: я не видел, значит этого нет — позиция невежды.
                    0
                    Специально статью написал, чтобы собрать фидбек и узнать об аналогах)
                0
                А TypeScript? А Coffeescript? Тоже баловство, получается? Babel отлично работает и ни разу не было ситуации с тем, что где-то что-то пошло не так.

                Если webpack или другая технология подойдёт лучше gulp в качестве основы и вы сможете объяснить как её настроить подобным образом — буду благодарен.

                Как минимум webpack из коробки поддерживает commonjs модули. То, что сделали вы, у нас занимает около 70 строк, у вас же около 500.
                  0
                  Кофескрипт, вообще, первый показатель того, что человека не стоит брать на работу по причине неадекватности. Как правило, это люди, пришедшие с бекенде или языков с похожим синтаксисом, которым лень освоить обычный js, либо те кто без разбору хватается за всё новое, пытаясь сэкономить на спичках вместо того чтобы писать по сути лучший код. (Сорри, если кого-то задел. Это субъективные наблюдения)

                  За Тайпскриптом наверняка будущее, но оно настанет не раньше чем через 3 года. Недавно специально прошёлся с поиском по своим проектам и по популярным фреймворкам, чтобы узнать в скольки местах можно применять новые фишки. Оказалось, что классов в проектах используется не больше 10 штук, стрелочные функции были нужны в ~5 местах и остальной сахар так же не настолько уж необходим.

                  Про commonJs и AMD та же история. Синтаксисы имеют одинаковую сложность, только AMD работает без компиляции. История о том, что можно использовать одни и те же модули на фронтендщик и на ноде не выдерживает никакой критики. У них совершенно разный код в 99,9% случаев.

                  Стандартная просьба. Покажите, пожалуйста, ваши 70 строчек. Не скажу, что горю желанием поддерживать очередную библиотеку. Если найду решение лучше — возьму на вооружение.
                    +3
                    Это уж слишком субъективные наблюдения. Что Coffee, что ES6-7 Babel будут в разы продуктивнее и удобнее нативного JS (ES4-5). В результате код будет на порядок быстрее писаться, быстрее читаться и быть вне конкуренции по качеству написания. И в 90% использующий знает JS, т.к. в перечисленных мною выше без знаний оного не обойтись.

                    P.S. Что касается TS — если не вдаваться в детали — это лишь небольшая надстройка над Babel + Flow.
                      –1
                      Coffee баловство, TypeScript нет.
                        0
                        А что отличает «баловство» от «не баловства»?
                          +1
                          Не баловство приносит ощутимую пользу, которая перевешивает накладные расходы использования абстракий от JS (усложнение инфраструктуры сборки, осваивание дополнительного синтаксиса, поиск экспертов в команду знающих эти ваши свистопределки, и прочее). Так вот, кофи по крайней мере в наше время, не нужен, изначально может быть для кого-то в нем и был смысл (не для меня). TS потенциально приносит больше пользы, так что его можно использовать.
                            0
                            Кофе, зная JS, можно изучить за пару дней при этом пользы он приносит в разы больше нативного JS. Так что следуя вашей логике — JS это откровенное баловство.

                            Если у вас непереносимость синтаксиса — так и скажите, но при выборе одного из двух — TS vs. Кофе я бы однозначно сделал ставку на кофе, в нём больше удобств, которые позволяют писать более лаконичный и чистый код.

                            При сравнении всех существующих решений я бы выстроил их так (в порядке удобства использования):
                            1) ES6-7 Babel
                            2) CoffeeScript
                            3) Haxe
                            4) TypeScript
                            5) Native JS

                            P.S. Предпоследнее место TS просто из-за слишком сильных ограничений в типах, когда на это тратится существенно больше времени, чем непосредственное написание кода.
                              +1
                              Кофи себя давно изжил и спорить здесь не о чем, TS дает реальные преимущества (особенно для больших проектов), кофи лишь сахарок, для меня этот сахарок не стоит того чтобы его внедрять в проекте. Делать ставку на кофи в конце 2015 года глупо.

                              ps dart забыли
                                –1
                                ES6-7 Babel, CoffeeScript, TypeScript, Native JS
                                Проблемы есть у всех вышеперечесленных, ES6 Babel — браузеры ещё не поддерживают ES6 (ES7) полностью, поэтому его придется компиллировать в ES5 ещё долгое время для всех браузеров, а Babel дает не «лучший» код (хотя он имеет ряд опций для этого), но для написания веб-приложений это не важно, это может быть важно при написании критичных к скорости участков, Babel можно смело пробовать для приложений.

                                CoffeeScript и TypeScript — оба «сахар», их оба нельзя будет запустить не компиллируя, они дают свои плюшки и проблемы, в CS есть генераторы и нет async/await, в TS есть async/await, но нет генераторов, CS дает лакончиность и краткость, но его многие не переносят, TS дает «типы» и тулзы, но его многие не любят за «многословность».
                                Они не в одном ряду с Babel (разные цели), они могут использоваться с Babel совместно (CoffeeScript/TypeScript -> ES7 Babel -> ES5).

                                CoffeeScript хорош, но у него есть проблемы со впихиванием фичей из ES7 и из-за этого он будет угасать, и сообществу пора инициировать CoffeeScript 2, иначе CS может вымереть.

                                С Native JS итак все ясно.

                                Вообщем, как обычно — идеала нет.
                                  0
                                  Ну над CS вместе с плюшками ES давно ведётся работа вроде такого: https://github.com/jashkenas/coffeescript/pull/3813 в версии 1.10 добавили ES6 деструктуризацию. Но в целом согласен, когда появился babel — кофе значительно начал проигрывать. По-этому я и написал его вторым в списке, т.к. при выборе между Babel и Coffee — выбор мой однозначно за первым.
                            0
                            Coffee — оптимизация процессов под быструю разработку, TypeScript — для крупных проектов. Babel — что-то среднее.
                            +2
                            поддержку, кофи протух и вооще не стоит внимания в наше время
                          +2
                          Что касается Babel, ES6 и т. п. то действительно считаю баловством использование в продакшене языков не поддерживаемых основными браузерами. Изучать новые технологии нужно, но бежать впереди поезда не слишком эффективно.

                          Последняя утвержденная спецификация языка для Вас — «бежать впереди поезда»?

                          Я не хочу никого обидеть, но затем создавать приложения на стеке умирающих технологий? Когда выйдет Angular 2, про первый будут помнить разве что те, у кого всё приложение в данный момент завязано на него, а что касается requirejs, то несмотря на свою дикую популярность 4 года назад, на нынешний день имеет на 100 000 скачиваний в месяц меньше, чем webpack и, на секундочку, на ~2 233 089 скачиваний меньше, чем browserify.

                          Вы так интересно рассуждаете о технологиях — «сегодня популярны, а завтра — забыли», но ведь уже «сегодня» про requirejs забыли, а про angular 1.x забудут, считай что «завтра».
                            0
                            Не стоит так переоценивать angular2. Это не более чем еще один js фреймворк, коих сейчас очень много. То, что в его названии есть слово angular я воспринимаю просто как маркетинговый ход. Каким бы плохим не был angular1, ему удалось создать вокруг себя сообщество, а это куда важнее «академической правильности», новизны, или даже отсутствия багов.

                            Про переезд python 2->3 в 2008-м тоже говорили «Да пару лет, и все забудут про вторую версию».
                            Но сообщество языка/фреймворко обычно гораздо более инертно, нежели работа авторов. И вот сейчас уже 2015, а нового продакшн-кода под python2 создается раза в 2 больше, чем под python3.
                              0
                              Именно по этому стараюсь делать сборщик, да и архитектуру приложения под технологии, а не под фреймворки. Т.е. Он работает с проектами поддерживающими DI (просто сейчас это реализовано через RequireJS), проектов с веб-компонентами (реализация ангуляровскими директивами), ORM (ангуляровскими ресурсы), кеширование (http/templateCache). В самом проекте свожу использование фишек Ангуляра к минимуму, например, никогда не используются ng-controller и ng-include (всё через роутер), никогда не используется $http (всё через $resource). Это позволит легко перейти на Angular2, а если он не выстрелит, на что-то другое. Потому что фреймворки меняются, а технологии остаются :-) Напишу подробнее в статье по архитектуре.

                              RequireJS и Gulp всего лишь инструменты для реализации идеи. Их можно и заменить.

                              P.S. Последняя утверждённая спецификация- это бежать впереди поезда. Ехать на поезде — это спецификация, поддерживаемая основными браузерами
                                0
                                Возможно на счёт поездов Вы и правы, только текущий «вагон» ну ни разу не удобен, когда уже пристрастился к люксовуму ES6\7, который, между прочим бесплатный и проверенный временем в боевых проектах.
                              0
                              Пользователю предлагается оптимальная структура проекта и оптимальный с точки зрения быстродействия результат сборки.


                              Знаете я тоже когда-то страдал подобным «перфекционизмом» а потом мне надоело. Сборка проекта — это второстепенная штука, часть инфраструктуры. Все что должна делать сборка — собирать проекты, быть неприхотливой к поддержке и т.д. бандлеры вроде webpack/system.js с этим справляются наура.

                              Если webpack или другая технология подойдёт лучше gulp в качестве основы


                              gulp — это таск раннер и только. Его задача — предоставить пайплайн для сборки. Webpack — это бандлер, его задача взять все ваши модули (js файлики, можно jade/html файлики, стили и т.д.) и собрать в соответствии с графом зависимостей и т.д.

                              вы сможете объяснить как её настроить подобным образом

                              подобным образом — не уверен что в этом есть смысл. Мне нравится та структура проекта которую я использую (потому что я могу эффективно делать свою работу не парясь по поводу сборки). Да конечно иногда коребит что есть не совсем православные вещи, но это опять же все определенные уступки в пользу скорости разработки. В конце концов jspm + system.js решают те же проблемы более православно.

                              использование в продакшене языков не поддерживаемых основными браузерами

                              Тогда давайте не будем использовать css с вендорными префиксами. Или js api с вендорными префиксами (хотя с этим сейчас проще).

                              babel транспайлит все в ES5, который более чем поддерживается основными браузерами. А то ускорение в плане разработки и повышение поддерживаемости кода более чем окупает «баловство». Вы же пользуетесь полифилами, да?
                                0
                                Смотря что имеете в виду под полифилами. За глаза хватает того, что предлагает Angular и lodash. От jQuery уже избавились (lodash на очереди). В том-то и дело, что ES6 фишки далеко не так сильно востребованы как об этом пишут. Классы и какие-то сложные вещи не нужны, потому что Angular и архитектура проекта берут это на себя и бизнес-логика описывается простым кодом. А сахар… Можно и без него прожить.

                                Резко высказался. Я не против ES6, Babel и т. п. Я против того, чтобы использовать эти вещи для разработки. Если последний Хром поддерживает ES6, то пусть разработчики отлаживают в нём, а сборщик просто соберет финальный билд под ES5 или соберет специальную версию для старых браузеров (сейчас это не поддерживается, но потом добавлю), Babel в роли Autoprefixer для JS вполне катит.

                                На счет Webpack всё жду, когда кто-нибудь напишет: Вот наш конфиг для Вебпака, который делает примерно то же самое, но без кучи самописных вещей :-)

                                На счет структуры проекта, жду когда кто-нибудь выложит свою структуру. Пусть с костылями, пусть не на Ангуляре. Просто не с чем сравнивать.
                            +1
                            Собирать билд можно будет вовсе без RequireJS

                            Посмотрите в сторону almond.js
                              0
                              Клевая штука, нужно обязательно заюзать у себя! Но так до конца и не понял:
                              В нашем случае это ограничения, накладываемые на структуру проекта

                              Вы парсите html файлы? Если да, тогда зачем что-то ограничивать, можно распарсить и выявить все зависимости по цепочке. Если нет, тогда почему не парсите? Можно какой-нибудь утилитой сначала составить список всех файлов в проекте, чтобы найти все html`ки.
                                0
                                Сборка начинается с того, что по цепочке зависимостей вытягиваются js-файлы. Далее рядом с каждым js-файлом ищется файл template.html и style.css (styl, less,...). Если находится, то теплейт добавляется в $templateCache Ангуляра, а стиль в файл со всеми стилями. Такая выборочность позволяет отключать любые части от проекта не удаляя отключенные файлы из проекта (достаточно убрать их из зависимостей). Также можно заимствовать какие-то модули из других проектов и быть уверенным что вместе с ними загрузятся их шаблоны и стили.

                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                              Самое читаемое