Manchetten

Подключение gulp для сжатия ассетов в Yii2

Я обожаю Yii2 - он очень прост и логичен, при этом очень гибок, мощно документирован и имеет невероятное количество плагинов, а также отзывчивое и гигантское комьюнити. Но порой, от некоторых вещей, которые реализованы в нем, впадаешь в ступор.

В качестве примера - сжатие и объединение ресурсов.  Фреймворк предлагает достаточно подробную документацию, описывая сам механизм построения ассетов и настройку бандлов для сжатия и минификации. В принципе, этого достаточно. Но сами инструменты для сжатия достаточно кривые.  Очень здорово, что фреймворк позволяет расширить эту функциональность. И очень классным решением будет подключить Gulp.js

Заводится он достаточно просто. В первую очередь, нужно вызвать консольную команду yii asset, чтобы сгенерировать конфиг для продакшена. Конфиг удобнее назвать assets_generate_conf.php и рядом же создать assets-dev.php, для возможности подключения не сжатых ассетов для разработки. 

В assets_generate_conf указываем новые компрессоры вместо дефолтных:

'jsCompressor' => './tools/gulp compress-js --gulpfile tools/gulpfile.js --src {from} --dist {to}',
'cssCompressor' => './tools/gulp compress-css --gulpfile tools/gulpfile.js --src {from} --dist {to}',

Далее стандартно по мануалу. Если используются кастомные библиотеки для Bootstrap и Jquery, то их переопределенные версии также можно включить в итоговый бандл, указав параметр bundles:

// Asset manager configuration:
    'assetManager' => [
        'basePath' => '@webroot/assets',
        'baseUrl' => '@web/assets',
        'bundles' => [
            'yii\bootstrap\BootstrapAsset' => [
                //'sourcePath' => '@vendor/bower/bootstrap/dist',
                'css' => []
            ],
            'yii\bootstrap\BootstrapPluginAsset' => [
                'css' => []
            ],
            'yii\web\JqueryAsset' => [
                'js' => []
            ]
        ]
    ],

Содержимое assets_generate_conf:

// In the console environment, some path aliases may not exist. Please define these:
Yii::setAlias('@webroot', __DIR__ . '/../web');
Yii::setAlias('@web', '/');

return [
    'jsCompressor' => './tools/gulp compress-js --gulpfile tools/gulpfile.js --src {from} --dist {to}',
    'cssCompressor' => './tools/gulp compress-css --gulpfile tools/gulpfile.js --src {from} --dist {to}',

    // The list of asset bundles to compress:
    'bundles' => [
        'yii\web\YiiAsset',
        'yii\web\JqueryAsset',
        'yii\bootstrap\BootstrapAsset',
        'yii\bootstrap\BootstrapPluginAsset',
        'app\assets\AppAsset',
    ],

    // Asset bundle for compression output:
    'targets' => [
        'all' => [
            'class' => 'yii\web\AssetBundle',
            'basePath' => '@webroot/assets',
            'baseUrl' => '@web/assets',
            'js' => 'js/all-{hash}.js',
            'css' => 'css/all-{hash}.css',
            'jsOptions' => [
                'position' => \yii\web\View::POS_END
            ],
        ],
    ],
    // Asset manager configuration:
    'assetManager' => [
        'basePath' => '@webroot/assets',
        'baseUrl' => '@web/assets',
        'bundles' => [
            'yii\bootstrap\BootstrapAsset' => [
                'css' => []
            ],
            'yii\bootstrap\BootstrapPluginAsset' => [
                'css' => []
            ],
            'yii\web\JqueryAsset' => [
                'js' => []
            ]
        ]
    ],
];

Далее, в корне создаем папку tools, в ней размещаем gulpfile.js со следующим содержимым:

var gulp = require('gulp');
var uglify = require('gulp-uglify');
var minifyJs = require('gulp-minify');
var cssMin = require('gulp-css');


// Need because of `yii console`
var rename = require('gulp-rename');
var minimist = require('minimist');
var options = minimist(process.argv.slice(2), { string: 'src', string: 'dist' });
var destDir = options.dist.substring(0, options.dist.lastIndexOf("/"));
var destFile = options.dist.replace(/^.*[\\\/]/, '');


// Use `compress-js` task for JavaScript files
gulp.task('compress-js', function() {
    gulp.src(options.src)
        .pipe(uglify())
        .pipe(minifyJs())

        .pipe(rename(destFile))
        .pipe(gulp.dest(destDir))
});

// Use `compress-css` task for CSS files
gulp.task('compress-css', function() {
    gulp.src(options.src)
        .pipe(cssMin())

        .pipe(rename(destFile))
        .pipe(gulp.dest(destDir))
});

Через npm устанавливаем сам gulp локально - для меня это оказалось проще, чем таскать весь стек nodejs по серверам. Для того, чтобы gulp смог выполниться, в папке tools необходимо создать симлинк на непосредственно исполняемый файл:

ln -sfn node_modules/gulp/bin/gulp.js gulp

После установки gulp и всех подключаемых модулей, можно выполнить команду сборки:

php yii asset config/asset_generate_conf.php config/assets-prod.php

Если все пройдет успешно, то директории web появятся папки js и css, в которых будут минифицированные бандлы. Новый конфиг будет сгенерирован в config/assets-prod.php

После переключения приложения в продакшен режим, ассеты автоматически подключатся из минифицированных версий

By Manchetten

Собираю самое интересное о разработке, музыке и не только.