Многие руководства по AngularJS показывают, как создать простое приложение с очень простой структурой проекта. Сегодня я собираюсь показать вам, как настроить более сложный и масштабируемый рабочий процесс разработки, который я использую в большинстве своих проектов Angular, используя Node.js, Gulp и Browserify.

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

Почему Node.js

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

<script src="/js/lodash.js"></script>
<script src="/js/jquery.min.js"></script>
<script src="/js/dependency2.js"></script>
<script src="/js/dependency1.js"></script>
<script src="/js/main.js"></script> ...

Как вы видите в приведенном выше примере, существует множество зависимостей, таких как lodash, jQuery и другие, которые вы могли написать сами. В конце концов, в самый низ будет добавлен файл main.js, который должен реализовать функциональность этих зависимостей. Если ваше приложение сложное, список станет длиннее. Это не так уж плохо, за исключением того, что браузер будет делать множество запросов на получение этих файлов, и ваш проект будет сложнее поддерживать.

В этом случае Node пригодится, потому что он предлагает готовую модульную систему, предоставляя такие функции, как require(), и такие объекты, как exports или module.exports.

// hello.js 
var $ = require('jquery') 
function greet() {
    $('h1').html('Hello World') 
}
module.exports = greet
// main.js 
var hello = require('./hello') 
hello() // <h1>Hello World</h1>

Это здорово, таким образом мы можем просто включить main.js в наш HTML-файл, для которого потребуется jQuery. Однако это не будет работать само по себе. Это связано с тем, что браузер не понимает модули Node, поэтому он не знает, как требовать другие файлы JS. К счастью, есть очень полезный инструмент под названием Browserify, который решает эту проблему.

Просматривать

Browserify — это модуль Node, который берет ваш основной файл JavaScript, считывает все его необходимые зависимости (и зависимости зависимостей) и создает один файл JavaScript, готовый для включения в ваш HTML. Этот файл содержит код JavaScript, который на самом деле совместим с браузерами, другими словами, он просматривает ваши модули Node. Вы можете подумать, что использование плагина для объединения файлов JS сделает ту же работу, но это не так. Это связано с тем, что при объединении исходных файлов вам придется учитывать их порядок на основе логики каждого файла. Порядок, в котором вы объединяете исходные файлы, имеет решающее значение, поскольку он потенциально влияет на их выполнение. Что, если, например, файл нужен после и перед другим файлом? Browserify позаботится об этом.

Глоток

Gulp — это универсальный инструмент, который автоматизирует ваши рабочие процессы. Он может выполнять такие действия, как компиляция ваших файлов sass, оптимизация ресурсов, компиляция CoffeeScript и браузер ваших модулей Node. Существует плагин gulp практически для каждой задачи, которую вам нужно автоматизировать в рабочем процессе разработки. У него также есть отличные опции, такие как выполнение определенных задач, когда файл сохраняется в вашем проекте. Например, вы можете настроить его на просмотр файла .sass, чтобы всякий раз, когда вы его сохраняете, Gulp выполнял задачу, которая компилирует этот файл sass и сохраняет его в вашем каталоге /public/css.

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

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

Установить узел

Скачать Node можно здесь. После установки откройте Терминал и введите:

node -v

Это показывает, какая версия Node у вас установлена ​​в вашей системе.

Создать проект

Теперь мы создадим пустой каталог и создадим файл package.json. Я предполагаю, что этот каталог находится на рабочем столе:

cd ~/Desktop 
mkdir angular_browserify_gulp 
cd angular_browserify_gulp 
npm init

Если вы знакомы с Node, npm init запустит утилиту командной строки, которая запросит некоторую информацию о вашем новом приложении, такую ​​как его имя, версия, тип лицензии и т. д. После этого он создает файл package.json в корневом каталоге каталог проекта со всеми подробностями. Этот файл также будет включать список всех зависимостей, которые вы будете использовать в этом проекте — либо devDependencies, которые потребуются вашему проекту для процесса разработки, либо/и зависимости, которые необходимы приложению для запуска. например, jQuery или lodash.

