30 June 2015

Быстрая разработка на 1С-Битрикс или как я познакомился с gulp

Website development1С-Bitrix


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

Не судите сторого


Так судьба сложилась, что я столкнулся с CMS 1С-Битрикс. Я прекрасно понимаю насколько она громоздкая и «грязная», но приходится иметь дело с тем, что есть. Исходя из этого прошу сильно не критиковать статью, она в первую очередь нацелена на тех, кто работает с этой системой.

Начнем


Первым делом необходимо настроить рабочую среду, а именно заполучить менеджер пакетов npm, который идет вместе с nodejs. Стоп, стоп юные битриксоиды, не разбегаемся, на windows это тоже можно поставить и через консоль работать тоже будет, проверено. А если возникнут вопросы, то google Вам в помощь (обратите внимание на пользовательские переменные среды, пути должны быть правильно прописаны, чтобы команда npm была глобальной).

Установив npm, мы получаем возможность установить все требуемые зависимости. Чтобы это сделать создадим файл:

package.json


{
  "name": "frontend-bitrix",
  "version": "1.0.0",
  "description": "",
  "author": "jmaks",
  "license": "ISC",
  "dependencies": {
    "gulp": "^3.8.11",
    "gulp-autoprefixer": "^2.1.0",
    "gulp-minify-css": "^1.0.0",
    "gulp-rigger": "^0.5.8",
    "gulp-sass": "^1.3.3",
    "gulp-uglify": "^1.1.0",
    "gulp-sourcemaps": "^1.5.0",
    "gulp-watch": "^4.1.1",
    "gulp-imagemin": "^2.2.1",
    "imagemin-pngquant": "^4.0.0",
    "gulp.spritesmith": "latest",
    "gulp-plumber": "latest"
  }
}

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

  • gulp — сам сборщик
  • gulp-autoprefixer — автоматически добавляет вендорные префиксы к CSS свойствам
  • gulp-minify-css — сжатие CSS кода
  • gulp-rigger — позволяет импортировать один файл в другой простой конструкцией
  • gulp-sass — для компиляции нашего SCSS кода
  • gulp-uglify — сжимать наш JS
  • gulp-sourcemaps — для генерации css sourscemaps, которые будут помогать нам при отладке кода
  • gulp-watch — наблюдение за изменениями файлов
  • gulp-imagemin — сжатие картинок
  • imagemin-pngquant — сжатие картинок | работа с PNG
  • gulp.spritesmith — создание png спрайтов
  • gulp-plumber — ловим ошибки, чтобы не прервался watch

Также нам потребуется такой прекрасный пакетный менеджер как Bower. Устанавливаем сначала его с помощью npm (установка bower идет отдельно от нашей установки зависимостей, так как bower нам надо установить глобально), а потом аналогично создадим файл с настройками:

bower.json


{
  "name": "frontend-bitrix",
  "version": "0.0.1",
  "authors": [
    "jmaks1 <my.mailname@mail.ru>"
  ],
  "license": "MIT",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
  "dependencies": {
    "jquery": "2.*",
    "bootstrap-sass": "*"
  }
}

Тут все аналогично package.json, есть блок dependencies, который содержит список загружаемых пакетов. Здесь мы загрузим jquery и bootstrap-sass.

Как Вы уже заметили, я использую связку bootstrap'а и css препроцессора sass.
По первому пункту — bootstrap, использую его в виду того, что сам 1С-Битрикс постепенно начинает использовать этот CSS-фреймворк (ну и просто привык уже к нему).
По второму пункту — Sass. Этот препроцессор более функционален чем less, последний я очень любил, но он не смог конкурировать с Sass.

Создадим структуру нового проекта


Создавая новый магазин/портал/«что то еще на битриксе» я устанавливаю на локальном сервере нужную редакцию битрикса. Во время установки выберите любой готовый шаблон из стартовых, а потом просто отмените мастер установки, чтобы не захламить сайт демо данными, в итоге получим такую структуру сайта:
auth
bitrix
upload

Теперь создадим разделы для билда и файлов разработки. Билд — это наш шаблон сайта, в нем будут собираться все файлы, разместить его необходимо в директории /local/. Для тех кто в танке — эта директория равнозначна /bitix/, то есть мы можем в ней создавать компоненты, шаблоны и так далее. Разработку же будем вести в директории /src/, внутри нее создадим простую структуру.

