Toly blog

Python and Django notes

Ускоряем разработку на AngularJS с помощью Yeoman, Grunt и Bower

Перевод статьи Бреда Барроу Kickstart Your AngularJS Development with Yeoman, Grunt and Bower

Любите ли вы или ненавидите его, нет никаких сомнений, что AngularJS является фреймворком о котором говорит каждый разработчик. Он может и не всем подходит, но тем неменее у AngularJS есть много адаптивных, эффективных и мощных возможностей. Добавьте несколько полезных инструментов разработки, таких как Yeoman, Grunt и Bower и вы получите невероятно быстрый процесс разработки прототипов.

Что мы рассмотрим

В этом руководстве мы рассмотрим:

  • генерацию каркаса ANgularJS приложения с помощью Yeoman
  • использование Grunt для ускорения разработки и автоматизации повторяющихся задач
  • использование Bower для добавления сторонних плагинов/фреймворков
  • выполнение небольших изменений в вашем Angular приложении

Предварительные приготовления

Чтобы получить максимальную отдачу от этого урока мы рекомендуем вам иметь следующие навыки и знания:

  • терминал и знание командной строки
  • установленные NodeJS и NPM
  • знание основ JS, CSS и HTML

Исходники

Репозиторий нашего учебного проекта можно найти здесь.

Давай начнем!

Хорошо, давайте приступим к реализации. Первое, что нам нужно сделать, это установить Yeoman, Grunt и Bower. Используем NPM, что бы установить все сразу. Выполните следующую команду в терминале:

1
npm install -g yo grunt-cli bower

Это было просто, но теперь в нашем распоряжении мощный набор инструментов. Я объясню как использовать каждый из них.

Yeoman

Yeoman используется для генерации каркаса вашего приложения. Он создаст основные каталоги, файлы и настройки проекта, что бы его можно было сразу же запустить. Помимо этого существуют различные особые генераторы, которые можно использовать для создания приложений определенного вида - мы собираемся использовать удобный генератор для AngularJS.

Одной из лучших функций Yeoman является возможность использования самописных генераторов. Мы установим генератор AngularJS, что бы сделать минимально работающее Angular приложение как можно быстрее.

Запустите следующую команду для установки AngularJS генератора:

1
npm install -g generator-angular

Теперь можно сгенерировать новенькое Angular приложение. В новом каталоге проекта запустите:

1
yo angular

Генератор задаст вам пару вопросов. Вы можете ответить утвердительно для установки Twitter Bootstrap. Так же ответьте да для включитьв проект ngResource. Остальное, для текущего проекта, нам не понадобится, поэтому отвечайте - нет.

Теперь расслабьтесь (на несколько секунд) и наблюдайте как генератор делает свою магию. Yeoman создаст файлы и каталоги, а затем он запустит установку Bower (подробности об этом чуть позже) и NPM установит различные зависимости, и наконец он выполнит начальное конфигурирование.

Что в коробке?

Давайте взглянем на то, что сделал нам Yeoman:

1
2
3
4
5
6
7
8
9
10
11
12
13
.bowerrc
.editorconfig
.gitattributes
.gitignore
.jshintrc
Gruntfile.js
app/
component.json
karma-e2e.conf.js
karma.conf.js
node_modules/
package.json
test/

Давайте рассмотрим наиболее важные из них:

app/ - Каталог содержит ваше статическое приложение. Он включает ​​HTML, CSS и JavaScript, и здесь вы будете заниматься большую часть времени разработки.

package.json - Этот файл помогает NPM определить наш проект, а также разрешать его зависимости. Он также может содержать всевозможные метаданные, относящиеся к вашему проекту.

node_modules/ - Название этого каталога говорит само за себя. Здесь хранятся модули node, от которых зависит ваш проект.

Gruntfile.js - Это яваскриптовый файл который отвечает за конфигурацию вашего проекта, а также различных задач и плагинов, используемых в вашем проекте. Например, здесь можно указать, что в проекте используется Uglify и что вы хотите запускать задачу Uglify в определенном каталоге во время сборки проекта. Подробнее о Grunt чуть позже.

