Geek #17

Co powiesz, jeśli zebraliśmy razem grono ekspertów, pracujących przy dużych serwisach dla stworzenia przewodnika wydajności?

Jeśli nie jest to jeden, z tych nudnych przewodników dla robotów, tylko coś naprawdę fajnego? Briza Bueno (Americanas.com), Davidson Fellipe (Globo.com), Giovanni Keppelen (ex-Peixe Urbano), Jaydson Gomes (Terra), Marcel Duran (Twitter), Mike Taylor (Opera), Renato Mangini (Google) and Sérgio Lopes (Caelum) połączyli siły i zebrali najlepsze możliwe referencje?

Właśnie to zrobiliśmy! Pokażemy Ci, że tworzone strony będą jeszcze szybsze.

Zeno Rocha, prowadzący projekt.

Czy wydajnie oznacza lepiej?

??

Oczywiście, że tak, przecież dobrze wiesz. Dlaczego zatem robimy ciągle powolne witryny, które prowadzą do złych odczuć użytkowników? Oto praktyczny przewodnik, stworzony przez społeczność, aby strony internetowe były szybsze. Nie traćmy czasu na pokazywanie milionów przypadków wydajności. Przejdźmy od razu do rzeczy!

HTML

Unikaj kodu wbudowanego

Istnieją trzy podstawowe sposoby na dołączanie CSS lub JavaScriptu na twojej stronie:

1) Liniowy: kod CSS jest zdefiniowany w znaczniku <style>, a kod JavaScript w atrybucie onclick dowolnego znacznika HTML.

2) Wbudowany: kod CSS jest zdefiniowany w znaczniku <style>, a kod JavaScript w znaczniku <script>.

3) Zewnętrzny: kod CSS jest ładowany ze znacznika <link>, a kod JavaScript z atrybutu src dla znacznika <script>.

Pierwsze dwie opcje, wprawdzie zmniejszają liczbę żądań HTTP, jednak zwiększają rozmiar samego dokumentu HTML. Taka sytuacja jest użyteczna, kiedy mamy niewielkie zasoby, koszt każdego kolejnego żądania jest znaczący. W tym przypadku, istotne jest przeprowadzenie testów w celu określenia ewentualnego wzrostu szybkości. Konieczne jest określenie celów twojej strony i jej użytkowników. Jeśli planujesz, że twoja strona zostanie odwiedzona tylko jeden raz i nie spodziewasz się powracających użytkowników, przykładowo przy jednorazowych akcjach promocyjnych to kod wbudowany pomaga w zmniejszeniu liczby żądań HTTP.

> Unikaj ręcznego tworzenia CSS/JS w środku dokumentu HTML (zalecana jest automatyzacja przy pomocy narzędzi).

Trzecia opcja nie tylko poprawia organizację twojego kodu, ale również umożliwia przeglądarce jego przechowywanie w cache. Takie rozwiązanie jest zalecane w większości przypadków, szczególnie przy plikach dużych rozmiarów, gdzie koszt stosowania kodu wbudowanego jest wiekszy.

> Przydatne narzędzia / Referencje.

Style na górze, skrypty na dole

Kiedy dołączany arkusze styli w znaczniku <head> pozwalamy na stopniowe generowanie strony, co sprawia wrażenie szybszego ładowania.

<!doctype html>
<html>
<head>

  <meta charset="UTF-8">
  <title>Browser Diet</title>

  <!-- CSS -->
  <link rel="stylesheet" href="style.css" media="all">

</head>

Jeśli jednak umieścimy arkusze na końcu kodu strony, całość zostanie wygenerowana bez styli, dopóki pliki CSS nie zostaną pobrane i zastosowane.

Z drugiej strony, jeśli omawiamy JavaScript, bardzo ważne jest umieszczenie skryptów na końcu strony, aby nie blokowały generowania w czasie ładowania i wykonywania.

<body>

  <p>Lorem ipsum dolor sit amet.</p>

  <!-- JS -->
  <script src="script.js"></script>

</body>
</html>

> Referencje.

Spróbuj asynchronicznie

Najlepszym wyjaśnieniem wpływu podanych atrybutów na lepszą wydajność, będzie zrozumienie tego, co dzieje się bez ich stosowania.

Geek #20
<script src="example.js"></script>

