Одна из особенностей Angular, присущая и первой и новой версии — высокий порог вхождения. Новый Angular, помимо всего прочего, трудно даже запустить. А и запустив, легко получить 1-2 Мб скриптов и порядка нескольких сотен запросов при загрузке hello world страницы. Можно, конечно, использовать всякие стартеры, seed'ы или Angular CLI, но для использования в серъезном проекте нужно самому во всем разбираться.


В этой статье я постараюсь описать, как настроить удобную среду разработки с использованием SystemJS, и production сборку Angular приложения на основе Rollup, с выходом около 100кб скриптов и нескольких запросов при открытии страницы. Использовать будем TypeScript и SCSS.


Попробовать все в деле можно в моем angular-gulp-starter проекте.




Среда разработки


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


Технически, нам нужно решить три задачи:


  1. Скомпилировать TypeScript
  2. Скомпилировать SCSS
  3. Загрузить все (в т.ч. зависимости) в браузер в нужном порядке

Первые две задачи удобнее всего решать при помощи функции compile-on-save, которая работает почти в любой IDE. При таком подходе достаточно сохранить свои правки в коде, переключиться на окно браузера и нажать F5 — очень быстро и удобно. Кроме того, результаты компиляции легко проконтролировать, js-файлы лежат рядом c ts, и в случае чего всегда можно их поисследовать.


Из IDE для работы с TypeScript могу порекомендовать Visual Studio (например, Visual Studio 2015 Community Edition), которая имеет встроенную поддержку TypeScript + расширение Web Compiler для SCSS. Я пробовал Atom, Visual Studio Code, но на моем ноутбуке они слишком тормозят. Visual Studio (не Code) хорошо справляется с подсветкой, автодополнением и компиляцией на лету даже на слабой машине. Хотя там есть некоторые проблемы подсветки при использовании es6 import.


Третья задача (загрузить все в браузер) — наиболее проблемная, т.к. скрипты зависят друг от друга, и должны загружаться в правильном порядке. Контролировать все это вручную трудно и не нужно. Лучше всего оставить разбираться с зависимостями библиотеке SystemJS: в коде используем ES6 import/export синтаксис, и основываясь на этом, SystemJS подгружает динамически все необходимые файлы. Не нужно строить никаких бандлов, выполнять какую-то специальную сборку, достаточно просто настроить config.


Конфигурация SystemJS — это js-файл, который может выглядеть примерно так:


Пример конфигурации SystemJS для Angular приложения
System.config({
  defaultJSExtensions: true,
  paths: {
    "*": "node_modules/*",
    "app/*": "app/*",
    "dist-dev/*": "dist-dev/*",
    "@angular/common": "node_modules/@angular/common/bundles/common.umd",
    "@angular/core": "node_modules/@angular/core/bundles/core.umd",
    "@angular/http": "node_modules/@angular/http/bundles/http.umd",
    "@angular/compiler": "node_modules/@angular/compiler/bundles/compiler.umd",
    "@angular/platform-browser-dynamic": "node_modules/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd",
    "@angular/platform-browser": "node_modules/@angular/platform-browser/bundles/platform-browser.umd",
    "@angular/router": "node_modules/@angular/router/bundles/router.umd",
    "@angular/forms": "node_modules/@angular/forms/bundles/forms.umd"
  },
  packageConfigPaths: ["node_modules/*/package.json"]
});

Здесь мы делаем следующее:


  1. Указываем, чтобы SystemJS автоматически подставляла расширения js к файлам (defaultJSExtensions).
  2. Указываем, что если не указано иное, искать все в папке node_modules ("*": "node_modules/*"). Это позволит легко устанавливать зависимости через npm.
  3. Прописываем, что модули, начинающиеся с app, нужно загружать не из node_modules, а из папки app (наша основная папка со скриптами). Это используется только в index.html, где импортируется app/main.
  4. Прописываем пути к angular модулям. В идеале, это должно происходить автоматически благодаря параметру packageConfigPaths, но у меня не получилось заставить его работать (что я сделал не так?).
  5. Если какая-то сторонняя библиотека не находится автоматически, то также прописываем путь к ней явно.

