• Strona główna
  • Curriculum Vitae
  • O mnie
  • Przykład: Gramatyka w PHP
  • Przykład: Kompresja CSS
  • Przykład: Kompresja JavaScript
  • Przykład: Skracanie linków
  • Przykład: Wykrywanie serwera HTTP
  • Przykład: Własna bramka SMS
  • Mapa strony
  • Kontakt
Niebieski Pomarańczowy Zielony Różowy Fioletowy

Kompresja CSS

Opublikowane 22 kwietnia 2010. Autor: Kamil Brenk. Wizyt: 6 288.

Kategorie: PHP
Tematyka: Apache, CSS, kompresja gzip, Minify CSS, optymalizacja serwisów, PHP, PHP PEAR, praktyczne skrypty, Protokół HTTP, wydajność serwisów internetowych, Wyrażenia regularne

kw. 22

Minimalizacja żądań do zewnętrznych zasobów, kompresja kodu wysyłanego do użytkownika, optymalizacja skyptów i styli, buforowanie i cachowanie – jako programista/webdeveloper powinieneś dążyć do tego celu nieustannie i niestrudzenie :-)

W nieniejszej notce zaprezentuję swoją małą bibliotekę do minimalizacji, kompresji i oczyszczania plików CSS – nieodzownych przy budowie każdej nowoczesnej strony internetowej (zgodnej z modelem MVC).

Dlaczego warto?

Niewielu graczy w internetowym półświatku stosuje kompresję i optymalizację stylów CSS. Przekłada się to na dłuższy czas rendowania strony (ponieważ zawartość HEAD dokumentu jest wysyłana przed rozpoczęciem wczytywania elementu BODY). Tracą na tym wszyscy:

  • użytkownik musi dłużej czekać – niektórzy zdążą przejść do innej strony,
  • serwis generuje więcej transferu – wyższe zapotrzebowanie na transfer oznacza wyższe koszty na serwer,
  • wyszukiwarki powoli zaczynają uwzględniać czas wczytywania strony.

Jak sobie z tym poradzić? Wystarczy napisać niezbyt skomplikowaną klasę wykonującą całe zadanie za nas.

Do roboty, zaczynamy!

W notce tej wykorzystamy element pakietu PHP PEAR – Cache_Lite. W niniejszym przykładzie wystarcza w zupełności.

Na początek napiszemy prosty interfejs, CodeCompressor. Przyda się on także przy kolejnym poście, kiedy to opiszę kompresor JavaScript. Pisząc jeszcze inne biblioteki minimalizujące kod, będę mógł oprzeć się na tym interfejsie, także myślę, iż jest to dobry punkt wyjścia.

Plik ten prezentuje się następująco:

1
2
3
4
5
6
7
8
9
10
11
interface CodeCompressor {

    public function addFiles($url_files);
    public function addFile($url_file);
   
    public function cleanCode($code);
    public function compressCode($code);
   
    public function showCode();
   
}

Zapiszmy go w pliku: interface.CodeCompressor.php

CSS Compressor

Czas na implementację logiki skryptu. Rozpocznijmy od nadania głównego kształtu klasie:

1
2
3
4
5
6
7
8
require_once 'interface.CodeCompressor.php';
require_once 'Cache/Lite.php';

class CSSCompressor implements CodeCompressor {

    // ...

}

Zapisujemy to w nowym pliku: class.CSSCompressor.php

Na początku damy tablicę z domyślnymi ustawieniami konfiguracyjnymi klasy:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* Domyślne ustawienia konfiguracyjne dla klasy
**/

private $config = array(
   
    'charset'               =>  'utf-8',    // kodowanie znaków
       
    'clean_code'            =>  true,       // czyszczenie kodu
    'compress_code'         =>  true,       // kompresja kodu
       
    'import_mode'           =>  true,       // włączanie wewnętrznych styli (@import)
       
    'gzip_contents'         =>  true,       // kompresja gzip
    'gzip_level'            =>  6,          // poziom kompresji gzip
       
    'cache_enabled'         =>  true,       // buforowanie po stronie serwera
    'cache_location'        =>  'tmp/',     // folder dla cache
    'use_flush_key'         =>  true,       // własnoręczne usuwanie cache, ?flush=FILE_ID
       
    'use_cache_browser'     =>  true,       // buforowanie po stronie klienta
    'time_cache_browser'    =>  3600        // czas trzymania w buforze (sekundy)
   
);

