Grunt — podstawowa konfiguracja task runnera

Published on 2017-07-11 · Junior WebDev

Odcinek drugi serii o task runnerach to wpis o dosyć specyficznym w kodzie narzędziu — grunt dał mi w kość w trakcie konfiguracji, ale o tym wspomnę szerzej w podsumowaniu i ocenie obu zawodników.

Poniżej znajdziesz instrukcję jak skonfigurować grunt w sposób minimalny — to jest skompilować SASS, zminimalizować i połączyć ze sobą pliki oraz skompresować zdjęcia. Tak przygotowany zestaw szybko zainstalujesz i dostosujesz do swoich potrzeb.

0. Instalacja Node.js

Jeśli jeszcze nie masz na komputerze Node.js, zainstaluj go teraz. Polecam na początek zainstalować stabilną wersję 6.11.0, która ma LTS (Long Time Support). Link do strony: https://nodejs.org/en/

1. Wymagania do web developmentu

Określmy, do czego użyjemy gulpa. We front-endzie zależy nam przede wszystkim na minimalizacji wagi plików oraz szybkości ładowania stron. Arkusze styli będą powstawać w SCSS.

Podstawowe zadania:

2. Struktura plików

Na samym początku stwórz dwa główne katalogi: src oraz dist. Wewnątrz src będziesz umieszczać surowe dane, które dopiero będą przetwarzane, a w folderze dist znajdziesz pliki gotowe do użycia po kompilacji/minifikacji. Wewnątrz src stwórz następujące foldery: scss, js, img, a wewnątrz dist: css, js, img.

Struktura plików projektu — konfiguracja grunt

3. Instalacja

Otwórz konsolę i przejdź w niej do katalogu, w którym znajduje się projekt. Na samym początku, jeśli nigdy wcześniej nie korzystałeś z grunta, zainstaluj go globalnie:

npm install -g grunt-cli

Możesz teraz zainicjalizować Node.js oraz npm w folderze za pomocą komendy npm init. W trakcie inicjalizacji npm spyta o kilka informacji, możesz je przeklikać naciskając Enter. Po chwili zostanie utworzony plik package.json z podstawowymi informacjami o projekcie (nazwa, wersja, adres repozytorium etc.).

Następnie możesz przystąpić do instalacji potrzebnych paczek, których użyjesz w task runnerze:

npm install --save-dev grunt grunt-contrib-sass grunt-contrib-cssmin grunt-contrib-concat grunt-contrib-uglify grunt-contrib-imagemin grunt-contrib-watch

Dodatkowo, by móc kompilować pliki SASS, musimy zainstalować Ruby, a za jego pomocą SASS.

  1. Zainstaluj Ruby. Dla Windowsa użyj dedykowanego instalatora: https://rubyinstaller.org/downloads/
  2. Zainstaluj SASS z poziomu konsoli Ruby: gem install sass

4. Konfiguracja pliku

Cały kod będzie zamknięty w specyficznej funkcji, która eksportuje “moduł” do Grunta. Na początku utwórz plik Gruntfile.js. W środku umieść początkową deklarację konfiguracji:

module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json')
  });
}

Grunt będzie wiedzieć, jakich paczek szukać wewnątrz node_modules, dzięki opcji pkg, która wskazuje na plik package.json. Kod odpowiedzialny za utworzenie zadania znajdzie się wewnątrz klamry initConfig, import paczek poza nią, ale wciąż wewnątrz module.exports. Pamiętaj również, że plik konfiguracyjny jest pisany składnią JSON-a, dlatego przecinki po wymienionych taskach są bardzo ważne.

Arkusze styli (SCSS → CSS)

Pod initConfig zaimportuj paczki odpowiedzialne za pierwsze dwa zadania: kompilację SASS i minimalizację CSS.

grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-cssmin');

Natomiast w środku init’a dodaj dwa pierwsze zadania: sass odpowiadający za kompilację i cssmin, który zminimalizuje pliki arkuszy.

sass: {
    dist: {
        files: [{
            expand: true,
            cwd: 'src/scss',
            src: '**/*.scss',
            dest: 'dist/css',
            ext: '.css'
        }],
        options: {
            style: 'expanded'
        }
    }
},
cssmin: {
    target: {
        files: [{
            expand: true,
            cwd: 'dist/css',
            src: ['*.css', '!*.min.css'],
            dest: 'dist/css',
            ext: '.min.css'
        }]
    }
}

Wewnątrz obiektu files znajduje się parę opcji. cwd określa folder rodzica, wewnątrz którego są pliki, które będą przetwarzane. src to źródło, czyli pliki, które są objęte zadanie, dest to lokalizacja, do której trafią pliki, a ext odpowiada za ich rozszerzenie. Dodatkowo dla przejrzystości skompilowane arkusze przed minimalizacją, dzięki options, będą miały format “expanded”.

JavaScript

Tak jak poprzednio, zacznij od importu paczek poza klamrą init’a.

grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');

concat odpowiada za łączenie plików w jeden, uglify natomiast minimalizuje skrypty JS. W przeciwieństwie do styli, zadania skryptów są dosyć krótkie.

concat: {
    dist: {
        src: ['src/js/*.js'],
        dest: 'dist/js/script.js'
    }
},
uglify: {
    my_target: {
        files: {
            'dist/js/script.min.js': 'dist/js/script.js'
        }
    }
}

Tutaj rozjaśnię tylko składnię wewnątrz zadania uglify: w opcji files po lewej znajduje się plik wynikowy, po prawej plik źródłowy.

Optymalizacja zdjęć

Kompresja zdjęć jest tylko odrobinę dłuższa pod względem kodu niż odpowiednik w gulpie. Import:

grunt.loadNpmTasks('grunt-contrib-imagemin');

oraz samo zadanie:

imagemin: {
    dynamic: {
        files: [{
            expand: true,
            cwd: 'src/img',
            src: ['**/*.{png,gif,jpg}'],
            dest: 'dist/img'
        }]
    }
}

Nie używam tutaj dodatkowych opcji (sprawdź dokumentację), według mnie domyślny stopień kompresji jest wystarczający.

Automatyzacja

Niestety w grunt trzeba doinstalować kolejną paczkę, dzięki której będzie możliwe obserwowanie plików:

grunt.loadNpmTasks('grunt-contrib-watch');

Potem możemy już deklarować zadania, które mają być uruchamiane przy zmianach w plikach:

watch: {
    css: {
        files: 'src/scss/**/*.scss',
        tasks: ['sass', 'cssmin']
    },
    scripts: {
        files: 'src/js/**/*.js',
        tasks: ['concat', 'uglify']
    },
    images: {
        files: 'scr/img/**/*.{png,gif,jpg}',
        tasks: ['imagemin']
    }
}

Każda zmiana w pliku może uruchomić więcej niż jedno zadanie, co można wykorzystać w naszej konfiguracji przy arkuszach styli i plikach skryptów.

Zadanie domyślne

Zadanie domyślne zadeklarujemy pod zaimportowanymi paczkami. Pierwszy argument to nazwa taska (w przypadku domyślnego musi to być słowo kluczowe default), drugi to w naszym przypadku lista tasków, które mają zostać uruchomione.

grunt.registerTask('default', ['sass', 'cssmin', 'concat', 'uglify', 'imagemin', 'watch']);

Cały plik możesz skopiować stąd:

Ten wpis jest jedną z części mini serii dotyczącej task runnerów. Zobacz pozostałe wpisy:

  1. Gulp — podstawowa konfiguracja task runnera
  2. Grunt — podstawowa konfiguracja task runnera
  3. Gulp vs Grunt — porównanie task runnerów