После этого, нам достаточно включить в index.html ряд служебных скриптов: zone.js, reflect-metadata, core-js (или es6-shim), саму systemjs, ее конфиг и вызвать импорт главного модуля:


<script>System.import('app/main');</script>

В результате SystemJS загрузит файл app/main.js, проанализирует его import и загрузит эти импортируемые файлы, проанализирует их import и так по очереди будут загружены все файлы приложения.


Однако, это еще не совсем все. Дело в том, что библиотека rxjs, активно используемая в Angular, состоит из множества маленьких модулей. Поэтому, если оставить все так, то при обновлении страницы все они будут грузится по одному, что несколько медленно (до 100-300 запросов).





Поэтому, в своем стартер-проекте я собираю всю rxjs в один бандл, с помощью Rollup. Перед этим, она дополнительно компилируется в ES6, что используется после, в продакшн сборке.


Сборка rxjs в один бандл для ускорения загрузки страницы в dev-окружении

Сборка этого rxjs бандла получается довольно сложной. Сначала компилируются TypeScript исходники в ES6 (из папки node_modules/rxjs/src), после чего все это пакуется при помощи Rollup в один файл, и транспилируется в ES5. При этом, чтобы подружить этот бандл с SystemJS, создается временный файл, который служит входной точкой для Rollup, и выглядит примерно так:


import * as pkg0 from 'rxjs/add/observable/bindCallback'; 
System && System.set && System.set('rxjs/add/observable/bindCallback', System.newModule(pkg0));

import * as pkg1 from 'rxjs/add/observable/bindNodeCallback'; 
System && System.set && System.set('rxjs/add/observable/bindNodeCallback', System.newModule(pkg1));

... и так все модули rxjs

Все это можно найти в файлах build.common.js/rxjsToEs и build.dev.js/rxjsBundle. Скомпилированные в ES исходники также используется при продакшн сборке, поэтому компиляция вынесена отдельно.


После того как бандл собран, его нужно загрузить перед тем, как будет загружен код нашего приложения. Делается это так:


    System.import('dist-dev/rxjs.js').then(function () {
        System.import('app/main');
    });

В результате получаем примерно на секунду быстрее загрузку страницы:




Для удобства разработки, вам также пригодится простой веб-сервер, с поддержкой HTML5 роутинга (когда на все запросы возвращается index.html). Пример такого сервера на основе express можно также найти в стартере.


Знающий читатель еще может спросить, почему не Webpack? Если коротко — webpack хорош для продакшн, но, имхо, неудобен во время разработки. Подробнее в спойлере ниже.


Почему не Webpack, не JSPM, не Browserify

Webpack


Angular CLI и многие starter и seed проекты используют Webpack. Он теперь умеет делать tree-shaking, и говорят, даже hot module reloading (кто-нибудь пробовал именно в контексте Angular?). Но я не разделяю ажиотажа вокруг этого сборщика, и не понимаю, откуда он берется. Webpack это бандлер, и он может только построить бандл. Это порождает множество проблем:


  1. Сборка занимает некоторое значительное время (как минимум, несколько секунд). Мы не можем использовать compile-on-save, который намного быстрее (по крайней мере, это не так просто).
  2. Да, можно использовать watch, так что при сохранении изменений сборка будет запускаться автоматически. Но это не решает проблемы. 1. На практике все выглядит так: я ввожу часть кода, сохраняю, запускается сборка, пока она длится, я ввожу следующий код и сохраняю — в результате получается устаревший бандл, без последних правок. Кто-нибудь сталкивался с такой проблемой? Как вы ее решаете?
  3. Если у вас не работают source maps (а они почему-то постоянно ломаются и иногда тормозят), то сообщения об ошибках будет трудно локализовать.

Впрочем, я могу ошибаться, так как с Webpack особо не работал.


JSPM


JSPM — это первое, что приходит в голову, когда речь заходит о SystemJS. Действительно, с его помощью довольно легко настроить удобную среду разработки для Angular. При этом можно использовать как compile-on-save, так и TypeScript загрузчик. Говорят, там даже работает tree-shaking на основе Rollup. Казалось бы, все идеально.