Пока оставим файл пакета как есть, затем

Установить глоток

Откройте терминал и установите пакет Gulp.

npm install gulp --save-dev

Приведенная выше команда сообщает npm или диспетчеру пакетов Node, чтобы установить Gulp и добавить его в качестве зависимости в ваш package.json в списке devDependencies, отсюда и опция — save-dev. Обратите внимание, что Gulp считается зависимостью, связанной с разработкой, что означает, что он будет работать только во время разработки приложения.

После установки Gulp вы найдете в своем проекте новый каталог с именем node_modules. Он содержит исходный код ваших установленных пакетов. Конечно, если вы собираетесь управлять версиями своего приложения, вы должны добавить эту папку в .gitignore, потому что вы не хотите помещать ее в свой репозиторий (поскольку эта папка будет очень большого размера). Затем тот, кто будет клонировать ваше приложение, может просто запустить npm install, который установит все зависимости в вашем файле package.json и создаст новую папку node_packages для этого конкретного рабочего каталога.

Установите несколько плагинов Gulp

Теперь давайте продолжим и установим несколько плагинов Gulp. Мы начнем с gulp-connect, который просто запускает статический локальный сервер, который статически обслуживает ваше приложение, так как в любом случае это интерфейсный проект.

npm install gulp-connect --save-dev

Затем давайте установим пакет, который компилирует файлы .sass в CSS:

npm install gulp-ruby-sass --save-dev

Обратите внимание, что для того, чтобы это работало, в вашей системе должен быть установлен гем Ruby Sass. Подробнее об этом здесь.

Создайте свою первую задачу Gulp

Теперь давайте создадим gulpfile.js в корне каталога нашего проекта и напишем следующий JS-код:

var gulp = require('gulp')
var sass = require('gulp-ruby-sass') 
var connect = require('gulp-connect') 
gulp.task('connect', function () {
  connect.server({ root: 'public', port: 4000 }) 
})

То, что делает этот код, довольно просто. Сначала нам потребуются три пакета Node, которые мы установили ранее, в данном случае Gulp, Gulp Ruby Sass и Connect. Затем мы создаем задачу, которая будет использовать модуль Connect. Каждая написанная вами задача Gulp имеет практически одинаковый синтаксис, единственное отличие состоит в самой задаче, которую Gulp собирается выполнить за вас. Посмотрим.

Чтобы создать новую задачу в Gulp, вы используете метод gulp.task(). Этот метод принимает два аргумента. Первая строка — это имя, которое вы выбираете для своей задачи. В данном случае мы назвали его connect, чтобы знать, что он делает. Второй аргумент — это, по сути, анонимная функция, содержащая код, необходимый для выполнения задачи. В случае задачи подключения мы вызываем метод connect.sever(), который принимает объект параметров, в котором мы указываем, что является корнем нашего приложения, и порт. В данном случае public и 4000 соответственно.

Теперь давайте попробуем, если это работает. Создайте общую папку в корне вашего проекта, затем создайте в ней файл index.html:

<!DOCTYPE html> 
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My App</title>
</head>
  <body>
   <h1>It works!</h1>
  </body>
</html>

Теперь запустите задачу из терминала

gulp connect

и откройте браузер на localhost:4000. Вы должны увидеть большой заголовок с хорошими новостями. Как вы видите, задача все еще выполняется на вашем терминале. Чтобы остановить задачу и тем самым остановить сервер, просто нажмите ctrl + c.

Теперь, когда у нас есть основная настройка локального сервера, давайте напишем код Angular.

Начнем с добавления файла app/main.js в корневой каталог вашего проекта (внутри каталога приложения).

require('angular')
var app = angular.module('app', [])
app.controller('MainController', function($scope) {
 $scope.message = 'Angular Works!' 
})