W tym przypadku, strona czeka do momentu, w którym skrypt zostanie całkowicie pobrany, przeanalizowany i wykonany, zanim przejdzie do analizowania i generowania HTML. Takie działanie powoduje dodatkowy narzut na czas ładowania strony. Przeważnie jest to zachowanie nieporządane.

<script async src="example.js"></script>

Skrypt jest pobierany asynchronicznie, a pozostała część stony jest nadal analizowana. Mamy gwarancję uruchomienia skryptu tuż po zakończeniu jego pobierania.

> Referencje

CSS

Minimalizuj swoje arkusze

Pisanie komentarzy i używanie wcięć poprawia czytelność kodu i ułatwia jego zarządzaniem.

.center {
  width: 960px;
  margin: 0 auto;
}

/* --- Struktura --- */

.intro {
  margin: 100px;
  position: relative;
}

Jednak dla przeglądarki nie ma to znaczenia. Z tego powodu pamiętaj zawsze o minimalizowaniu swoich arkuszy CSS poprzez automatyczne narzędzia.

.center{width:960px;margin:0 auto}.intro{margin:100px;position:relative}

Takie golenie rozmiaru pliku, pozwoli w rezultacie na szybsze pobieranie, analizowanie i uruchamianie strony.

Osoby, które używają pre-procesorów jak Sass, Less i Stylus, mają możliwość ustawienia minimlizowania przetworzonych stylów CSS.

> Przydatne narzędzia / Referencje

Scalanie wielu plików CSS

Kolejna dobra praktyka dla organizacji i obsługi stylów to dzielenie ich na mniejsze moduły.

Geek #9
<link rel="stylesheet" href="structure.css" media="all">
<link rel="stylesheet" href="banner.css" media="all">
<link rel="stylesheet" href="layout.css" media="all">
<link rel="stylesheet" href="component.css" media="all">
<link rel="stylesheet" href="plugin.css" media="all">

Jednak każdy z tych plików wymaga osobnego żądania HTTP (dobrze wiemy, że przeglądarki pobierają równolegle ograniczoną liczbę zasobów).

<link rel="stylesheet" href="main.css" media="all">

Połącz swoje pliki CSS. Mniejsza liczba plików, daje w rezultacie mniejszą liczbę żądań i szybsze ładowanie strony.

Chcesz najlepszych wyników? Automatyzacja tego procesu poprzez narzędzia budowania.

> Przydatne narzędzia / Referencje

Preferuj <link> zamiast @import

Istnieją dwa sposoby na dołączenie zewnętrznych arkuszy stylów do twojej strony: poprzez znacznik <link>:

<link rel="stylesheet" href="style.css">

lub poprzez dyrektywę @import (wewnątrz pliku ze stylami lub w środku znacznika <style>):

@import url('style.css');

Druga opcja, w przypadku stylów zewnętrznych blokuje w przeglądarce pobieranie równoległe, co dalej ogranicza pobieranie kolejnych zasobów.

> Referencje

JavaScript

Załaduj zewnętrzny kod asynchronicznie

Kto nie używał zewnętrznego kodu do osadzenia wideo z YouTube lub przycisku Like/Tweet?

Geek #46

Kod zewnętrzny nie zawsze jest sprawnie dostarczany, czasami przez połączenie użytkownika z internetem, innym ze względu na serwer gdzie jest umieszczony, co często stanowi duży problem. Zdarza się, że usługa bywa nawet tymczasowo niedostępna lub zablokowana przez firewall.

Uniknięcie takiej sytuacji jest ważne, ponieważ krytyczne żądanie spowalnia ładowanie strony, a czasami nawet całkowicie je przerywa. Istotne jest ładowanie takiego kodu asynchronicznie lub poprzez przyjazdne ramki.

var script = document.createElement('script'),
    scripts = document.getElementsByTagName('script')[0];
script.async = true;
script.src = url;
scripts.parentNode.insertBefore(script, scripts);

Ewentualnie, jeśli chcesz załadować kilka niezależnych wtyczek, możesz asynchronicznie załadować je z pomocą tego skryptu.

> Wideo / Referencje

Buforuj rozmiar tablicy

Pętla jest bez wątpienia jednym z najważniejszych elementów związanych z wydajności JavaScript. Optymalizacja logiki wewnątrz pętli jest ważna, ponieważ każda z operacji jest wykonywana wielokrotnie.