Но это только на первый взгляд. Порой мне кажется, что JSPM живет в каком-то своем параллельном мире, далеком от всего происходящего вокруг. Зачем-то им понадобилось хранить все пакеты, в том числе npm-пакеты, в своей отдельной папке особым образом. В результате, вместо удобного "из коробки" инструмента, вы получаете кучу головной боли, о том, как заставить все остальные утилиты (которые, как правило, умеют работать с node_modules) подружить с JSPM.


Как минимум, придется устанавливать отдельно typings для зависимостей, чтобы подружить JSPM с TypeScipt (или еще хуже, прописывать пути). Заставить работать AOT-компилятор — тоже отдельная тема. Если нужно сделать что-то нестандартное (как с rxjs), тоже проблемы. Вообщем, у меня просто не получилось все увязать и сделать production сборку на JSPM. Если у кого-то получится, мне было бы очень интересно посмотреть.


Browserify


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



Production сборка


Релизная сборка Angular включает в себя следующие этапы:


  1. Ahead of time (AOT) компиляция шаблонов (html и css части компонентов). В dev-среде они компилируются прямо в браузере, однако для релиза лучше делать это заранее. Тогда нам не придется тащить в браузер код компилятора, повысится эффективность tree-shaking, немного ускорится запуск приложения.
  2. Компиляция TypeScript в ES6 (включая результаты первого шага). Нужен именно ES6, т.к. Rollup умеет работать только с ES6. Компилируем также SCSS, запускаем пост-процессинг.
  3. Сборка бандла с использованием tree-shaking при помощи Rollup. В результате из кода удаляются все неиспользуемые части, и размер скриптов сокращается в десятки раз.
  4. Транспиляция результата в ES5 при помощи того же TypeScript, минификация.
  5. Подготовка релизного index.html, копирование файлов в dist.

AOT-компиляция


AOT-компиляция осуществляется при помощи пакета @angular/compiler-cli (называемый также ngc), который построен на базе компилятора TypeScript. Для выполнения компиляции нужно:


  1. Установить пакеты: @angular/compiler, @angular/core, @angular/platform-browser-dynamic, typescript и собственно, @angular/compiler-cli. Лучше всего, устаналивать все локально в проекте.
  2. Создать файл tsconfig.json (например, такой).
  3. Запустить компиляцию командой "./node_modules/.bin/ngc" -p tsconfig.ngc.json, либо при помощи gulp-плагина.

Неприятные особенности AOT-компилятора

NGC построен на основе TypeScript, но построен, стоит сказать, плохо. Не все возможности TypeScript в нем работают, как надо. Например, наследование конфигураций не работает (поэтому в стартере 3 отдельных tsconfig-файла). В этой статье можно посмотреть, что еще не поддерживает AOT-компилятор. Список далеко не полный (вот, например), поэтому будьте готовы, что с этим будут проблемы. Компилятор может "упасть" где-то в своих недрах или уйти в бесконечный цикл, и выяснить причину не всегда просто. Проверять, что все компилируется нужно часто, чтобы потом не разбираться со всем разом.


Конфигурационный файл выглядит в основном также, как и основной tsconfig. Однако, компилятор порождает множество файлов, захламлять которыми папку с исходниками неприятно. Поэтому в конфигурации желательно указать папку, куда будут помещены результаты компиляции:


"angularCompilerOptions": {
        "genDir": "app-aot"
    }

Это актуально еще и потому, что компилятор обрабатывает также компоненты самого Angular. Поэтому если не указать genDir, то часть результатов появится в папке node_modules. Это как минимум странно.


Стоит обратить внимание, что AOT-файлы ссылаются на основные исходники по относительным путям. Поэтому, взаимное расположение папок важно.


Релизная компиляция TypeScript


Отличие релизной компиляции от обычной заключается, во-первых, в том, что необходимо создать отдельный main.ts файл. Во время разработки его следует исключить из компиляции, а в релизной сборке, наоборот, заменить им dev-версию. Отличие этого файла в том, что используется специальная bootstrap функция, которая задействует результаты AOT-компиляции. В частности, мы запускаем AppModuleNgFactory (результат компиляции AppModule) из genDir AOT-компиляции:


import { platformBrowser } from '@angular/platform-browser';
import { AppModuleNgFactory } from '../app-aot/app/app.module.ngfactory';

platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);

Также здесь мы включаем продакшн режим для Angular (это важно сделать, так как сильно влияет на производительность):


import { enableProdMode } from "@angular/core";

enableProdMode();

Второе отличие релизной компиляции — использование целевой платформы ES6. Если этого не сделать, Rollup не выдаст ошибки, но и tree-shaking не выполнит. По этой же причине, нам необходима ES6 версия rxjs. Раньше у rxjs был специальный пакет rxjs-es, и все примеры сборки Angular на gulp, которые показывает гугл на первых страницах, используют именно его. К сожалению, данный пакет перестали поддерживать. Поэтому нам необходимо самим компилировать rxjs из TypeScript исходников, как было описано выше.


Конфигурация релизной компиляции включает папки app, и app-aot (genDir AOT-компиляции) и исключает dev main.ts, как было описано выше. Также, для порядка, в моем стартере результаты prod-компиляции помещаются в temp/app-prod-compiled. Все это находится в файле build.prod.js.


Tree-shaking при помощи библиотеки Rollup


Сборка при помощи Rollup — это ключевой этап сборки, способный превратить 1 Мб исходников в 100 Кб. Rollup анализирует исходники, и выбрасывает из них те участки кода, которые не используются.


На вход он принимает один единственный файл — main.js (точнее main-aot.js), анализируя import выражения, в котором собираются все остальные модули. Отсюда следует, что Rollup должен уметь находить нужные библиотеки. Большинство проблем решает плагин rollup-plugin-node-resolve, который находит библиотеки в node_modules. Его использование прописывается в соответствующем конфигурационном файле.


В случае, если нужно сделать что-то специфичное, то легко написать свой плагин. Например, таким образом я указываю Rollup, что rxjs нужно брать из той самой папки, где лежит наша скомпилированная ES6 версия (RollupNG2 в том же rollup-config).


Из особенностей конфигурации, стоит отметить параметр treeshake: true (разумеется), context: 'window' (говорим, что собираем для браузера) и format: 'iife'. Формат IIFE позволит обойтись без SystemJS, просто добавив результирующий файл как script-тэг в index.html.


Транспиляция результата в ES5 при помощи TypeScript довольно проста, главное выставить параметр allowJs. Операция занимает пару строчек в файле bundling.js в функции rollupBundle.


Подготовка релизного index.html


После всей проделанной выше работы, нам остается только собрать все вспомогательные библиотеки в один бандл, и добавить результат работы rollup на страницу через script-тэг. Все это стандартные для gulp задачи.


В стартере все это сделано из расчета на максимальную простоту, чтобы не заставлять пользователей лишний раз разбираться. Найти соответствующий код можно в файле build-prod.js. Для тестирования, там также настроен express-сервер, со включенным gzip-сжатием.


В итоге получаем 118 Кб после gzip:




В примере используется Tour of Heroes из официальных руководств Angular, который не совсем "Hello world". Если совсем упростить, то может получиться вплоть до 50-80 Кб.


По ссылкам ниже можно попробовать обе версии сборки вживую:


> DEV версия online
> PROD версия online


В заключении, хочу порекомендовать отменную статью по теме Minko Gechev. В ней он приводит пример простейшей сборки из 6 npm-скриптов, которая выполняет все основные шаги (учтите, что там используется rxjs-es, который больше не поддерживается). Правда seed-проект за его авторством мне не понравился, из-за высокой сложности и не очень высокого удобства.


На этом все, удачи!

Поделиться с друзьями
-->

