Powrót do kategorii
Frontend
tagi
grunt, java script, optymalizacja,

Grunt.js – sposoby optymalizacji plików JavaScript w web aplikacjach

Artur
Artur, 08/01/2015

Automatyzacja naszej pracy pomaga realizować projekty szybciej i sprawia, że programowanie staje się jeszcze bardziej przyjemne. W pracy Front-End Developer’a jest wiele czynności, które można poddać takiemu zabiegowi (np. łączenie i minimalizacja plików js oraz css, kompilacja plików pre-procesorów CSS, optymalizacja grafiki, generowanie Sprite CSS, Sprite SVG i wiele, wiele innych). Z pomocą w tej kwestii przychodzi Grunt.js.

Instalacja

  1. Node.js
    Do działania Grunt.js wymagany jest serwer Node.js. Należy go prostu pobrać i zainstalować z tej strony.
  2. Grunt-CLI (Grunt’s Command Line Iterface)Otwieramy systemowy terminal (dla Windows powinien być uruchomiony z uprawnieniami administratora, natomiast dla systemów UNIX’owych przed poniższą komendą należy dodać  „sudo”) i wpisujemy:
    npm install -g grunt-cli

    W celu sprawdzenia poprawności instalacji można wpisać polecenie:

    grunt --version

    W tym momencie mamy przygotowane środowisko do obsługi Grunt.js. Jest to procedura jednorazowa.

Konfiguracja projektu

W katalogu z projektem, w którym chcemy używać Grunt.js należy utworzyć plik package.json oraz Grunfile.js. Poniżej przedstawiona jest przykładowa struktura plików oraz konfiguracja Grunt.js w celu łączenia oraz minimalizowania plików js w projekcie. W sekcji „Materiały dodatkowe” zamieszczam linki do artykułów szerzej omawiających konfigurację w.w. plików.

struktura plików

root
|-- Gruntfile.js
|-- index.html
|-- js
|   |-- lib
|   |   |-- lib-1.js
|   |   |-- lib-2.js
|   |   |-- lib-3.js
|   |   |-- lib-4.js
|   |   |-- lib-5.js
|   |   `-- lib-6.js
|   |-- main.js
|   |-- modules
|   |   |-- module-1.js
|   |   `-- module-2.js
`-- package.json

Powyższa struktura plików oprócz plików Gruntfile.js oraz package.json zawiera także plik index.html oraz pliki js, które są poddawane optymalizacji.

package.json

{
 "name": "Test",
 "version": "0.1.0",
 "author": "Artur",
 "private": true,
 "devDependencies": {
   "grunt": "^0.4.5",
   "grunt-contrib-concat": "^0.5.0",
   "grunt-contrib-uglify": "^0.5.1",
   "grunt-contrib-watch": "~0.6.1"
 }
}

„devDependencies” zawiera deklarację Grunt.js oraz listę pluginów do instalacji:

Mając gotowy plik package.json można przystąpić do instalacji wszystkich zależności w nim zadeklarowanych. W tym celu należy w wierszu poleceń, będąc w katalogu zawierającym omawiany plik, wykonać komendę:

npm install

Gruntfile.js

module.exports = function(grunt){
 'use strict';
 grunt.initConfig({
  pkg: grunt.file.readJSON('package.json'),
  // Concat
  concat: {
   scripts: {
    src: [
     'js/lib/lib-1.js',
     'js/lib/lib-2.js',
     'js/lib/lib-3.js',
     'js/lib/lib-4.js',
     'js/lib/lib-5.js',
     'js/lib/lib-6.js',
     'js/main.js'
    ],
    dest: 'js/minified/scripts.js',
   }
  },
  // Uglify
  uglify: {
   options: {
    preserveComments: 'some'
   },
   scripts: {
    files: {
     'js/minified/scripts.min.js': ['js/minified/scripts.js']
    }
   },
   modules: {
    expand: true, // Enable dynamic expansion.
    cwd: 'js/modules', // Src matches are relative to this path.
    src: ['**/*.js'], // Actual pattern(s) to match.
    dest: 'js/minified', // Destination path prefix.
    ext: '.min.js', // Dest filepaths will have this extension.
    extDot: 'first' // Extensions in filenames begin after the first dot
   }
  },
  // Watch
  watch: {
   js: {
    files: ['js/*.js', 'js/modules/*.js'],
    tasks: ['concat', 'uglify']
   }
  }
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['concat', 'uglify', 'watch']);
};

W pliku Grunfile.js zawarta jest cała konfiguracja działania poszczególnych pluginów:

  1. Concat (grunt-contrib-concat) Pliki:  lib-1.js, lib-2.js,  lib-3.js, lib-4.js, lib-5.js, lib-6.js, main.js. łączone są w jeden wynikowy plik scripts.js. W tym przypadku ważna jest ich kolejność deklaracji, żeby pliki pluginów były przed plikami je wywołującymi.  Dzięki zabiegowi łączenia, z 7 zapytań do serwera otrzymujemy tylko zapytanie o 1 plik, zyskując na czasie ładowania strony.
  2. Uglify (grunt-contrib-uglify) Task „concat” jest podzielony na dwa pod zadania: – „scripts” Zawartość utworzonego przez poprzedni plugin pliku scripts.js zostaje skompresowana i zapisana do pliku scripts.min.js. Dzięki temu otrzymujemy plik o mniejszym rozmiarze, a zatem również zyskujemy na czasie ładowania strony. – „modules” W bardzo rozbudowanych projektach warto odseparować js dedykowany wyłącznie dla danej części aplikacji, żeby niepotrzebnie nie zwiększały znacznie rozmiaru pliku, w którym i tak nie zostanie wykorzystany. Pliki z katalogu „modules” są automatycznie minimalizowane i zamieniane na plik z końcówką „.min.js”.
    Opcja:

    preserveComments: 'some'

    nakazuje podczas kompresji zachowanie komentarzy zaczynających się od lub zawierających w swojej treści dyrektywy @preserve @license @cc_on.Dzięki temu nie zostają usunięte informacje o autorze i licencji pluginów. Więcej opcji znajduje się na stronie pluginu.

  3. Watch (grunt-contrib-watch)Jeżeli zostanie wykonana jakakolwiek zmiana w plikach js w wybranych lokalizacjach, zostanie uruchomiony task „concat”, a następnie „uglify”. Dzięki temu nie trzeba za każdym razem uruchamiać ręcznie grunt’a.

Gdy plik jest gotowy, całość uruchamiana jest za pomocą komendy:

grunt

Wynikowa struktura plików wygląda następująco:

root
|-- Gruntfile.js
|-- index.html
|-- js
|   |-- lib
|   |   |-- lib-1.js
|   |   |-- lib-2.js
|   |   |-- lib-3.js
|   |   |-- lib-4.js
|   |   |-- lib-5.js
|   |   `-- lib-6.js
|   |-- main.js
|   |-- minified
|   |   |-- module-1.min.js
|   |   |-- module-2.min.js
|   |   |-- scripts.js
|   |   `-- scripts.min.js
|   |-- modules
|   |   |-- module-1.js
|   |   `-- module-2.js
|-- node_modules
|   |-- grunt
|   |-- grunt-contrib-concat
|   |-- grunt-contrib-uglify
|   `-- grunt-contrib-watch
`-- package.json