Jednym ze sposobów na to jest zapisanie rozmiaru tablicy, która będzie przetwarzana, z tego powodu nie będzie konieczne jego obliczanie przy każdej iteracji.

var arr = new Array(1000);

for (var i = 0; i < arr.length; i++) {
  // źle - rozmiar jest obliczany 1000 razy
}

for (var i = 0, len = arr.length; i < len; i++) {
  // dobrze - rozmiar jest obliczny 1 raz i dalej przechowywany
}

> Wyniki w JSPerf

> Uwaga: Chociaż silniki nowoczesnych przeglądarek automatycznie optymalizują ten proces, pamiętaj o dobrych praktykach programistycznych w starszych przeglądarkach.

Przetwarzanie kolekcji w HTML jako listy węzłów (NodeList) generowanej przykładowo przez document.getElementsByTagName('a') jest krytyczne. Takie kolekcje są traktowane "dynamicznie", co oznacza automatyczne aktualizowanie w przypadku zmian w elemencie nadrzędnym.

var links = document.getElementsByTagName('a');

for (var i = 0; i < links.length; i++) {
  // źle - każda iteracja pętli wymaga przeliczenia listy, czy nie nastąpiła zmiana
}

for (var i = 0, len = links.length; i < len; i++) {
  // dobrze - rozmiar listy jest uzyskany i przechowywany, później porównywany w kolejnych iteracjach
}

// Straszne: przykład pętli nieskończonej
for (var i = 0; i < links.length; i++) {
  document.body.appendChild(document.createElement('a'));
  // każda iteracji pętli zwiększa liczbę elementów, warunek końca pętli nie zostanie nigdy osiągnięty
  // Byłoby inaczej, gdyby rozmiar listy był przechowywany i używany jako warunek pętli
}

> Referencje

Unikaj document.write

Używanie document.write powoduje, że strona jest zależna, a w konsekwencji ponownie ładowana.

Ta (zła) praktyka była zabroniona przez lata, choć dalej istnieją przypadki, kiedy jest wymagana, jak w synchronicznej obsłudze niektorych plików JavaScript.

Przykładowo, HTML5 Boilerplate używa tej techniki do ładowania jQuery lokalnie, jeśli CDN Google nie odpowiada.

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.9.0.min.js"><\/script>')</script>

> Uwaga: document.write jest wykonywane w trakcie lub po zdarzeniu window.onload i zastępuje całą zawartość bieżącej strony.

<span>foo</span>
<script>
  window.onload = function() {
    document.write('<span>bar</span>');
  };
</script>

Wynikiem ostatecznej strony będzie bar, a nie foobar, jakbyśmy oczekiwali. To samo dzieje się przy wywołaniu po zdarzeniu window.onload.

<span>foo</span>
<script>
  setTimeout(function() {
    document.write('<span>bar</span>');
  }, 1000);
  window.onload = function() {
    // ...
  };
</script>

Wynik będzie taki sam, jak w poprzednim przykładzie, jeśli funkcja zaplanowana przez setTimeout zostanie wykonana po zdarzeniu window.onload.

> Demo / Referencje

Ograniczaj ponowne malowanie i rysowanie elementów

Ponowne malowanie i rysowanie elementów powstaje w momencie generowania drzewa DOM po zmianie właściwości elementu lub samego elementu.

Ponowne malowanie jest wyzwalane, gdy zmienia się wygląd elementu, ale nie jego układ. Nicole Sullivan opisuje to jako zmianę stylów, na przykład atrybutu background-color.

Ponowne rysowanie jest najbardziej kosztowne, ponieważ jest spowodowane przez zmianę układu strony, na przykład zmianę szerokości elementu.

Nie ma wątpliwości, że zarówno ponowne malowanie i rysowanie elementów powinny być unikane, więc zamiast w ten sposób:

Geek #55
var div = document.getElementById("to-measure"),
    lis = document.getElementsByTagName('li'),
    i, len;

for (i = 0, len = lis.length; i < len; i++) {
  lis[i].style.width = div.offsetWidth + 'px';
}

Zróbmy to tak:

var div = document.getElementById("to-measure"),
    lis = document.getElementsByTagName('li'),
    widthToSet = div.offsetWidth,
    i, len;