Wszystko jest ładnie opisane i myślę, że więcej wyjaśniać nie trzeba (w razie wątpliwości później będą rozwinięte te właściwości).

Ustawienia te możemy dowolnie skonfigurować we własnym zakresie, choć wydaje mi się, że te powyższe są całkiem dobre.

Dodajmy kilka innych właściwości klasy, niezbędnych do prawidłowego działania:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// zmienna przechowująca złączony kod css
private $css_code;
   
// tablica z adresami plików do złączenia i optymalizacji
private $files_require = array();
   
// tablica przechowująca adresy plików, które już przetworzono
private $files_loaded = array();
   
// przechowuje importowane pliki (@import)
private $files_import = array();
   
// uchwyt dla klasy buforującej wynik
private $cache_lite;
   
   
// zerowe wielkości atrybutów - różne zapisy
private $sizes = array(
            array(' 0px', ' 0em', ' 0%', ' 0ex', ' 0cm', ' 0mm',
                    ' 0in', ' 0pt', ' 0pc'),
            array(':0px', ':0em', ':0%', ':0ex', ':0cm', ':0mm',
                    ':0in', ':0pt', ':0pc')
);
   
// wartości css => ich krótsze zamienniki
private $shortcuts = array(
       
            // specjalne znaki
            ', '    => ',',
            ' , '   => ',',
            ';}'    => '}',
            '; }'   => '}',
            ' ; }'  => '}',
            ' :'    => ':',
            ': '    => ':',
            ' {'    => '{',
            '; '    => ';',
           
            // kolory
            ':black'        => ':#000',
            ':darkgrey'     => ':#666',
            ':fuchsia'      => ':#F0F',
            ':lightgrey'    => ':#CCC',
            ':orange'       => ':#F60',
            ':white'        => ':#FFF',
            ':yellow'       => ':#FF0',
               
            ':silver'       => ':#C0C0C0',
            ':gray'         => ':#808080',
            ':maroon'       => ':#800000',
            ':red'          => ':#FF0000',
            ':purple'       => ':#800080',
            ':green'        => ':#008000',
            ':lime'         => ':#00FF00',
            ':olive'        => ':#808000',
            ':navy'         => ':#000080',
            ':blue'         => ':#0000FF',
            ':teal'         => ':#008080',
            ':aqua'         => ':#00FFFF'

        );
           
// font-weight:name => font-weight:num
private $font_weight_to_num = array(
            'lighter'       => 100,
            'normal'        => 400,
            'bold'          => 700,
            'bolder'        => 900
        );

Możemy przejść do tworzenia kolejnych metod. Pozostanę przy opisywaniu kodu bezpośrednio w komentarzach języka, gdyż jest to po prostu wygodniejsze.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public function __construct($config=array()) {
   
    // jeśli nie zdefiniowano ustawień - pozostaw domyślne
    if (!is_array($config)) return false;
       
    // przypisz ustawienia konfiguracyjne do właściwości klasy
    foreach ($config as $name => $type) {
           
        if (in_array($name, $this->config)) {
            $this->config[$name] = $config[$name];
        }
           
    }
       
       
    // uruchom buforowanie plików
    $options = array(
        'caching' => $this->config['cache_enabled'],
        'cacheDir' => $this->config['cache_location']
    );

    $this->cache_lite = new Cache_Lite($options);
       
       
    // samodzielne czyszczenie buforu
    // dodaj ?flush=FILE_ID do adresu, aby usunąć cache
    if (
        $this->config['cache_enabled']
        and $this->config['use_flush_key']
        and !empty($_GET['flush'])
    ) {
        $this->flushCache($_GET['flush']);
    }
   
}