Прохладный. Но этот код не будет работать, потому что ваш браузер не понимает, что делает require(), верно? Итак, давайте воспользуемся нашим другом Browserify.

Установите и создайте задачу Browserify

Несколько недель назад появился плагин Gulp под названием gulp-browserify, который выполнял эту работу. Теперь он устарел, так как Gulp посчитал его избыточным. Это связано с тем, что сам модуль Browserify можно использовать отдельно в задаче Gulp. Посмотрим, как.

Сначала установите Browserify и Vinyl-Source-Stream, который представляет собой пакет, преобразующий поток Browserify в поток, который действительно понимает Gulp.

npm install --save-dev browserify vinyl-source-stream

Затем потребуйте оба из них в вашем gulpfile.js, который должен выглядеть так:

var gulp = require('gulp')
var sass = require('gulp-ruby-sass')
var connect = require('gulp-connect'
// requires browserify and vinyl-source-stream 
var browserify = require('browserify') 
var source = require('vinyl-source-stream')
// Connect task 
gulp.task('connect', function () {
   connect.server({ root: 'public', port: 4000 })
})

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

1. Он захватывает один или несколько файлов

2. Манипулирует ими

3 .Сохраняет их где-то

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

Теперь давайте напишем задачу, которая выполняет три вышеуказанных действия: берет ваш файл app/app.js, просматривает его и сохраняет в public/js/main.js, чтобы затем включить его в ваш HTML-файл.

Добавьте этот код в свой gulpfile.js:

gulp.task('browserify', function() {
  // Grabs the app.js file 
  return browserify('./app/app.js')
  // bundles it and creates a file called main.js
  .bundle()
  .pipe(source('main.js'))
  // saves it the public/js/ directory
  .pipe(gulp.dest('./public/js/'))
})

Вот и все. Теперь, прежде чем запускать эту задачу, мы должны фактически установить пакет angular Node, потому что мы включаем его в первую строку нашего файла app.js. Это круто, потому что таким образом все, что вам нужно сделать, это:

npm install --save angular

Теперь, когда у вас установлен angular в качестве зависимости (на этот раз обратите внимание на параметр «сохранить»), мы можем продолжить и отредактировать наш файл public/index.html, чтобы загрузить наш файл app.js. Также нам нужно будет реорганизовать этот файл, чтобы иметь атрибут ng-app="app" и контроллер, который показывает сообщение. Ваш файл index.html должен выглядеть так:

<!DOCTYPE html>
<html lang="en" ng-app="app">
  <head> <meta charset="UTF-8">
    <title>My App</title>
    <script src="/js/main.js"></script>
  </head>
<body>
  <div ng-controller="MainController">
    <h1>{{ message }}</h1>
  </div>
</body>
</html>

Теперь, когда наши задачи готовы и зависимость Angular установлена, мы можем продолжить и запустить задачу browserify:

gulp browserify

Gulp регистрирует, сколько времени ушло на выполнение задачи. Когда это будет сделано, вы должны найти файл main.js внутри public/js.

Напомним, что это структура папок, которую мы придумали до сих пор:

Затем давайте запустим наш сервер, запустив задачу подключения:

gulp connect

Теперь перейдите на localhost:4000 и проверьте, отображает ли Angular сообщение Angular Works!.

Но есть еще кое-что. Разработчики ленивы по своей природе, и выполнение задач вручную всякий раз, когда мы вносим изменения в наши файлы JS, менее чем продуктивно. Итак, давайте добавим функцию, которая запускает задачу browserify при каждом сохранении JS-файла.

Добавьте это к вашему gulpfile.js:

gulp.task('watch', function() {
  gulp.watch('app/**/*.js', ['browserify']) 
})
gulp.task('default', ['connect', 'watch'])

Мы добавили две новые задачи. Первая — это задача просмотра, которая сообщает Gulp о необходимости просмотра каждого файла .js в любом подкаталоге внутри /app. Всякий раз, когда файл сохраняется, запускается задача browserify. Чтобы быть более конкретным, метод gulp.watch() принимает два аргумента. Первый — это строка с образцом файла, второй — массив задач для выполнения.

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

Теперь на терминале:

gulp

Идите вперед и отредактируйте значение $scope.message в файле app.js, например, так:

$scope.message = 'Two birds killed with one stone!'

Обновите браузер и бум!.

Модульный угловой

Теперь, когда мы настроили наши основные задачи Gulp, давайте воспользуемся преимуществами Node и Browserify и разделим наш код. Например, на этом этапе было бы неплохо отделить наш контроллер MainController от фактического файла app.js. Давайте сделаем это.

Сначала создайте папку контроллеров в каталоге приложения. Создайте там файл MainController.js, который должен выглядеть так:

module.exports = function($scope) {
 $scope.message = 'Two birds killed with one stone!' 
}

Если вы знакомы с узлом, это должно быть довольно понятно. На самом деле мы «экспортируем» из этого файла функцию, которую передали ранее в наш контроллер (в app.js). Итак, теперь наш файл app.js нужно будет реорганизовать следующим образом:

require('angular') 
var MainController = require('./controllers/MainController') 
var app = angular.module('app', [])
app.controller('MainController', ['$scope', MainController])

Итак, сначала нам нужен наш MainController, который экспортирует функцию и сохраняет ее в var MainController. Затем, в последней строке, мы по-прежнему создаем Angular Controller, но вместо того, чтобы передавать ему встроенную функцию, мы передаем требуемый файл MainController, который экспортирует функцию, так что результат тот же. Конечно, синтаксис немного меняется из-за того, как Angular обрабатывает внедрение зависимостей.

И оттуда у вас могут быть такие папки, как службы или директивы. Или, если ваш проект большой, вы можете создавать папки на основе функций. Например, если в вашем приложении есть страница регистрации, вы можете создать папку с именем Registration, содержащую файлы RegistrationController.js, RegistrationTemplate.html и RegistrationService.js. Это действительно зависит от того, как вы хотите разделить свое приложение.

Это круто

С этой настройкой Gulp и Browserify разделение вашего приложения на разделы (см. Принцип проектирования Разделение проблем) становится проще, потому что вам не нужно будет включать JS-файл в ваш HTML-файл каждый раз, когда вы создаете функцию. Кроме того, большинство библиотек JS, которые вы, вероятно, используете ежедневно, можно установить с помощью npm, чтобы вы могли использовать их в своем коде. К ним относятся такие библиотеки, как jQuery, lodash, moment.js, underscore, superagent и другие.

Скомпилируйте sass с помощью Gulp

Мы уже установили наш плагин gulp-ruby-sass, так что давайте его использовать. Сначала давайте создадим каталог sass в корне нашего проекта, а затем скопируем в него файл sass, например, style.sass. Обратите внимание, что это будет работать и с файлами .scss, но мне больше нравится .sass, потому что он менее загроможден.

$someColor: #bada55 h1 color: $someColor

Затем напишите задачу Gulp:

gulp.task('sass', function() {
 return sass('sass/style.sass') 
.pipe(gulp.dest('public/css')) 
})

И отредактируйте задачу наблюдения, чтобы она также следила за файлом sass:

gulp.task('watch', function() {
 gulp.watch('app/**/*.js', ['browserify']) 
// Watches for changes in style.sass and runs the sass task gulp.watch('sass/style.sass', ['sass']) })

Теперь все, что вам нужно сделать, это связать файл style.css, который будет сгенерирован, с ‹head› HTML-файла:

<link rel="stylesheet" href="/css/style.css">

Теперь запустите gulp в терминале, внесите изменения в файл .sass и наблюдайте.

Вывод

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

Первоначально опубликовано на сайте omarfouad.com 21 марта 2015 г.