for (i = 0, len = lis.length; i < len; i++) {
  lis[i].style.width = widthToSet + 'px';
}

Po ustawieniu style.width, przeglądarka ponownie oblicza układ. Przeważnie, zmiany stylów dla wielu elementów powodują pojedyncze rysowanie, dopóki przeglądarka nie musi myśleć, o tym, że aktualizuje ekran. Jednakże, w pierwszym przykładzie potrzebujemy wartości offsetWidth, która jest szerokością elementu, więc przeglądarka potrzebuje przeliczenia układu.

Jeśli potrzebujesz informacji o układzie, pobierz wszystko zanim cokolwiek zmienisz, tak jak w przykładzie drugim.

> Demo / Referencje

Unikaj niepotrzebnych manipulacji DOM

Za każdym razem, gdy niepotrzebnie odwołujesz się do drzewa DOM, umiera Panda.

Poważnie, przeglądanie elementów DOM jest kosztowne. Silniki JavaScriptu są coraz wydajniejsze i szybsze, ale zawsze lepsze jest ograniczenie odwołań do drzewa DOM.

Jednym z najprostszych sposobów optymalizacji jest przechowywanie często używanych elementów DOM. Na przykład, zamiast odpytywania DOM w każdej iteracji pętli, pytamy raz i przechowujemy wynik w zmiennej, dostępnej dla każdej iteracji.

// bardzo źle!
for (var i = 0; i < 100; i++) {
  document.getElementById("myList").innerHTML += "<span>" + i + "</span>";
}
// nieco lepiej :)
var myList = "";

for (var i = 0; i < 100; i++) {
  myList += "<span>" + i + "</span>";
}

document.getElementById("myList").innerHTML = myList;
// dużo, *dużo* better :)
var myListHTML = document.getElementById("myList").innerHTML;

for (var i = 0; i < 100; i++) {
  myListHTML += "<span>" + i + "</span>";
}

> Wuniki w JSPerf

Minimalizuj kod JS

Podobnie jak w przypadku CSS, zarządzanie czytelnym kodem jest łatwiejsze, gdy w znajują się w nim komentarze i wcięcia:

BrowserDiet.app = function() {

  var foo = true;

  return {
    bar: function() {
      // do something
    }
  };

};

Jednak dla przeglądarki jest całkowicie bez znaczenia. Z tego ważne jest minimalizowanie kodu JavaScript przy pomocy automatycznych narzędzi.

BrowserDiet.app=function(){var a=!0;return{bar:function(){}}}

Takie golenie rozmiaru pliku, pozwoli w rezultacie na szybsze pobieranie, analizowanie i uruchamianie strony.

> Przydatne narzędzia / Referencje

Scalanie wielu plików JS w jeden

Bardzo dobrym rozwiązaniem dla organizacji i obsługi skryptów jest rozdzielenie ich na osobne moduły.

Geek #47
<script src="navbar.js"></script>
<script src="component.js"></script>
<script src="page.js"></script>
<script src="framework.js"></script>
<script src="plugin.js"></script>

Jednak każdy z tych plików wymaga osobnego żądania HTTP (dobrze wiemy, że przeglądarki pobierają równolegle ograniczoną liczbę zasobów).

<script src="main.js"></script>

Połącz swoje pliki JS. Mniejsza liczba plików, daje w rezultacie mniejszą liczbę żądań i szybsze ładowanie strony.

Chcesz najlepszych wyników? Automatyzacja tego procesu poprzez narzędzia budowania.

> Przydatne narzędzia / Referencje

jQuery

Zawsze korzystaj z najnowszej wersji jQuery

Główny zespół jQuery zawsze stara się wnieść poprawki do biblioteki, dzięki lepszej czytelności kodu, nowym funkcjonalnościom i optymalizacji istniejących algorytmów.

Geek #36

Z tego powodu, zawsze używaj najnowszej wersji jQuery, która jest dostępna tutaj, jeśli chcesz skopiować skrypt lokalnie:

http://code.jquery.com/jquery-latest.js

Jednak nigdy nie używaj tego adresu w znaczniku <script>, ponieważ spowoduje to problemy w przyszłości, kiedy twoja strona automatycznie pobierze aktualne wydanie biblioteki i nie będzie szansy na jej wcześniejsze przetestowanie. Zamiast tego określ dokładnie, której wersji jQuery potrzebujesz.

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