W samym już konstruktorze klasy dzieje się kilka rzeczy, m. in. przypisywane są ustawienia konfiguracyjne zdefiniowane przy wywoływaniu instancji klasy, definiowana jest możliwość wywoływania metody usuwającej dotychczasowy cache i uruchamiana jest klasa odpowiadająca za cache, wspomniany wcześniej Cache_Lite.

Skoro już wspomniałem o możliwości czyszczenia buforu to utwórzmy metodę wykonującą to zadanie:

1
2
3
private function flushCache($id_cache) {
    $this->cache_lite->remove($id_cache);
}

Wykorzystujemy tutaj wcześniej nawiązane połączenie z klasą odpowiadającą za cache i wysyłamy do niej identyfikator pliku cache, którego zamierzamy usunąć – proste.

Następnym krokiem będzie stworzenie metod pozwalających na załączanie kolejnych plików CSS:

1
2
3
public function addFile($url_file) {
    array_push($this->files_require, $url_file);
}

oraz wygodniejszej u użyciu:

1
2
3
4
5
6
7
8
public function addFiles($url_files) {
       
    // wczytaj kolejne pliki do złączenia
    foreach ($url_files as $id => $file) {
        $this->addFile( trim($file) );
    }
   
}

Tutaj nie trzeba niczego objaśniać, adresy do plików pozostawiamy po prostu we właściwości obiektu – zajmiemy się nimi potem.

Czas przejść do najciekawszej części całej klasy, czyli optymalizacji i minimalizacji kodu CSS!

1
2
3
4
5
6
7
8
9
10
11
12
public function cleanCode($code) {
   
    // wywal komentarze
    $code = preg_replace('!/*[^*]**+([^/][^*]**+)*/!', null, $code);
       
    // wywal niepotrzebne spacje i odstępy
    $code = str_replace (array("rn", "r", "n", "t", '  ', '    '), null, $code);
       
    // zwróć wyczyszczony kod
    return $code;
   
}

Tutaj nie dzieje się nic szczególnego. Ciekawiej ma się kompresja kodu:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public function compressCode($code) {
   
    // popraw zera na wersje skrócone
    $code = str_replace($this->sizes[0], ' 0', $code);
    $code = str_replace($this->sizes[1], ':0', $code);
       
    // wywal niepotrzebne spacje z reguł, skróć popularne nazwy kolorów do wartości HEX
    $code = str_ireplace(
                array_keys($this->shortcuts),
                array_values($this->shortcuts),
                $code
            );


    // Wzorce regex:
    // 1 => minimalizuj wartości HEX kolorów
    // 2 => wywal wszystkie cudzysłowy z adresów url
    // 3 => skróć wartości reguły 'font-weight' do wartości liczbowych
    $search = array(
        1 => '/([^=])#([a-fd])2([a-fd])3([a-fd])4([s;}])/i',
        2 => '/url(['"](.*?)['"])/s',
        3 => '
/(font-weight|font):([a-z- ]*)(normal|bolder|bold|lighter)/ie'
    );

    $replace = array(
        1 => '
$1#$2$3$4$5',
        2 => 'url($1)',
        3 => '"$1:$2" . $this->font_weight_to_num["$3"]'
    );

    // wykonaj podmiany
    $code = preg_replace($search, $replace, $code);
       
    // zwróć skompresowany kod
    return $code;
   
}

Wywalamy tutaj niepotrzebne spacje w regułach, zmieniamy nadmierne wartości reguł, minimalizujemy wartości kolorów HEX i kilka innych optymalizacji.

Następnym głównym krokiem będzie metoda, która łączy wcześniej napisany kod w spójną całość:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public function showCode($mode = 'infile') {

    // wyczyść bufor, jeśli pliki css były modyfikowane
    $this->checkModifiedFiles();
   
    // utwórz cache, jeśli nie istnieje
    if ( !($this->css_code = $this->cache_lite->get( $this->_getCacheName() )) ) {

        // przetwórz kod css
        $css_code = $this->getCodeCSS($this->files_require);
           
        $this->css_code .= '@charset "' . $this->config['charset'] . '";';
        $this->css_code .= $this->getImportRules();
        $this->css_code .= $css_code;
        $this->css_code .= "n// generated by CSS Minify (http://blog.kamilbrenk.pl/css-minify/)";
           
        // buforuj kod do pliku
        $this->cache_lite->save($this->css_code);
        unset($css_code);
           
    }
       
       
    switch ($mode) {
       
        // zwróć kod (return)
        case 'inline':
            return $this->css_code;
            break;
           
        // generuj kod (echo)
        case 'infile':
            $this->outputHeaders();
            break;
       
    }
   
}

