Веб-разработка Пример создания нового проекта с помощью Yeoman 1.0beta и Geddy (Node.js)

Чуть менее суток назад было объявлено о выходе Yeoman 1.0beta. Новая версия принесла с собой множество изменений, включая изменившийся синтаксис для командной строки. Главным нововведением можно считать то, что авторы позиционируют новую версию не просто как набор инструментов для разработки, а уже как подобие полноценной среды для веб-разработки. Подробнее о нововведениях можно прочитать здесь.

Сегодня я расскажу о том, как с помощью Yeoman 1.0beta подготовить окружение для разработки нового веб-проекта. Для примера создадим проект, и серверная, и клиентская часть которого будут написаны на javascript. Для этого в качестве инструментов разработки выберем такой экзотичный инструмент как Geddy (Node.js MVC-фреймворк) для бекенда и Ember.js для фронтенда. В качестве шаблонизатора будем использовать Handlebars.js, так как он может работать и на серверной стороне, и на клиентской. Вся работа будет проводиться в Ubuntu 12.04 LTS.

Будем считать, что Yeoman у нас уже установлен. Если нет — обращаемся в одной из предыдущих статей.

Если ранее у вас был установлен Yeoman, то скорее всего, его придется переустановить. У меня, например, он не смог обновиться с версии 0.9.5 до 0.9.6 с помощью команды yeoman update, ссылаясь на отсутствие Bower.

sudo npm uninstall -g yeoman
sudo npm install -g yeoman

На момент написания статьи можно установить лишь Yeoman версии 0.9.6. Это нормально. Для того чтобы работать с Yeoman 1.0 — обращаемся к статье https://github.com/yeoman/yeoman/wiki/Getting-started-with-1.0 и устанавливаем дополнительные инструменты.

sudo npm install -g yo grunt-cli bower

Также обратите внимание, что если у вас ранее был установлен Grunt (отдельно от Yeoman), то следует его удалить до выполнения написанной выше команды.

sudo npm uninstall -g grunt

Процесс установки Yeoman 1.0beta на этом можно считать завершенным. Приступим к установке Geddy — MVC-фреймворка для Node.js. Проще всего установить его через NPM.

sudo npm install -g geddy

В качестве системы управления версиями я использую Subversion. Поэтому создадим для нового проекта каталог, внутри которого создадим подкаталоги branches, tags. Каталог trunk мы создадим при создании веб-приложения.

mkdir ~/www/project
mkdir ~/www/project/branches
mkdir ~/www/project/tags

Переходим в каталог trunk и инициализируем наше Nodejs-приложение с названием «projectname» с помощью Geddy. Обратите внимание, что мы указываем параметр «—handle» для того, чтобы наш проект работал с Handlebars-шаблонами на бекенде. Помимо Handlebars, в Geddy поддерживаются шаблоны Mustache и Jade.

cd ~/www/project
geddy app projectname --handle
mv projectname trunk

Так как мы используем Handlebars-шаблоны на серверной стороне, то нужно установить соответствующий пакет с помощью NPM. Установку будем производить в каталог с проектом.

cd ~/www/project/trunk
sudo npm install handlebars

После этого можно запустить встроенный в Geddy веб-сервер для разработки на Node.js. Приложение по умолчанию запустится по адресу http://127.0.0.1:4000.

cd ~/www/project/trunk
geddy

Изменить номер порта, на котором запускается приложение в режиме разработки, можно в файле config/development.js. Также в каталоге config есть файл production.js с настройками приложения, когда оно запускается в продакшн-режиме. Рекомендую выставить для продакшн-режима другой порт, например 4001. Чуть позже мы настроим Nginx на доменные имена project.com и dev.project.com, поэтому важно, чтобы приложение могло одновременно запуститься и в режиме разработки с выводом отладочных сообщений, и в продакшн-режиме на разных портах.

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

geddy secret

Эта команда создаст файл config/secrets.json, который ни в коем случае не следует включать в SVN. В дальнейшем при запуске приложения на продакшн-сервере следует сгенерировать другой уникальный ключ. После этого можно запустить приложение в продакшн-режиме.

geddy -e production

На этом развертывание серверной части нашего приложения заканчивается. Приступаем к созданию фронтенд-части приложения с помощью Yeoman. Как известно, в состав Yeoman входит система сборки для фронтенд-разработчиков Grunt. Мы настроим ее так, чтобы она склеивала и минифицировала css и js-файлы, относящиеся к фронтенду только в продакшн-режиме нашего приложения. Но в режиме разработки Grunt все равно будет следить за изменениями в наших файлах, так что у нас останется возможность использования, скажем, SASS или CoffeeScript в нашем проекте.

Для развертывания Yeoman-приложения внутри Geddy-приложения создадим каталог /app/views/yeoman.

mkdir ~/www/project/trunk/app/views/yeoman
cd ~/www/project/trunk/app/views/yeoman

С помощью Yeoman 1.0beta можно сгенерировать базовый проект, который будет содержать Html5Boilerplate, Twitter Bootstrap for SASS, Modernizr и jQuery.

yo webapp
sudo npm install

В Yeoman 0.9 можно было создавать базовые проекты следующими командами:

yeoman init              # Создаем базовое приложения, задавая вопросы в процессе создания
yeoman init quickstart   # Базовое приложение с Html5Boilerplate, jQuery и Modernizr
yeoman init bbb          # Приложение с Boilerplate, Bootstrap и Backbone.js
yeoman init ember        # Приложение на Ember.js
yeoman init backbone     # Backbone-Underscore приложение

Для добавления в приложение, которое создается командой «yo webapp», дополнительных js-библиотек, можно воспользоваться Bower, который теперь входит в состав Yeoman. Например, следующие команды установят последние версии Twitter Bootstrap for SASS, Modernizr, jQuery, Ember и Handlebars.