Tak jak mądry Barney Stinson mówi, "Nowe jest zawsze lepsze" :P

> Referencje

Selektory

Selektory stanowią jeden z najpoważniejszych problemów przy korzystaniu z jQuery. Istnieje wiele różnych sposobów wyboru elementu z DOM, ale nie wszystkie mają taką samą wydajność, kiedy szukasz według klasy, identyfikatora lub moetod typu find(), czy children().

Spośród wszystkich dostępnych, wybieranie poprzez ID jest najszybsze, ponieważ opiera się o natywne operacje w DOM:

$("#foo");

> Wyniki w JSPerf

Korzystaj z `for` zamiast `each`

Korzystanie z natywnych funkcji JavaScript prawie zawsze jest szybsze niż te wykonywanw w jQuery. Z tego powodu, zamiast metody jQuery.each używaj pętli for w JavaScript.

Zwróć jednak uwagę, pomimo, że instrukcja for in jest natywna to w wielu przypadkach wydajnościowo wypada gorzej niż jQuery.each.

Wypróbowana i sprawdzona pętla for daje nam kolejną możliwość przyspieszenia poprzez buforowanie długości przetwarzanej kolekcji.

for ( var i = 0, len = a.length; i < len; i++ ) {
    e = a[i];
}

Używanie odwrotnych pętli while i for stanowi gorący temat w środowisku programistycznym jako najszybsze sposoby iterowania elementów. Niestety są unikane, ze względu na mniejszą czytelność.

// odwrotna petla while
while ( i-- ) {
  // ...
}

// odwrotna petla for
for ( var i = array.length; i--; ) {
  // ...
}

> Wyniki w JSPerf / Referencje

Nie zawsze korzystaj z jQuery...

Czasami czysty JavaScript może być jeszcze prostszy niż jQuery.

Geek #6

Rozważmy następujący kod HTML:

<div id="text">Zmieńmy treść tego tekstu</div>

Zamiast robić to w taki sposób:

$('#text').html('Treść zmieniła się').css({
  backgroundColor: 'red',
  color: 'yellow'
});

Użyj samego JavaScriptu:

var text = document.getElementById('text');
text.innerHTML = 'Treść zmieniła się';
text.style.backgroundColor = 'red';
text.style.color = 'yellow';

Tak jest prościej i o wiele szybciej.

> Wyniki w JSPerf / Referencje

Obrazy

Korzystaj ze sprite'ów CSS

Technika ta polega na grupowaniu różnych obrazów w jednym pliku.

CSS Sprite Example

A następnie umieszczaniu ich w CSS.

.icon-foo {
  background-image: url('mySprite.png');
  background-position: -10px -10px;
}

.icon-bar {
  background-image: url('mySprite.png');
  background-position: -5px -5px;
}

W rezultacie, znacznie zmniejszamy liczbę żądań HTTP i unikamy potencjalnych opóźnień dla innych zasobów naszej strony.

Kiedy używamy ikonek, unikamy pozostawiania zbyt dużej pustej przestrzeni miedzy obrazami. Nie ma to wpływu na rozmiar pliku, ale ma wpływ na zużycie pamięci.

Pomimo szerokiej wiedzy na temat sprite'ów, technika ta nie jest często stosowana—może, ze względu na brak stosowania narzędzi do automatycznego generowania sprite'ów. Poniżej przedstawiamy listę narzędzi, które okażą się bardzo pomocne.

*> Przydatne narzędzia / Referencje

Data URI

Opisana technika jest alternatywą dla używania 'CSS sprites'.

Technika Data-URI jest sposobem na wstawienie danych z określonego adresu. W tym przypadku używamy jej do wstawienia treści jako tła obrazka dla właściwości CSS w celu ograniczenia liczby żądań HTTP potrzebnych do załadowania strony.

Przed:

.icon-foo {
  background-image: url('foo.png');
}

Po:

.icon-foo {
  background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII%3D');
}

Wszystkie przeglądarki od IE8 i nowsze wspierają technikę kodowania base64.

Zarówno metoda kodowania base64, jak i CSS sprites wymagają odpowiednich narzędzi do zarządania. Zaletą tej metody jest brak ręcznego pozycjonowania obrazów, które dalej są trzymane w osobnych plikach w czasie rozwoju projektu.