Dzieje się tutaj kilka ciekawych rzeczy:

  1. sprawdzamy czy któryś z plików został zmodyfikowany; jeśli tak to odświeżamy plik cache,
  2. tworzymy plik cache, jeśli tak ustawiono w konfiguracji obiektu,
  3. generujemy kod css,
  4. w zależności od kontekstu wywołania metody – zwracamy efekt działania lub przekazujemy do metody odpowiadającej za ustawienia nagłówków i wyświetlamy bezpośrednio w oknie przeglądarki.

Ad. 1) Piszemy metody odpowiedzialne za sprawdzanie, czy któryś z załączonych plików nie był później modyfikowany aniżeli plik cache.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
private function checkModifiedFiles() {
   
    // sprawdź czy plik był edytowany (jeśli to możliwe)
    foreach ($this->files_require as $id => $url_file) {
       
        if (file_exists($url_file)) {
           
            // liczba sekund od ostatniej aktualizacji
            $life_file = filemtime($url_file);
               
            // jeśli plik był aktualizowant -> wyczyść bufor
            if ($life_file > $this->_lastModifiedCache()) {
                return $this->flushCache( $this->_getCacheName() );
            }
               
        }
       
    }
   
}

private function _lastModifiedCache() {
   
    $this->cache_lite->_setFileName($this->_getCacheName(), 'default');
    return $this->cache_lite->lastModified();
   
}

private function _getCacheName() {
    return md5( serialize($this->config) . implode($this->files_require) );
}

Ad. 3) Wcześniej załączone pliki były gromadzone w właściwości obiektu o nazwie files_require. Czas pobrać ten kod i go przetworzyć.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
private function getCodeCSS($files) {
    // zmienna przechowująca kod
    $full_code = null;
   
    // pobierz i zoptymalizuj kod z załączonych plików
    foreach ($files as $id => $url_file) {
           
        // pobierz kod źródłowy - błędy zostaną 'stłumione' i pominięte
        // zabezpiecz przed wielokrotnym pobieraniem tego samego kodu
        if (
            !in_array($url_file, $this->files_loaded)
            and $code = @file_get_contents($url_file)
        ) {
           
            // odnotuj dołączenie pliku
            array_push($this->files_loaded, $url_file);
           
            // wywal deklarację charset w dokumencie, o ile posiada
            // aby nie dublować dla każdego pliku
            $code = preg_replace('/@charset\s["\']([0-9A-Za-z-]+)["\'];?/', null, $code);
               
            // sposób implementowania reguły: http://www.w3.org/TR/CSS21/cascade.html#at-import
            $code = preg_replace_callback(
                        '/@import\s(?:url\([\'"]?([^\'"]+)[\'"]?\)|["\'](.+)[\'"])\s?([ A-Za-z0-9,]*)?;/',
                        array($this, '_import'),
                        $code
                    );
               
            // wyczyść kod
            if ($this->config['clean_code']) $code = $this->cleanCode($code);
            if ($this->config['compress_code']) $code = $this->compressCode($code);
               
            // dodaj kod do zwrócenia
            $full_code .= $code;
            unset($code);
           
        }
    }
}

Dlaczego każdy kod jest osobno pobierany, przetwarzany, a na sam koniec łączony w całość? Ano między innymi dlatego, że preg_replace, który jest niezbędny do wykorzystania ma pewne ograniczenia.

Więcej przeczytasz w komentarzach oficjalnej dokumentacji języka PHP: http://www.php.net/manual/en/function.preg-replace.php#93840.

Powyższa metoda usuwa wszystkie reguły ustalające kodowanie, ponieważ wg standardu CSS, może być tylko jedna taka reguła na początku dokumentu.