component.json - Этот файл используется для уведомления менеджера пакетов Bower о зависимостях проекта, а также другие метаданные. В последних версиях Bower этот файл называется bower.json - об этом чуть позже.

.bowerrc - Используется для передачт опций в Bower.

Karma files - Karma - фреймворк для тестирования. Мы будем использовать его для запуска нескольких тестов для нашего Angular приложения.

Уф! Это довольно много, что бы запомнить - но как только вы больше познакомитесь с работой генератора Yeoman, вам понравится то, что он делает все это за вас.

Давайте добавим еще несколько вещей в наш проект, прежде чем начать приступить к разработке.

Bower - пакетный менеджер для веб разработки

Перед тем как использовать Bower, небольшую часть конфигурации нужно написать самим. Bower недвано изменил название файла component.json на bower.json, таким образом нам нужно привести код в соответствие с этим.

Первое, что нам нужно сделать, это небольшое изменение в нашей Bower конфигурации в .bowerrc - откройте его и добавьте следующее:

1
2
3
4
{
	"directory": "app/components",
	"json": "bower.json" // Add this line
}

Это скажет пакетному менеджеру Bower использовать файл bower.json для получения инструкций о том как устанавливать этот пакет.

Так как мы используем Bower для разрешения зависимостей нашего проекта, то также нужно переименовать файл component.json в корне нашего прокета в файл bower.json. Незначительные премудрости при использовании таких передовых технологий.

Bower - это пакетный менеджер. Он поможет нам быстрой найти и установить наши любимые CSS фреймворки, яваскрипт библиотеки и плагины, используя всего лишь несколько просты комманд.

Отлично, давайте дадим ему поработать. Ранее Yeoman воспользовался Bower что бы установить Bootstrap, но то были только CSS файлы. А нам нужны и модные яваскиптовые виджеты.

Так как мы делаем Angular приложение, нам нужны скрипты для Bootstrap которые работают с Angular.

К счастью, команда Angular UI портировала скрипты Bootstrap для Angular. Давайте используем Bower чтобы установить их библиотеку!

1
bower install angular-bootstrap --save

Флаг -save указывает макетному менеджеру добавить зависимость в bower.json.

Фантастика! Это было просто, не так ли? Теперь перейдите в каталог вашего приложения (app/) и давайте посмотрим, с чем мы будем работать.

Наша статическое приложение

Взгляните на содержание каталога app/:

1
2
3
4
5
6
7
favicon.ico
index.html
robots.txt
components/
scripts/
styles/
views/

index.html - Это должно быть известно большинству читателей, это главная HTML-страница вашего приложения.

components/ - Это каталог компонентов, такой же как и node_modules/, но для Bower. Здесь хранятся все библиотеки, которые вы установили с помощью Bower. Например, AngularUI Bootstrap находится здесь.

scripts/ - Опять же, знакомый для большинства каталог. Здесь хранятся JavaScript файлы ваших приложений. Обратите внимание, что библиотеки, такие как AngularJ, будут находиться в каталоге для компонентов, так что каталог scripts/ только для тех файлов, которые пишете вы сами.

styles/ - Все ваши CSS/Sass, что бы сделать ваше приложение более красивым.

views/ - Это каталог, где будут храниться ваши шаблоны для Angular.

Теперь более внимательно посмотрим на файлы AngularJS.

AngularJS

Angular-генератор в Yeoman сделал для нас самое необходимое: модуль, контроллер и представление. Давайте рассмотрим каждый из них:

Модуль: /app/scripts/app.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
'use strict';
// Here we set up an angular module. We'll attach controllers and 
// other components to this module.
angular.module('testApp', [])
  // Angular supports chaining, so here we chain the config function onto
  // the module we're configuring.
  .config(function ($routeProvider) {

    // We use AngularJS dependency injection to fetch the route provider.
    // The route provider is used to setup our app's routes. 

    // The config below simply says when you visit '/' it'll render
    // the views/main.html template controlled by the MainCtrl controller.

    // The otherwise method specifies what the app should do if it doesn't recognise 
    // the route entered by a user. In this case, redirect to home.
    $routeProvider
      .when('/', {
        templateUrl: 'views/main.html',
        controller: 'MainCtrl'
      })
      .otherwise({
        redirectTo: '/'
      });
  });

Контроллер: /app/scripts/controllers/main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
'use strict';

  // Here we attach this controller to our testApp module
  angular.module('testApp')

    // The controller function let's us give our controller a name: MainCtrl
    // We'll then pass an anonymous function to serve as the controller itself.
    .controller('MainCtrl', function ($scope) {

      // Using AngularJS dependency injection, we've injected the $scope variable
      // Anything we attach to scope will be available to us in the view.

      // In this case, we're attaching a collection of Awesome Things to display
      // in app/views/main.html
      $scope.awesomeThings = [
        'HTML5 Boilerplate',
        'AngularJS',
        'Karma'
      ];
    });

Представление: app/views/main.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<div class="header">
  <ul class="nav nav-pills pull-right">
    <li class="active"><a ng-href="#">Home</a></li>
    <li><a ng-href="#">About</a></li>
    <li><a ng-href="#">Contact</a></li>
  </ul>
  <h3 class="text-muted">angyeo</h3>
</div>

<div class="jumbotron">
  <h1>'Allo, 'Allo!</h1>
  <p class="lead">
    <img src="images/yeoman.png" alt="I'm Yeoman"><br>
    Always a pleasure scaffolding your apps.
  </p>
  <p><a class="btn btn-lg btn-success" ng-href="#">Splendid!</a></p>
</div>

<div class="row marketing">
  <h4>HTML5 Boilerplate</h4>
  <p>
    HTML5 Boilerplate is a professional front-end template for building fast, robust, and adaptable web apps or sites.
  </p>

  <h4>Angular</h4>
  <p>
    AngularJS is a toolset for building the framework most suited to your application development.
  </p>

  <h4>Karma</h4>
  <p>Spectacular Test Runner for JavaScript.</p>
</div>

<div class="footer">
  <p>♥ from the Yeoman team</p>
</div>

Давайте посмотрим его в действии!

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

1
grunt server

Grunt

Grunt является мощным, многофункциональным, исполнителем задач на JavaScript. Короче говоря, он позволяет автоматизировать повторяющиеся задачи, такие как компиляция CoffeeScript, минификация CSS, проверка корректности кода и т.д. Мы так же будем делать это, для того что бы подготовить наш код для разработки и развертывания.

Grunt проходится по каталогу нашего проекта и подготавливает его для нас, например компилирует подключенный Bootstrap SASS в CSS.

Через несколько секунд окно браузера должно появиться с вашим работающим приложением.

Что бы быть уверенным в корректной работе, откройте исходный код страницы и посмотрите подключенный main.css. Он должен содержать кучу Bootstrap кода - благодаря магии Bower и Grunt.

Давайте изменим его

Пришло время попробовать наши силы в изменении проекта. Так как это Angular проект, начнем с тестов.

Yeoman любезно сгенерировал пример теста, так что давайте начнем с него.

Мы собираемся добавить еще один элемент в список awesomeThings, поэтому откройте test/spec/controllers/main.js и измените ожидаемую длину списка на 4 вместо 3.

test/spec/controllers/main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
'use strict';

describe('Controller: MainCtrl', function () {

  // load the controller's module
  beforeEach(module('testApp'));

  var MainCtrl,
    scope;

  // Initialize the controller and a mock scope
  beforeEach(inject(function ($controller, $rootScope) {
    scope = $rootScope.$new();
    MainCtrl = $controller('MainCtrl', {
      $scope: scope

    });
  }));

  it('should attach a list of awesomeThings to the scope', function () {
    // Change this line
    expect(scope.awesomeThings.length).toBe(3);

    // To this
    expect(scope.awesomeThings.length).toBe(4);
  });
});