Wadą tego rozwiązania jest rosnący rozmiar HTML/CSS, jeśli mamy duże obrazy. Technika ta nie jest zalecana, jeżeli wynikowy kod HTML/CSS nie jest kompresowany, ponieważ wiele większy rozmiar plików i dłuższy czas pobierania będzie nieadekwatny do zysków ze zmniejszenia liczby żądań HTTP.

> Przydatne narzędzia / Referencje

Nie skaluj obrazów w znacznikach

Zawsze określaj rozmiary obrazów poprzez atrybuty width i height. Pomoże to w uniknięciu niepotrzebnego przesuwania elementów podczas generowania strony.

<img width="100" height="100" src="logo.jpg" alt="Logo">

Wiedząc, o tym programista Jan K. ma obraz 700x700px i decyduje się na jego wyświetlenie w postaci obrazu 50x50px.

Co, czy pan programista nie zdaje sobie sprawy, że dziesiątki niepotrzebnych kilobajtów zostaną przesłane przez sieć.

Zawsze miej na uwadze. Możliwość określenia szerokości i wysokości obrazu w HTML nie oznacza, że powienieneś to robić, aby zmniejszyć duże obrazy.

> Referencje

Optymalizuj swoje obrazy

Pliki obrazów zawierają wiele informacji, ktore są bezużyteczne w sieci. Przykładowe zdjęcie JPEG zawiera metadane Exif z aparatu (jak data, model aparatu, miejsce, itp.). Plik PNG zawiera informacje o kolorach, metadanych, a czasami nawet osadzoną miniaturę. Nic z tego nie jest używane przez przeglądarkę, a tylko przyczynia się do zwiększenia rozmiaru pliku.

Istnieją narzędzia do optymalizacji obrazów, które usuwają te niepotrzebne dane i zmiejszają rozmiar plików bez utraty jakości. Mówimy wtedy o kompresji bezstratnej.

Inny sposób optymalizacji obrazów to kompresja kosztem pogorszenia jakości obrazu. Nazywamy to kompresją stratną. Podczas eksportowania obrazów JPEG, przykładowo wybieramy jakość (liczba między 0 a 100). Myśląc o wydajności, zawsze wybieramy najniższą liczbę z możliwych, gdzie jakość jest do zaakceptowania. Inna powszechna technika stratna to zmniejszenie palety kolorów w formacie PNG lub konwersji plików PNG-24 do formatu PNG-8.

Aby zwiększyć wydaność postrzeganą przez użytkownika należy przekształcić wszystkie pliki JPEG do wersji progresywnych. Progresywne pliki JPEG mają dobrą obsługę w przeglądarkach, są bardzo proste do tworzenia i nie mają znaczącego spadku wydajności. Plusem jest to, że obraz pojawi się wcześniej na stronie (zobacz prezentację).

> Przydatne narzędzia / Referencje

Bonus

Narzędzia diagnostyczne: twój najlepszy przyjaciel

Geek #43

Jeśli chcesz dołączyć do świata wydajności internetowej, kluczowe będzie zainstalowanie wtyczek YSlow w twojej przeglądarce—od teraz będą twoimi najlepszymi przyjaciółmi.

Albo, jeśli wolisz narzędzia online, odwiedź strony WebPageTest, HTTP Archive lub PageSpeed.

W zasadzie każde z nich po analizie wydajności twojej strony stworzy raport, który połączony z bezcennymi radami pomoże w rozwiązaniu ewentualnych problemów.

To wszystko na dziś!

Geek #31

Mamy nadzieję, że po przeczytaniu tego poradnika Twoja strona będzie lepsza. :)

Pamiętaj, jak ze wszystkim w życiu, nie ma czegoś takiego jak srebrna kula. Kwestia wydajności twojej aplikacji jest opłacalna, ale nie powinna być jedynym kierunkiem rozwoju—poprostu oceniasz czy spodziewane korzyści są warte zachodu.

Chcesz dowiedzieć się więcej? Sprawdź odnośniki wykorzystane przy pisaniu tego przewodnika.

Jakieś sugestie? Wyślij tweeta do @zenorocha lub wywołaj żądanie na Githubie.

Nie zapomnij podzielić się z przyjaciółmi, uczyńmy internet szybszym dla wszystkich. \o/