В итоге получим:
auth
bitrix
upload
local
— templates
— — main
src
— fonts
— images
— sprite
— js
— — partials
— styles
— — partials

Тут все тривиально:
Директория local содержит базовый шаблон сайта main.
Директория src содержит:

  • fonts — шрифты
  • images — картинки
  • sprite — иконки для спрайта
  • js — скрипты. В корне этой папки будет файл script.js, который пригодится нам для сборки.
  • styles — стили. Тут так же, в корне template_styles.scss.

Файлы из директории partials в обоих случаях будут дополнительными, их мы просто подключим в главном файле, соответственно в script.js подключим все скрипты, а в template_styles.scss все дополнительные файлы стилей.

Подключать файлы будем конструкцией //= для script.js:

// include jquery
//= ../../bower_components/jquery/dist/jquery.min.js
// include bootstrap.js
//= ../../bower_components/bootstrap-sass/assets/javascripts/bootstrap.min.js

console.log("i'm a live!");

// another scripts
//= partials/app.js

Scss файлы подключим с помощью @import:

// include bootstrap sass
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap";

// include variables
@import "partials/variables";
// include sprite
@import "partials/sprite";
// include mixin
@import "partials/mixin";
// include fonts
@import "partials/fonts";

Получив структуру проекта, добавим в её корень наши файлы bower.json и package.json. Осталось только создать файл настроек для нашего сборщика — gulpfile.js. Именно этот файл будет отвечать за всю магию.

gulpfile.js


Все зависимости, которые мы прописали в файле package.json подключаем внутри gulpfile.js:

'use strict';

var gulp        = require('gulp'),
    watch       = require('gulp-watch'),
    prefixer    = require('gulp-autoprefixer'), 
    uglify      = require('gulp-uglify'),     
    rigger      = require('gulp-rigger'),     
    sass        = require('gulp-sass'),   
    sourcemaps  = require('gulp-sourcemaps'),
    cssmin      = require('gulp-minify-css'),  
    imagemin    = require('gulp-imagemin'), 
    pngquant    = require('imagemin-pngquant'), 
    spritesmith = require('gulp.spritesmith'),
    plumber     = require('gulp-plumber');

Создадим объект path со всеми путями, чтобы при необходимости легко в одном месте их редактировать. Они будут использоваться нашими таск'ами (task — задача, ставим задачи нашему менеджеру, а он быстро все исполняет).

var path = {
    build: {
        js:            'local/templates/main/',
        css:           'local/templates/main/',
        images:        'local/templates/main/images/',
        fonts:         'local/templates/main/fonts/',
        fontsBootstrap:'local/templates/main/fonts/bootstrap/'
    },
    src: {
        js:            'src/js/script.js',
        styles:        'src/styles/template_styles.scss',
        stylesPartials:'src/styles/partials/',
        spriteTemplate:'src/sass.template.mustache',
        images:        'src/images/**/*.*',
        sprite:        'src/sprite/*.*',
        fonts:         'src/fonts/**/*.*',
        fontsBootstrap:'bower_components/bootstrap-sass/assets/fonts/bootstrap/*.*'
    },
    watch: {
        js:    'src/js/**/*.js',
        styles:'src/styles/**/*.scss',
        images:'src/images/**/*.*',
        sprite:'src/sprite/*.*',
        fonts: 'src/fonts/**/*.*'
    }
};

Подключив все зависимости и написав маршруты создадим таск'и, которые отвечают за всю работу нашего сборщика.

Сборщик js файлов
gulp.task('js:build', function () {
    gulp.src(path.src.js)               // Найдем наш main файл
        .pipe(plumber())
        .pipe(rigger())                 // Прогоним через rigger
        .pipe(sourcemaps.init())        // Инициализируем sourcemap
        .pipe(uglify())                 // Сожмем наш js
        .pipe(sourcemaps.write())       // Пропишем карты
        .pipe(plumber.stop())
        .pipe(gulp.dest(path.build.js)) // Выплюнем готовый файл в build
});