bower install sass-bootstrap
bower install ember
bower install modernizr

Теперь нам нужно сделать точкой входа в приложение файл /app/views/yeoman/app/index.html. По умолчанию в Geddy точкой входа является файл /app/views/main/index.html.hbs, который в зависимости от режима работы приложения (development/production) использует в качестве layout либо файл /app/views/layouts/application.index.hbs, либо /app/views/layouts/production.index.hbs. Таким образом, нам нужно очистить файл /app/views/main/index.html.hbs и сделать мягкую ссылку с именем application.index.hbs на файл /app/views/yeoman/app/index.html.

ln -s ~/www/project/trunk/app/views/yeoman/app/index.html ~/www/project/trunk/app/views/layouts/application.html.hbs

Для того, чтобы корректно отдавать статику в виде картинок, css и js-файлов, следует настроить виртуальный хост в Nginx и проксировать остальные запросы к nodejs-приложению на порт 4000. Конфигурационный файл для Nginx будет выглядеть в этом случае примерно так:

server {
    listen  80;
    server_name  dev.project.com;
 
    access_log  off;
 
    location ~* \.(css|js|jpg|jpeg|png|gif|ico)$ {
        root  /home/andy/www/project/trunk/app/views/yeoman/app/;
    }
 
    location ~ /\.(ht|svn) {
        deny  all;
    }
 
    location / {
        root  /home/andy/www/project/trunk/app/views/yeoman/app/;
        index  index.php;
 
        proxy_pass  http://127.0.0.1:4000;
        include  proxy_params;
    }
}

Еще нужно немного поправить файл Gruntfile.js для того, чтобы в development-режиме создавать css-файлы из scss-файлов в каталоге /app/views/yeoman/app/, а в production-режиме — в каталоге /public.

...
compass: {
    options: {
        sassDir: '<%= yeoman.app %>/styles',
        cssDir: '<%= yeoman.app %>/styles',
        imagesDir: '<%= yeoman.app %>/images',
        javascriptsDir: '<%= yeoman.app %>/scripts',
        fontsDir: '<%= yeoman.app %>/styles/fonts',
        importPath: 'app/components',
        relativeAssets: true
    },
    dist: {
        sassDir: '<%= yeoman.app %>/styles',
        cssDir: '<%= yeoman.dist %>/styles',
        imagesDir: '<%= yeoman.app %>/images',
        javascriptsDir: '<%= yeoman.app %>/scripts',
        fontsDir: '<%= yeoman.app %>/styles/fonts',
        importPath: 'app/components',
        relativeAssets: true,
        environment: 'production',
        outputStyle: 'compressed'
    },
    server: {
        options: {
            debugInfo: true
        }
    }
},
...

Заодно поменяем еще одну настройку в Gruntfile.js. Всю минифицированную и собранную в единые файлы статику мы будем хранить в каталоге /public в корне проекта. Ни в коем случае не нужно включать содержимое каталога /public в SVN.

// configurable paths
var yeomanConfig = {
    app: 'app',
    dist: '../../../public'
};

После всех этих настроек можно запустить наш сервер для разработки и отладки приложения. Для этого нам понадобится открыть два терминала в Ubuntu. В одном запускаем сам сервер.

cd ~/www/project/trunk
geddy

В другом запускаем задачу для Grunt по отслеживанию изменений в файлах проекта. Это нужно, если в проекте используются, например, SASS или CoffeeScript.

cd ~/www/project/trunk/app/views/yeoman
grunt watch

Учитывая, что мы предварительно настроили виртуальный хост dev.project.com в Nginx, набрав http://dev.project.com в адресной строке браузера, мы увидим главную страницу, которая была сгенерирована Yeoman.

Осталось лишь настроить продакшн-сервер на виртуальном хосте project.com. Конфигурационный файл Nginx будет выглядеть подобным образом:

server {
    listen  80;
    server_name  project.com;
 
    access_log  off;
 
    location ~* \.(css|js|jpg|jpeg|png|gif|ico)$ {
        root  /home/andy/www/project/trunk/public/;
        gzip_static  on;
    }
 
    location ~ /\.(ht|svn) {
        deny  all;
    }
 
    location / {
        root  /home/andy/www/project/trunk/public/;
        index  index.php;
 
        proxy_pass  http://127.0.0.1:4001;
        include  proxy_params;
    }
}

Для того чтобы Geddy использовало разные layout-шаблоны в development и production-режима, нужно настроить роуты в файле /app/controllers/main.js.

var Main = function () {
    this.index = function (req, resp, params) {
        this.respond(params, {
            format: 'html',
            template: 'app/views/main/index',
            layout: 'app/views/layouts/' + global.geddy.config.environment
        });
    };
};
 
exports.Main = Main;

После этого останется лишь собрать проект и сделать мягкую ссылку production.html.hbs на файл /public/index.html.

cd ~/www/project/trunk/app/views/yeoman
grunt build --force
ln -s ~/www/project/trunk/public/index.html ~/www/project/trunk/app/views/layouts/production.html.hbs

После этого в еще одном терминале запускаем продакшн-сервер с нашим приложением.

cd ~/www/project/trunk
geddy -e production

В браузере по адресу http://project.com будет работать в продакшн-режиме наше приложение. При этом в отличие от development-версии в нем будут грузиться минифицированные и собранные в единые файлы css и js-файлы.

В следующей статье я расскажу, как научить Grunt автоматически проставлять номера ревизий для файлов в каталоге /public, а также как сжимать статику в gzip-файлы на этапе сборки приложения, не перекладывая эту задачу на веб-сервер.