Również reguła @import jest usuwana, ponieważ może być tylko na początku dokumentu CSS. Reguła ta odpowiada za importowanie zewnętrznych plików CSS, jednak nie jest zbyt wydajna. Jeśli w ustawieniach konfiguracyjnych obiektu nakazano włączanie także importowanych plików, nastąpi to w niniejszej metodzie:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private function _import($result) {
   
    // wyciągnij nazwę importowanego pliku css
    $filename = !empty($result[1]) ? $result[1] : $result[2];
       
    // imprtowanie włączone: zwróć zawartość poprawionego pliku do złączenia
    if ($this->config['import_mode']) {
        return $this->getCodeCSS( array($filename) );
    }
       
       
    // imprtowanie wyłaczone: przechowaj dane w tablicy
    $this->files_import += array($filename => $result[3]);

}

Dodam także, że zaimplementowano zabezpieczenie przed nieskończonym wczytywaniem tych samych plików.

plik1.css

1
@import ('plik2.css')

plik2.css

1
@import ('plik1.css')

Powyższy przykład wczyta tylko jednokrotnie plik1.css oraz plik2.css, po czym zakończy działanie.

Jeśli natomiast wyłączone jest importowanie plików z tej reguły, następuje ich usunięcie ze środka dokumentu i wyświetlenie na samym początku dokumentu CSS (nakazuje tego standard).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private function getImportRules() {
   
    // zmienna przechowująca kod
    $code = null;
   
    // załącz kolejne pliki imprortowane
    foreach ($this->files_import as $filename => $type) {
        $code .= '@import url("' . $filename . '") ' . $type . ';';
    }
       
    // zwróć przetworzony kod
    return $code;
   
}

Ad. 4) Wysyłamy nagłówki do przeglądarki oraz kompresujemy css, jeśli jest taka potrzeba. W tym celu posłuży nam ostatnia już metoda:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
protected function outputHeaders() {
   
    // standardowe nagłowki
    header('Content-Type: text/css; charset=' . $this->config['charset']);
   
    // buforuj w przeglądarce
    if ($this->config['use_cache_browser']) {
        header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->_lastModifiedCache()) . ' GMT');
        header('Cache-Control: public, must-revalidate, max-age=' . $this->config['time_cache_browser']);
        header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $this->config['time_cache_browser']) . ' GMT');
    } else {
        header("Cache-Control: no-cache, must-revalidate");
        header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
    }
       
    // ustaw kompresję gzip
    if ($this->config['gzip_contents'] and extension_loaded("zlib") and !ini_get('zlib.output_compression')) {

        $this->css_code = gzencode($this->css_code, $this->config['gzip_level']);
        header('Content-Encoding: gzip');
           
    }
       
    header('Content-Length: ' . strlen($this->css_code));
    echo $this->css_code;
   
}

Dodajemy tutaj nagłówki dla pliku odpowiedzialne m. in. za buforowanie w przeglądarce (po stronie klienta) czy kodowanie znaków.

Ładujemy również kompresję gzip, jeśli tego żądano.

Na sam koniec dodajmy destruktor odwalający brudną robotę – usuwania niepotrzebnych zmiennych.

1
2
3
public function __destruct() {
    unset($this->files_code);
}
Mamy zbudowaną klasę. I co dalej?

Teraz wystarczy wywołać instancję klasy i w zależności od potrzeb rozpocząć ładowanie kolejnych plików CSS do optymalizacji:

1
2
3
4
5
6
7
8
9
10
11
12
13
require_once 'class.CSSCompressor.php';

// utwórz instancję klasy
$css_compress = new CSSCompressor();

// dodaj pliki css do złączenia
$css_compress->addFile('file1.css');
$css_compress->addFile('file2.css');
$css_compress->addFile('file3.css');

echo '<style>';
echo $css_compress->showCode('inline');
echo '</style';

Czego efektem będzie złączenie powyższych trzech plików, dokonanie ich kompresji oraz optymalizacji, dodanie do buforu przeglądarki, zapis cache w folderze tmp/, po czym zwrócenie z wykorzystaniem gzip. Tak działają domyślne ustawienia skryptu.