Теперь мы можем использовать еще одну замечательную возможность в Grunt:

1
grunt test

Эта команда запустит наши Karma-тесты. Они должны выдать ошибку потому, что ожидается 4 элемента в awesomeThings, а у нас по прежнему 3. Давайте исправим это и сделаем так, что бы наши тесты прошли.

Откройте app/scripts/controllers/main.js и добавтье еще один элемент в список:

app/scripts/controllers/main.js

1
2
3
4
5
6
7
8
.controller('MainCtrl', function ($scope) {
  $scope.awesomeThings = [
    'HTML5 Boilerplate',
    'AngularJS',
    'Karma',
    'SitePoint'
  ];
});

Сохраните файл и запустите тесты снова:

1
grunt test

На этот раз они должны успешно завершиться. Теперь вы можете запустить приложение в браузере (grunt server) и заметить, что есть дополнительный пункт в списке. Аккуратные да?

Использование пакета, установленного через Bower

Давайте используем библиотеку AngularUI Bootstrap, которую мы подключили ранее, что бы наш список awesomeThings стал раскрываемым.

Важно: Bower - просто пакетный менеджер, он не отвечает за добавление файлов в index.html. Нам нужно сделать это самим.

Поэтому откройте app/index.html и добавьте следующую строку:

1
<script src="components/angular-bootstrap/ui-bootstrap.js"></script>

Потом, в соответствии со вступительным руководством по AngularUI Bootstrap, мы должны добавить их модуль в качестве зависимости в наш модуль Angular.

Откройте app/scripts/app.js и добавьте ui.bootstrap как зависимость:

/app/scripts/app.js

1
2
3
4
'use strict';

angular.module('testApp', ['ui.bootstrap'])
...

Хорошо, теперь можно его использовать. Сделайте несколько изменений в нашем представлении:

app/views/main.html

1
2
3
4
5
6
7
8
9
10
11
12
<ul>
  <li class="dropdown">
    <a class="dropdown-toggle">
      Click me to see some awesome things!
    </a>
    <ul class="dropdown-menu">
      <li ng-repeat="thing in awesomeThings">
        <a></a>
      </li>
    </ul>
  </li>
</ul>

Мы использовали несколько CSS классов из Bootstrap и переместили директиву ng-repeat что бы создать пункты меню, а не стандартный список.

Директивы AngularUI Bootstrap работают на классах, так что просто добавив класс dropdown-toggle к тегу, мы получили полностью рабочий выпадающий список!

Еще нужно добавить модуль Bootstrap UI к нашим тестам, иначе они будут валиться до тех пор пока на будут внесены следующие изменения:

test/spec/controllers/main.js

1
2
3
4
5
6
7
8
9
10
'use strict';

describe('Controller: MainCtrl', function () {

  // load the controller's module
  beforeEach(module('testApp'));
  // load the BootstrapUI module
  beforeEach(module('ui.bootstrap')); // Add this line
 ...
});

/karma.conf.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Karma configuration

// base path, that will be used to resolve files and exclude
basePath = '';

// list of files / patterns to load in the browser
files = [
  JASMINE,
  JASMINE_ADAPTER,
  'app/components/angular/angular.js',
  'app/components/angular-mocks/angular-mocks.js',
  'app/components/angular-bootstrap/ui-bootstrap.js', // Add this line
  'app/scripts/*.js',
  ...

Запустите grunt test, что бы убедиться, что тесты успешно пройдены.

Теперь вы можете открыть ваше приложение в браузере (grunt server) еще раз и посмотрите на результат вашей работы.

Заключение

Что у вас теперь есть! Простое Angular приложение, подключенная сторонняя библиотека, тесты, минификация и куча других вкусностей с минимальными усилиями!

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

Comments