Dodany został katalog node_modules z zainstalowanym Grunt.js i pluginami oraz katalog minified ze zoptymalizowanymi plikami js.

Wyniki optymalizacji

Przed

grunt-js-before

Czas ładowania strony: 251ms.

Po

grunt-js-after

Czas ładowania strony: 135ms.

Podsumowanie

Optymalizacja plików javascript ma bardzo duży wpływ na szybkość ładowania strony. Już przy połączeniu 7 plików w 1 i kompresji, czas ładowania strony zmniejszył się praktycznie dwukrotnie. Manualna optymalizacja jest bardziej uciążliwa, szczególnie przy pracy w zespole przy dużym projekcie. Jednakże z pomocą przychodzi Grunt.js, dzięki któremu wszystko przebiega szybko, sprawnie i automatycznie.

Materiały dodatkowe

Grunt.js
Grunt.js – Getting started
grunt-contrib-concat
grunt-contrib-uglify
grunt-contrib-watch

Podobne artykuły

Hashowanie plików CSS / JS w Grunt.js

Jak przejąć kontrolę nad pamięcią podręczną przeglądarki.

Audyt UX (użyteczności) – Dlaczego warto go wykonać?

Jedna z dróg do podniesienia sprzedaży na Twojej stronie WWW

Poznajmy się
Poznajmy się
Chcesz porozmawiać o start-upach, projektach lub programowaniu?

Hello World! Sp. z o.o.
ul. Twarda 18
00 -105 Warszawa

+48 22 378 47 27
GOGOmedia
GOGOmedia
Internet Software House

Jesteśmy internetową firmą technologiczną, dostarczamy kompletne rozwiązania informatyczne z zakresu web aplikacji. Kompleksowo obsługujemy klientów z różnych sektorów biznesu w zakresie dedykowanego oprogramowania. Prowadzimy szkolenia, doradzamy, wykonujemy specjalistyczne audyty i dzielimy się zdobytą przez lata wiedzą. Dla wielu jesteśmy partnerem, który pomaga osiągać wyznaczone cele biznesowe w najbardziej optymalny sposób.

Polecamy
Polecamy
narzędzia wspierające naszą codzienną pracę
  • New Relic
  • CloudFlare
  • JIRA
  • Bamboo
  • Axure
  • Zendesk
  • Microsoft Project