Skrypt, choć liniowo włączony do strony, jest zbuforowany i nie ma żadnego problemu przy kolejnych odwiedzinach strony – zamiast trzech plików jest wczytywany jeden – zoptymalizowany i często nawet kilkakrotnie mniejszy!

Bibliotekę tą możemy wykorzystać także w bardziej przydatny sposób. Oto przykład:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
require_once 'class.CSSCompressor.php';

// konfiguracja
$_config = array(

    'charset'               =>  'utf-8',    // kodowanie znaków
   
    'import_mode'           =>  true,       // włączanie wewnętrznych styli (@import)
   
    'clean_code'            =>  true,       // status czyszczenia kodu
    'compress_code'         =>  true,       // status kompresji kodu
   
    'cache_enabled'         =>  true,       // buforowanie po stronie serwera
    'cache_location'        =>  'tmp/',     // folder dla cache
   
    'use_cache_browser'     =>  true,       // buforowanie po stronie klienta
    'time_cache_browser'    =>  3600,       // czas trzymania w buforze (sekundy)
   
    'gzip_contents'         =>  true,       // kompresja gzip
    'gzip_level'            =>  6           // poziom kompresji gzip

);

// utwórz instancję klasy
$css_compress = new CSSCompressor($_config);

// dodaj pliki css do złączenia
$css_compress->addFile('file1.css');
$css_compress->addFile('file2.css');
$css_compress->addFile('file3.css');

// wersja 2
$css_compress->showCode('infile');

Tworzymy plik z powyższym kodem i zapisujemy, np. css.php.

Teraz na każdej kolejnej stronie możemy odwołać się do tego pliku w następujący sposób:

1
<link rel="stylesheet" type="text/css" href="css.php" />

Jeśli komuś przeszkadza odwoływanie się do pliku CSS bezpośrednio w elemencie link, może za pośrednictwem mod_rewrite przepisać URL na „udający” prawdziwy plik CSS.

Przykład z życia wzięty

Sam najczęściej stosuję się do następującego rozwiązania:

css.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
require_once 'class.CSSCompressor.php';

// utwórz instancję klasy
$css_compress = new CSSCompressor();

// dodaj pliki css do złączenia
if (!isset($_GET['load'])) die('Nie wczytano żadnych styli.');

// przerób na tablicę
$files = explode(',', $_GET['load']);

foreach ($files as $id => &$file) {
    $file = 'style/' . trim($file) . '.css';
}

// ustaw do kompresji
$css_compress->addFiles($files);

// wyświetl wynik
$css_compress->showCode('infile');

Po czym do plików odwołuję się w poniższy sposób:

1
<link rel="stylesheet" type="text/css" href="css.php?load=file1,file2,file3" />

lub przy pomocy mod_rewrite można upiększyć jeszcze bardziej, np. :

1
<link rel="stylesheet" type="text/css" href="css.css?load=file1,file2,file3" />
Czas na wyniki, analizę – efekty pracy!

Mam nadzieję, że powyższe przykłady prostotę i potęgę optymalizacji plików CSS. Jeśli nadal nie jesteś przekonany, spójrz na wyniki moich optymalizacji:

oryginalny rozmiar plików:
17,03 KB

domyślne ustawienia skryptu:
3,74 KB, oszczędność wynosi 78%, czyli plik zmniejszył się prawie pięciokrotnie!

maksymalna minimalizacja:

  • plik jest trzymany po stronie klienta,
  • plik jest trzymany na serwerze i ponownie generowany w przypadku aktualizacji któregoś ze arkuszy stylów,
  • zamiast odwołań do wielu plików, mamy tylko jedno zapytanie o zewnętrzny zasób; czasem ma to istotny wpływ na wczytywanie strony, o czym więcej przeczytasz we wpisie: Minimalizacja zapytań HTTP.

To by było na tyle. Zapraszam do testów i wytykania błędów.

Mam również nadzieję, że przekonałem Cię do buforowania plików CSS. W następnym wpisie zabierzemy się za JavaScript!

Przydatne linki
  • Kompresja CSS – pokaż przykład
  • Pełny kod źródłowy biblioteki + przykłady (36 KB)