Сборщик css файла
gulp.task('styles:build', function () {
    gulp.src(path.src.styles)            // Выберем наш main.scss
        .pipe(plumber())
        .pipe(sourcemaps.init())         // То же самое что и с js
        .pipe(sass())                    // Скомпилируем
        .pipe(prefixer())                // Добавим вендорные префиксы
        .pipe(cssmin())                  // Сожмем
        .pipe(sourcemaps.write())        // Пропишем карты
        .pipe(plumber.stop())
        .pipe(gulp.dest(path.build.css)) // И в build
});

Таск, отвечающий за сжатие всех картинок
gulp.task('image:build', function () {
    gulp.src(path.src.images) //Выберем наши картинки
        .pipe(plumber())
        .pipe(imagemin({   //Сожмем их
            progressive: true,
            svgoPlugins: [{removeViewBox: false}],
            use: [pngquant()],
            interlaced: true
        }))
        .pipe(plumber.stop())
        .pipe(gulp.dest(path.build.images))
});

Таск собирающий спрайт
gulp.task('sprite:build', function() {
    var spriteData =
        gulp.src(path.src.sprite)
            .pipe(spritesmith({
                imgName: 'sprite.png',
                cssName: 'sprite.scss',
                cssFormat: 'scss',
                algorithm: 'binary-tree',
                padding: 20,
                cssTemplate: path.src.spriteTemplate,
                cssVarMap: function(sprite) {
                    sprite.name = 's-' + sprite.name
                }
            }));

    spriteData.img.pipe(gulp.dest(path.build.images));
    spriteData.css.pipe(gulp.dest(path.src.stylesPartials));
});

Он берет все наши иконки из папки sprite и генерирует спрайт, параллельно на основе файла sass.template.mustache он создает scss файл, в который записываются все размеры и позиции иконок.

sass.template.mustache


{{#items}}
${{name}}: {{px.x}}, {{px.y}}, {{px.offset_x}}, {{px.offset_y}}, {{px.width}}, {{px.height}}, {{px.total_width}}, {{px.total_height}}, '{{{escaped_image}}}';
{{/items}}

Перенос шрифтов в билд
//Переместим шрифт bootstrap'а, для работоспособности иконок 
gulp.task('icons:build', function() {
    gulp.src(path.src.fontsBootstrap)
        .pipe(gulp.dest(path.build.fontsBootstrap));
});
// Переместим шрифты из папки src
gulp.task('fonts:build', function() {
    gulp.src(path.src.fonts)
        .pipe(gulp.dest(path.build.fonts))
});

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

gulp.task('build', [
    'js:build',
    'sprite:build',
    'icons:build',
    'fonts:build',
    'styles:build',
    'image:build',
]);

gulp.task('watch', function(){
    watch([path.watch.js], function(event, cb) {
        gulp.start('js:build');
    });
    watch([path.watch.sprite], function(event, cb) {
        gulp.start('sprite:build');
    });
    watch([path.watch.styles], function(event, cb) {
        gulp.start('styles:build');
    });
    watch([path.watch.fonts], function(event, cb) {
        gulp.start('fonts:build');
    });
    watch([path.watch.images], function(event, cb) {
        gulp.start('image:build');
    });
});

gulp.task('default', ['build', 'watch']);

В итоге мы получаем в корне проекта три файла конфигураций, исполним их прописав команды в консоли:

  • npm install — установятся все зависимости, которые требует gulp (создастся директория node_modules)
  • bower install — поставим плагины для нашего сайта (создастся директория bower_components)
  • gulp — запустим наш сборщик

профит!

Итог


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

Подводные камни


Перед созданием резервной копии сайта не забудьте поставить исключение на директории: node_modules и bower_components, иначе резервная копия не создасться. Эти папки нужны только для разработки, в «боевой» версии сайта они не понадобятся.



p.s.
Статья берёт начало из статьи «Приятная сборка frontend проекта» – рекомендую ознакомиться.
Если кому то интересно, могу добавить в сборщик генерацию svg спрайтов.
Tags:1с-битриксgulpsassbootstrapnpmbower
Hubs: Website development 1С-Bitrix
+11
23.8k 126
Comments 18
Top of the last 24 hours