Приложение на Express.js + Sass/Compass + CoffeeScript + Haml

Добрый день!
Решил поделиться опытом перехода с Middleman (Ruby) на Express.js (Node.js) в качестве инструмента front-end разработчика.
Сам я занимаюсь back-end, так что статья может выйти не слишком актуальной, но, надеюсь, полезной хотя бы кому-нибудь.

Итак, задача: сделать приложение на Node.js с поддержкой компиляции Sass(Compass), CoffeeScript и Haml «на лету» при редактировании соответствующих файлов. Для этого будем использовать Express и Grunt для запуска веб-сервера и выполнения задач компиляции соответственно.

Для начала, нам нужен сам Node. Я предпочитаю для его установки и контроля версий использовать NVM (аналог RVM для Ruby).

Ставим NVM:
curl https://raw.github.com/creationix/nvm/master/install.sh | sh

И подключаем его:
source ~/.nvm/nvm.sh


Далее, ставим и подключаем последнюю версию Node (на данный момент она не вышла из 0.10.*, поэтому для установки последней версии достаточно прописать):
nvm install 0.10
nvm use 0.10


Теперь можно использовать сам Node вместе с его менеджером пакетов npm. Ставим Express и Grunt глобально:
npm install -g express
npm install -g grunt-cli


Создаем express-приложение с помощью express <проект> -e:
express develop -e
cd develop

Опция -e устанавливает базовым шаблонизатором ejs, который будет спокойно рендерить обычные html, в которые мы будем компилировать наш haml. Для того, чтобы показать приложению, что нужно делать именно так, добавим в app.js в настройки app строку
app.engine('html', require('ejs').renderFile);


Сразу установим все нужные пакеты через npm:
npm install grunt-contrib-watch grunt-contrib-sass grunt-contrib-compass grunt-contrib-coffee grunt-contrib-haml grunt-express-server --save-dev

(опция --save-dev пропишет нужные зависимости в нашем package.json, чтобы потом их не потерять)

Теперь установим все остальные зависимости Express'а:
npm install


Ну и последнее: создаем файл Gruntfile, в котором будем описывать нужные таски:
touch Gruntfile.js


Подготовку закончили! Теперь — за сами таски. Пишем в Gruntfile что-то типа
module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    // здесь будут настроенные нами таски
  });

  // здесь будут подключаться необходимые модули
  grunt.loadNpmTasks('');

  // а здесь - вызываться таски
  grunt.registerTask('default', ['']);

};


И начинаем заполнять его. Сперва подключим все нужные модули в loadNpmTasks:

  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-haml');
  grunt.loadNpmTasks('grunt-contrib-sass');
  grunt.loadNpmTasks('grunt-contrib-compass');
  grunt.loadNpmTasks('grunt-contrib-coffee');
  grunt.loadNpmTasks('grunt-express-server');


Теперь можем начать описывать задания (таски) компиляции:
Все вью будем хранить в папке views/, все js и coffee — в javascripts/, все css и scss — в stylesheets/.
Создадим несколько файлов для примера:
touch public/javascripts/x.coffee
touch public/stylesheets/s.scss
touch views/index.haml


И удалим ненужный нам index.ejs, созданный по умолчанию:
rm views/index.ejs


Все coffee можно скомпилировать в один js, чем мы воспользуемся.
Набор тасков для компиляции будет выглядеть следующим образом:
    haml : {
      dist: {
        files: {
          'views/index.html': 'views/index.haml'
        }
      }
    },
    sass : {
      dist: {
        files: {
          'public/stylesheets/s.css': 'public/stylesheets/s.scss'
        }
      }
    },
    coffee : {
       compile: {
        files: {
          'public/javascripts/x.js': ['public/javascripts/*.coffee']
        }
      }
    }


! Чтобы сработал таск haml, в системе должен быть установлен и доступен гем haml (и ruby, конечно)!

Чтобы использовать Compass вместо Sass, нужно заменить соответствующий таск (sass) на
  compass: {
      dev: {
        options: {
          sassDir: ['public/stylesheets'],
          cssDir: ['public/stylesheets'],
          environment: 'development'
        }
      }
    },


Теперь добавим таски к выполнению в блок registerTask:
grunt.registerTask('default', ['sass', 'coffee', 'haml']);

(compass вместо sass при необходимости)

Выполним grunt и увидим, что таски успешно выполнились, и в соответствующих папках теперь можно найти index.html, s.css и x.js.
Осталось только включить сервер и сделать процесс рекомпиляции автоматическим с помощью watch. Gruntfile получится таким:

module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    // здесь будут настроенные нами таски
    watch : {
      haml : {
        files : 'views/*.haml',
        tasks : 'haml'
      },
      coffee : {
        files : 'public/javascripts/*.coffee',
        tasks : 'coffee'
      },
      sass : {
        files : 'public/stylesheets/*.scss',
        tasks : 'sass'
      },
      //  compass : {
      //    files: ['public/stylesheets/*.{scss,sass}'],
      //    tasks: ['compass']
      //  }
    },
    express : {
      dev: {
        options: {
          script: 'app.js'
        }
      }
    },
    haml : {
      dist: {
        files: {
          'views/index.html': 'views/index.haml'
        }
      }
    },
    sass : {
      dist: {
        files: {
          'public/stylesheets/s.css': 'public/stylesheets/s.scss'
        }
      }
    },
    compass: {
      dev: {
        options: {
          sassDir: ['public/stylesheets'],
          cssDir: ['public/stylesheets'],
          environment: 'development'
        }
      }
    },
    coffee : {
       compile: {
        files: {
          'public/javascripts/x.js': ['public/javascripts/*.coffee']
        }
      }
    }
  });

  // здесь будут подключаться необходимые модули
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-haml');
  grunt.loadNpmTasks('grunt-contrib-sass');
  grunt.loadNpmTasks('grunt-contrib-compass');
  grunt.loadNpmTasks('grunt-contrib-coffee');
  grunt.loadNpmTasks('grunt-express-server');

  // а здесь - вызываться таски
  grunt.registerTask('default', ['sass', 'coffee', 'haml', 'express', 'watch']);
};

(Соответственно, для использования Compass нужно будет поменять таск sass на compass в описании таска watch и в регистрации таска default)

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

Update: Livereload
Таск watch можно настроить на livereload страницы.
Для этого нужно добавить в описание таска watch соответствующие options:
 watch : {
      options: {
        livereload: true,
        nospawn: true
      },
      haml : {
        files : 'views/*.haml',
        tasks : 'haml'
      },
      coffee : {
        files : 'public/javascripts/*.coffee',
        tasks : 'coffee'
      },
      // sass : {
      //   files : 'public/stylesheets/*.scss',
      //   tasks : 'sass'
      // },
      compass: {
        files: ['public/stylesheets/*.{scss,sass}'],
        tasks: ['compass']
      }
    }

И включить на страницу скрипт livereload, через порт по умолчанию 35729
%script{src:"//localhost:35729/livereload.js"}


===================

Спасибо прочитавшим!
В следующих статьях планирую поделиться своим опытом знакомства с Sails.js (Rails-like MVC на Node) и прочими радостями server-side JS.

Similar posts

Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 12

    0
    А в чем вы выиграли, перенеся фронтенд разработку с Middleman на Node? Интересно, потому что сам сейчас работаю с Middleman.
      0
      Дело в том, что основную разработку мы ведем на Rails, но в последнее время в некоторых проектах Node стал окупать себя (в частности, в мелких проектах, для которых Rails чересчур велик, а также в проектах с плотным async-общением). Поэтому стало иногда удобнее верстать сразу в окружении Node. Это отнюдь не замена Middleman — просто альтернатива.
        0
        Ситуация с проектами, для которых RoR велик знакома. Мы только начинаем смотреть в сторону NodeJS. Будет очень интересно почитать ваши статьи о Sails.js.
          0
          Sails.js — далеко не аналог Rails, но предоставляет множество удобных, хотя и иногда спорных штук. В целом — очень приятный, понятный фреймворк, но куда более легковесный, нежели Rails. Впрочем, может быть проблема как раз в том, что Rails немного раздут.
            0
            Извините за офтоп. Если вам знакомы rails, node.js и coffee-script, думаю, будет интересно посмотреть costa.
            0
            После знакомства с middleman, думаю, это лучшее решение для подобных задач. Можно, конечно, держать заготовку грунтфайла, но в миддлемане куда меньше нужно настраивать. Плюс гемы с bootstrap/foundation и прочим. Livereload опять же из коробки, у вас не увидел про него ничего. Хотя он вроде в grunt-contrib-watch есть, я еще не попробовал.
              +1
              Стоит попробовать :) Очень дельная утилита. Еще можно глянуть mean.io и Hackathon Starter для полного фарша, где (почти) все настроено — можно взять и использовать.
                0
                VasilioRuzanni , printercu — спасибо за ссылки!
                Про Livereload дописал.
          0
          Почему не подключить HAML как шаблонитизатор для expressjs?
            0
            Спасибо автору за статью! Хотелось бы так же добавить, что в Yeoman есть генератор Express.js проектов с компиляцией ресурсов «на лету». Для хранения данных используется mongodb (можно удалить из config.js если не надо).

            Ссылка на генератор

            генерация проекта

            mkdir express-project && cd express-project
            npm install -g yo
            npm install generator-express
            yo express --mvc
            grunt
            


            установка mongo (mac osx)
            brew update && brew install mongodb
            sudo mkdir -p /data/db
            sudo chown `id -u` /data/db
            mongod &
            
              0
              Друзья, большое спасибо за комментарии и подсказки!
              Я описал всего лишь один из способов решить поставленную задачу, он не претендует на звание лучшего — просто довольно понятный, простой и рабочий вариант.
                +1
                Вместо compass я бы порекомендовал Bourbon. Его можно установить прямо в папку со стилями, что избавляет от необходимости в grunt-contrib-compass. Плюс у бурбона документация удобнее на порядок.

                Only users with full accounts can post comments. Log in, please.