Komentarze (4)

  1. Michal Wachowski 22 kwietnia 2010

    To już lekka przesada dla mnie – te konwersje itd…
    Możesz jeszcze dać zamianę color: rgb(X, Y, Z) na # :)

  2. Kamil Brenk 22 kwietnia 2010

    Możliwe, że popłynąłem trochę za bardzo – często mi się to zdarza i zamiast użytecznego i lekkiego narzędzia powstaje zasobożerny potwór ;)

  3. megawebmaster 17 września 2010

    @Kamil – wątpię, żeby to była przesada – o ile jest tylko z tego jakiś zysk to warto nawet przedłużyć czas kompresowania – odzyskamy go z nawiązką później. Kto często modyfikuje pliki CSS? :)

  4. Kamil Brenk 18 września 2010

    Przy każdej rozbudowie strony i różnych innych poprawkach aktualizuje się także pliki CSS – dodając moduł, usuwając moduł, aktualizując cokolwiek. Przynajmniej u mnie zdarza się to dość często przy stronach nad którymi na bieżąco pracuję i które rozwijam :-)

    Niemniej jednak wciąż korzystam z powyższego skryptu i sprawdza się doskonale – nie miałem jeszcze z nim żadnych problemów i niczego nie zmieniałem.



Kamil Brenk Blog

PHP, JavaScript, SQL, HTML

  • Informacje o blogu

    Kamil Brenk

    Blog o tworzeniu aplikacji na potrzeby sieci Web.

    Praktyczne przykłady, porady i sztuczki. PHP, SQL, AJAX, JavaScript, HTML i pochodne.

    Kanał RSS

    • Najnowsze
    • Komentarze
    • Popularne
    • Liczniki w CSS
    • Wyprzedaż książek o programowaniu!
    • Niestandardowy placeholder
    • JavaScript w modułach
    • Co dalej z blogiem?
    • Interaktywna mapa w HTML i CSS
    • Olsztyn: Jak wyseparować zawartość zassaną przez file_get_content?
    • ERMLAB: Od czegoś trzeba zacząć :) Wiele osób właśnie stawia na...
    • david: co nalezy wkleić na stronę aby plik ze stylami był ladowany...
    • krynicz: Nie jestem pewien czy dobrze to rozumiem: wpisujemy OG w...
    • yaro: Jak zmienić re_write znak "_" na "-"?
    • Piotr: stworzyłem prostą stronkę w PHP, czy jest możliwość aby...
    • MichalR: Super sprawa... bardzo przydatne.. dzieki i pozdrawiam..
    • Niestandardowe czcionki na stronie
    • Sposoby wczytywania JavaScript
    • Gramatyka w PHP, część 1
    • Umowa i zaliczka dla freelancera
    • Wysyłanie wiadomości SMS w PHP
    • Projekt aplikacji po stronie klienta
    • Własny mechanizm Feed
  • Szukajka
    Wpisz co chcesz wyszukać na stronie…
  • Kategorie
    • Apache
    • Freelancer
    • Front-end Development
    • HTML5 & CSS3
    • Inne
    • JavaScript
    • Książki
    • PHP
    • Po godzinach
    • Pozycjonowanie
    • Protokół HTTP
    • SQL
    • Wyrażenia regularne
  • Moje serwisy
    • Testy zawodowe
    • Miłość, uczucia i seks
  • Czytane blogi
    • Wojciech Sznapka
    • Wojciech Soczyński
    • Michał Wachowski
    • Tomasz Kowalczyk
    • Filip Górczyński
  • Strona główna
  • Curriculum Vitae
  • O mnie
  • Przykład: Gramatyka w PHP
  • Przykład: Kompresja CSS
  • Przykład: Kompresja JavaScript
  • Przykład: Skracanie linków
  • Przykład: Wykrywanie serwera HTTP
  • Przykład: Własna bramka SMS
  • Mapa strony
  • Kontakt

Kamil Brenk © 2010. All rights reserved.

Designed by FTL Wordpress Themes brought to you by Smashing Magazine.

Do góry ∧