Комментарии (30)


  1. hardex
    10.02.2017 12:25

    запускается сборка, пока она длится, я ввожу следующий код и сохраняю — в результате получается устаревший бандл, без последних правок

    В Webpack 2 это починили


    1. PFight77
      10.02.2017 12:28

      И что происходит? Останавливается предыдущая сборка и запускается новая?


      1. hardex
        10.02.2017 12:35

        Текущая продолжается, а потом собирается еще раз. Не фонтан, конечно.


  1. ganqqwerty
    10.02.2017 14:11
    +1

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


    1. PFight77
      10.02.2017 14:28

      Была статья на эту тему How it feels to learn JavaScript in 2016: ))


  1. xGromMx
    10.02.2017 14:35

    Есть такой репозиторий и там же презентация https://github.com/mlaval/optimize-angular-app


    1. PFight77
      10.02.2017 14:49

      lazy loading and pre-rendering

      Как раз следующая тема, с которой хотел разробраться — это серверный рендеринг. Lazy loading без code splitting смысла особо не имеет к сожалению. Кстати, как у webpack получается сплиттить, кто-нибудь пробовал? Гугл говорит вроде умеет, но интересно как это на практике.


  1. indestructable
    10.02.2017 15:47
    +1

    Сборка Angular 2 приложения — это боль и страдания. Продакшн билд приложения с компиляцией шаблонов и использованием ДевЭкстрим занимает… 8.5 минут!!!


    Да, можно использовать watch, так что при сохранении изменений сборка будет запускаться автоматически. Но это не решает проблемы. 1. На практике все выглядит так: я ввожу часть кода, сохраняю, запускается сборка, пока она длится, я ввожу следующий код и сохраняю — в результате получается устаревший бандл, без последних правок. Кто-нибудь сталкивался с такой проблемой? Как вы ее решаете?

    Постигая дзен двухсекундными ожиданиями после полусекундных правок.
    Существует опция вебпака watchOptions.aggregateTimeout и watchOptions.poll, которая теоретические добавляет задержку перед запуском билда после изменений.


  1. Casufi
    10.02.2017 17:06

    В README вашего стартера не описано как быть если IDE не поддерживает compile-on-save. Используете ли вы browsersync или аналоги для автозагрузки изменений в коде?


    1. PFight77
      10.02.2017 17:17

      О какой IDE речь? Из коробки кажется только VS поддерживает, в остальных нужно ставить плагины. Без compile-on-save вся идея dev-окружения теряет смысл. Проще тогда взять тот же Angular CLI и не париться.


      Browsersync у меня как-то не прижилось — мне кажется нерациональным гонять браузер постоянно (ноутбук относительно слабый). Сохраняю я часто, а переключаюсь на браузер гораздо реже. Да и вообще, не очень доверяю подобной автоматике — F5 надежнее, все под контролем. Впрочем, если есть интерес, с удовольствием замержу пулреквест (при условии что browsersync будет запускаться отдельной командой).


      1. Casufi
        10.02.2017 17:31

        Я о VIM например. Я сторонник того, чтобы дев окружение не было привязано к рабочему месту. Разработчик обычно работает в команде и неизвестно кто и в каких условиях будет править твой проект. Я, например, частенько правлю на c9.io, поэтому окружение должно быть максимально функционально само по себе и не зависеть от IDE.


        1. PFight77
          10.02.2017 17:59

          Для vim тоже есть плагин. Если нужно что-то быстро поправить без настройки рабочей среды, можно запустить из консоли gulp build-dev --color, это запустит компиляцию всего.
          На крайняк можно запустить tsc --watch, но добавлять это в стартер я бы не стал по все тем же причинам — никогда не знаешь, что и как ты получишь, все зависит от порядка и скорости нажатия Ctrl+S.


          1. Casufi
            10.02.2017 18:04

            Не заметил вот этой строки gulp build-dev --color, мое упущение, простите.


  1. cjbars
    10.02.2017 19:01
    +4

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

    Я очень хочу перейти на новый уровень, но совершенно не понимаю ради чего весь этот оверхед? Что мне даст этот бонусный мегабайт? Ведь мне нужно то не много: двусторонний биндинг и DRY. Большего от Angular, и прочих фреймворков я не жду.

    Что это? Java экспансия во все языки? Или что?


    1. PFight77
      10.02.2017 19:17

      Ох не возьмусь оправдывать Angular, его сложность и размеры действительно пугают. Хотя вот Ember еще больше, только там кажется даже tree-shaking не применишь. Оставлю только вот эту ссылочку в защиту Angular. Все-таки, как не крути, а есть у Ангуляра киллер-фичи. За одну изоляцию CSS я готов с ним мириться.


      1. cjbars
        10.02.2017 19:43

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


        1. kuftachev
          12.02.2017 08:44

          Так в этом же и весь смысл, SPA — это, по сути, десктопное/нативное приложение, только без проблем связанных с доставкой этого приложения всем пользователям и поддержкой актуальной версии этого приложения у всех пользователей.


          Получается, победа бизнес-требований над качеством приложений.


          1. PFight77
            12.02.2017 08:47

            Получается, победа бизнес-требований над качеством приложений.

            Как интересно вы выразились. Значит веб априори менее качествен чем десктоп? Как вы определяете качество в данном случае?: )


          1. indestructable
            12.02.2017 20:21

            Хмм, разве качество — это не бизнес-требование? :)


  1. irsick
    10.02.2017 19:18
    +1

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

    Исторически, Angular 2 имеет очень сложную процедуру сборки проекта, заставляя разбираться во всем многообразии различных подходов и инструментов, не имеющих напрямую отношения к самому коду.

    Как самый базовый предлагается использовать Angular Quickstart, однако после написания «Hello World» его возможностей резко начинает нехватать. И тут начинается тернистый путь выбора подходящего бойлерплейта.

    Мой текущий выбор — Angular CLI (использует Webpack)

    Плюсы:

    • Самый официальный среди официальных бойлерплейтов, большинство сторонних модулей ориентируются именно на него
    • Ментейнеры — разработчики ядра Angular, поэтому поддержка новых фич появляется достаточно быстро
    • Инструменты CLI
    • Безболезненная компиляция AoT
    • Генерация бандлов Lazy Load из коробки
    • Удобное обновление самой среды Angular CLI (как отдельный пакет)
    • Быстрая пересборка только измененных частей (около секунды)
    • Синхронизация с браузером через LiveReload (несколько проигрывает Browsersync по функционалу)


    Минусы:
    • Все еще бета, время от времени одна из сотен зависимостей ломает все (правда, быстро чинят)
    • Работает по принципу «черного ящика» с минимумом доступных настроек
    • Linter доступен только как отдельная команда
    • Размер бандлов несколько больше, чем с system.js (однако в сжатом виде они могут быть и меньше)


    До перехода на CLI я долгое время использовал angular-seed (использует system.js).

    Плюсы:
    • Полуофициальный бойлерплейт
    • Главный ментейнер — уже упомянутый разработчик ядра Angular Minko Gechev, поддержка новых фич появляется достаточно быстро (часто быстрее CLI)
    • Очень гибкая настройка Gulp tasks
    • Агрессивный linter на этапе сборки
    • Первый бойлерплейт, ставший поддерживать AoT
    • Генерация кода из коробки через compodoc
    • Сравнительно малый размер бандлов (см. выше)
    • Синхронизация с браузером через Browsersync


    Минусы:
    • Частые проблемы с AoT со многими популярными сторонними модулями из-за system.js (ng2-bootstrap, например, официально не поддерживает system.js)
    • Отсутствует changelog и система версий, очень неудобное обновление вручную
    • Нет генерации бандлов Lazy Load
    • Долгое время пересборки (2-5 секунд)


    Выбор бойлерплейта в мире Angular напоминает религиозные войны дистрибутивов Linux, где каждый продвигает свою философию. На данный момент самым перспективным считается tree shaking с помощью rollup.js, однако работа ведется и на фронте Google Closure Compiler. Помимо уменьшения размеров самого бандла есть еще 2 приема оптимизации: Lazy Load и рендеринг на сервере через Angular Universal.


    1. PFight77
      10.02.2017 19:32

      Seed проект Minko мне не понравился по двум причинам:


      1. Очень сложная система сборки. Когда мне надо было добавить стороннюю библиотеку в зависимости, и у меня ничего не заработало из коробки, я начал разбираться. У него там куча каких-то скриптов, непонятно что из них что делает, откуда все берется и куда следует. В итоге я добавил эту библиотеку в папку с исходниками и так решил проблему. Что особенно печально, на тот момент не было другого сида, который делал бы AOT и tree-shaking. Тогда-то я и начал разбираться в теме, чтобы сделать свое.
      2. Не работает compile-on-save. Дев сборка в его сиде (когда я с ним работал) копировала файлы в специальную папку (как у меня релизная сборка). В результате, пока ты не запустишь из консоли билд (который довольно долгий), изменения в браузере не посмотришь. Может сейчас он это уже изменил, не знаю.

      В своем стартере я старался сделать максимально простую и прозрачную систему, чтобы в ней легко было разобраться. Я намеренно оставил ряд вещей не автоматизированными (например, редактирование index.html), дабы не плодить громоздких gulp-конструкций.


      Решения вида "черный ящик", конечно, хорошо, но только до тех пор пока все работает. Если что-то идет не так, то ты сразу же оказываешься в безвыходной ситуации. Остается только писать ишью, на которые неизвестно когда ответят. Поэтому для продакшена мне страшновато использовать Angular CLI. Может быть когда-нибудь, когда она станет совсем стабильной (как Ember CLI)...


      1. irsick
        10.02.2017 20:29

        Я использовал angular-seed с момента, когда Angular 2 был beta 3, все вышеперечисленное у меня работало из коробки. Собственно, bundling, complile-on-save и AoT были основными причинами, почему я его выбрал. Запускал на MacOS и CentOS. Пользователи Windows постоянно жаловались на кактус.

        Куча скриптов требовала вдумчивого чтения, но после большого опыта собственного велосипедостроения на Gulp особых проблем не вызывала. Зато внедрение экзотических фич (вроде ставки кода Google Analytics только для продакшена) происходило куда легче, чем с CLI.

        Искренне желаю вам успехов с вашим проектом, надеюсь вам удастся сочетать баланс легкости в использовании и функционала.


      1. sentyaev
        10.02.2017 22:42

        Не понимаю чем не угодил angular-cli, в моей компании его в родакшене используют с тех пор как появились первые beta версии, да и сам Angular тоже еще с beta версий в продакшене.
        Да, бывают проблемы, но вдумчивое чтение багтрекера не дает наступать на грабли.
        Ну и как основной плюс, angular-cli тестируют тысячи человек.


        1. PFight77
          10.02.2017 23:28

          А какого рода проблемы? Можете привести случаи из жизни?


          1. irsick
            11.02.2017 00:26

            К примеру вот это https://github.com/angular/angular-cli/issues/4378 во время деплоя в четверг попротило много крови мне и куче народа. Справедливости ради обратите внимание на то, сколько времени прошло от создания поста до решения проблемы. Opens Source в действии.


        1. PFight77
          12.02.2017 11:06

          А не бывает проблем, когда нужно подключить какую-то библиотеку, или сделать что-нибудь специфичное? Как, допустим, выше приводили пример, добавить аналитику только в production сборку. Или подключить библиотеку, которой вообще нет в npm, и она есть только в виде репозитория на гитхабе.


          1. sentyaev
            12.02.2017 13:45

            В angular-cli есть поддержка environment, изначально есть prod, dev, но можно добавить сколько угодно своих.
            Подключить библиотеку не из npm — тривиально. В angular-cli.json есть раздел scripts.
            Ну а для совсем специфичных вещей вам никто не запрещает запустить какой-нить скрипт, но я бы это уже вынес из приложения и переложил на CI или CD.


  1. SuperOleg39ru
    10.02.2017 23:26

    Попробуйте webpack все-таки, может там не такой эффективный tree-shaking, но комфорт в разработке того стоит)


  1. StressoID
    14.02.2017 22:00

    Ведем разработку на Angular CLI. Пока полет нормальный, компилим для продакшена тоже без особых проблем.


  1. Kayun
    14.02.2017 22:00

    Вот не очень понимаю, что эти 2-3 секунды перекомпиляции вам дадут. Зачем каждую секунду править свой код, может лучше подумать, что конкретно нужно написать? А если так хочется постоянно что-то вводить, то настройте перекомпиляцию по ctrl + s. В любой ide это возможно. В крайнем случае, писали выше, у вебпака можно задержку выставить.
    Единственный недостаток при сборке вебпаком, а может и не только им, в том, что не работают сорсмапы для изолированных стилей. Если у кого-нибудь есть решение этой проблемы, то с радостью послушаю!