Generowanie przychodu w witrynie HTML5

Wprowadzenie

Obecnie tworzenie aplikacji internetowych na urządzenia mobilne jest bardzo popularnym tematem. W tym roku po raz pierwszy smartfony wyprzedziły komputery PC. Coraz więcej użytkowników korzysta z urządzeń mobilnych do przeglądania internetu, co oznacza, że optymalizacja witryn pod kątem przeglądarek mobilnych staje się dla programistów kluczowa.

„Pole bitwy” mobilności to dla wielu deweloperów wciąż nieznane terytorium. Wielu użytkowników ma stare witryny, które w ogóle nie uwzględniają użytkowników mobilnych. Witryna została zaprojektowana głównie z myślą o użytkownikach przeglądających ją na komputerach, a jej jakość w przeglądarkach mobilnych jest niska. Ta strona (html5rocks.com) nie jest wyjątkiem. Na początku nie przykładaliśmy zbyt dużej uwagi do wersji mobilnej witryny.

Tworzenie strony html5rocks.com zoptymalizowanej pod kątem urządzeń mobilnych

W ramach ćwiczenia warto dodać html5rocks (dotychczasową stronę HTML5) do wersji na komórki. Najbardziej zależało mi na minimalnej ilości pracy wymaganej do kierowania reklam na telefony komórkowe. Celem tego ćwiczenia nie było tworzenie zupełnie nowej witryny mobilnej i utrzymywanie 2 kodów źródłowych. Zajmowałoby to wieczność i byłoby ogromną stratą czasu. Strukturę witryny (oznaczanie) mieliśmy już zdefiniowaną. Sprawdziliśmy to (CSS). Główna funkcjonalność (JS) była dostępna. Chodzi o to, że wiele witryn ma ten sam problem.

W tym artykule opisujemy, jak utworzyć wersję mobilną strony html5rocks zoptymalizowaną pod kątem urządzeń z Androidem i iOS. Wystarczy, że otworzysz stronę html5rocks.com na urządzeniu z jednym z tych systemów operacyjnych, aby zobaczyć różnicę. Nie ma żadnych przekierowań do witryny m.html5rocks.com ani innych podobnych witryn. Otrzymasz html5rocks w jego pierwotnej formie, z dodatkowymi zaletami, które sprawiają, że wygląda on świetnie i dobrze działa na urządzeniu mobilnym.

Komputer – html5rocks.com Komórka html5rocks.com
html5rocks.com na komputerze (po lewej) i urządzeniu mobilnym (po prawej)

Zapytania o media CSS

Standardy HTML4 i CSS2 od dawna obsługują arkusz stylów zależny od nośnika. Na przykład:

<link rel="stylesheet" media="print" href="printer.css">

kierować na urządzenia do drukowania i zapewniać określony styl dla treści strony podczas drukowania. CSS3 idzie o krok dalej w sprawie typów mediów i rozszerza ich funkcjonalność za pomocą zapytań o media. Zapytania o multimedia zwiększają użyteczność typów multimediów, umożliwiając dokładniejsze oznaczanie arkuszy stylów. Dzięki temu możesz dostosować prezentację treści do określonego zakresu urządzeń wyjściowych bez konieczności zmiany samych treści. To idealne rozwiązanie dla istniejącego układu, który wymaga modyfikacji.

W atrybucie media w zewnętrznych arkuszach stylów możesz używać zapytań dotyczących multimediów, aby dopasowywać szerokość ekranu, szerokość urządzenia, orientację itp. Pełną listę znajdziesz w specyfikacji zapytań dotyczących multimediów W3C.

Kierowanie na rozmiary ekranów

W poniższym przykładzie właściwość phone.css będzie stosowana do urządzeń uważanych przez przeglądarkę za „podręczne” lub urządzeń, których ekran ma szerokość <= 320 pikseli.

 <link rel='stylesheet'
  media='handheld, only screen and (max-device-width: 320px)' href='phone.css'>

Poprzedzanie zapytań o multimedia słowem kluczowym „only” spowoduje, że przeglądarki niezgodne z CSS3 będą ignorować tę regułę.

Na przykład:

 <link rel='stylesheet'
  media='only screen and (min-width: 641px) and (max-width: 800px)' href='ipad.css'>

Zapytania o multimedia mogą się też pojawiać we wbudowanych tagach <style>. Te typy multimediów są kierowane na all typy multimediów w orientacji pionowej:

 <style>
  @media only all and (orientation: portrait) { ... }
 </style>

media="handheld"

Musimy na chwilę przerwać i omówić media="handheld". Android i iOS ignorują media="handheld". Użytkownicy mogą stracić dostęp do wysokiej jakości treści dostarczanych przez pliki stylesheeta kierowane na media="screen", a deweloperzy mogą mieć trudności z utrzymaniem wersji media="handheld" o niższej jakości. Zgodnie ze swoim motto „pełnym dostępem do internetu” większość nowoczesnych przeglądarek w smartfonach po prostu ignoruje przenośne arkusze stylów.

Najlepiej używać tej funkcji do kierowania na urządzenia mobilne, ale różne przeglądarki implementują ją na różne sposoby:

  • Niektóre z nich odczytują arkusz stylów tylko z ręcznego.
  • Niektóre odczytują arkusz stylów tylko z ręcznego, jeśli taki istnieje, ale domyślnie używają arkusza stylów ekranu w przeciwnym razie.
  • Niektóre urządzenia odczytują zarówno arkusz stylów dla urządzeń mobilnych, jak i arkusz stylów dla ekranów.
  • Niektóre czytają tylko arkusz stylów ekranu.

Opera Mini nie ignoruje media="handheld". Aby Windows Mobile rozpoznał wartość media="handheld", należy użyć wielkich liter w wartości atrybutu media w stylu ekranu:

 <!-- media="handheld" trick for Windows Mobile -->
 <link rel="stylesheet" href="screen.css" media="Screen">
 <link rel="stylesheet" href="mobile.css" media="handheld">

Jak html5rocks korzysta z zapytań dotyczących multimediów

Zapytania o multimedia są często używane w html5rocks na urządzeniach mobilnych. Pozwoliło nam to ulepszyć układ bez konieczności wprowadzania znaczących zmian w znacznikach szablonów Django. To prawdziwy ratownik. Poza tym ich obsługa w różnych przeglądarkach jest całkiem niezła.

W sekcji <head> na każdej stronie zobaczysz następujące arkusze stylów:

 <link rel='stylesheet'
  media='all' href='/static/css/base.min.css' />
 <link rel='stylesheet'
  media='only screen and (max-width: 800px)' href='/static/css/mobile.min.css' />

base.css zawsze określał wygląd strony html5rocks.com, ale teraz stosujemy nowe style (mobile.css) dla ekranów o szerokości mniejszej niż 800 pikseli. Zapytanie dotyczące multimediów obejmuje smartfony (~320 pikseli) i iPady (~768 pikseli). Efekt: stopniowo zastępujemy style w base.css (tylko w razie potrzeby), aby poprawić wygląd na urządzeniach mobilnych.

Niektóre zmiany stylizacji, które narzuca mobile.css:

  • zmniejsza ilość pustego miejsca w witrynie, Na małych ekranach miejsce jest na wagę złota.
  • Usuwa :hover stanu. Nie będą widoczne na urządzeniach dotykowych.
  • Dostosowuje układ do pojedynczej kolumny. Więcej informacji na ten temat znajdziesz później.
  • Usuwa box-shadow wokół głównego kontenera div witryny. Duże cienie zmniejszają wydajność strony.
  • Użyto modelu flex box w CSS box-ordinal-group, aby zmienić kolejność poszczególnych sekcji na stronie głównej. Na stronie głównej sekcja „UCZ NA NAJWAŻNIEJSZYCH GRUP FUNKCJI HTML5”, a na stronie mobilnej – po sekcji „PORADY”, Takie uporządkowanie było bardziej sensowne w przypadku urządzeń mobilnych i nie wymagało zmian w znacznikach. CSS flexbox FTW!
  • Usuwanie zmian opacity. Zmiana wartości alfa wpływa na skuteczność na urządzeniach mobilnych.

Metatagi mobilne

Mobile WebKit obsługuje kilka ulepszeń zapewniających użytkownikom lepsze przeglądanie na określonych urządzeniach.

Ustawienia widocznego obszaru

Pierwszym ustawieniem meta (i tym, którego będziesz używać najczęściej) jest właściwość viewport. Ustawienie widocznego obszaru informuje przeglądarkę, jak treści powinny pasować do ekranu urządzenia, oraz informuje przeglądarkę, że witryna jest zoptymalizowana pod kątem urządzeń mobilnych. Na przykład:

 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">

informuje przeglądarkę, aby ustawiła widoczny obszar na szerokość urządzenia ze skalą początkową 1. Ten przykład umożliwia też powiększanie, co może być pożądanym efektem w przypadku witryny, ale nie aplikacji internetowej. Możemy zapobiec powiększaniu za pomocą parametru user-scalable=no lub ograniczyć skalowanie do określonego poziomu:

 <meta name=viewport
  content="width=device-width, initial-scale=1.0, minimum-scale=0.5 maximum-scale=1.0">

Android rozszerza metatag viewport, umożliwiając deweloperom określenie rozdzielczości ekranu, dla której została przygotowana witryna:

 <meta name="viewport" content="target-densitydpi=device-dpi">

Możliwe wartości dla target-densitydpi to device-dpi, high-dpi, medium-dpi i low-dpi.

Jeśli chcesz zmodyfikować stronę internetową pod kątem różnych gęstości ekranu, użyj zapytania o media CSS -webkit-device-pixel-ratio lub właściwości window.devicePixelRatio w języku JavaScript, a następnie ustaw właściwość meta target-densitydpi na wartość device-dpi. Dzięki temu Android nie będzie skalować Twojej strony internetowej i będziesz mieć możliwość wprowadzania niezbędnych korekt dla każdej gęstości za pomocą CSS i JavaScriptu.

Więcej informacji o kierowaniu na rozdzielczości urządzeń znajdziesz w dokumentacji WebView na Androida.

Przeglądanie na pełnym ekranie

Istnieją jeszcze 2 inne wartości metadanych, które są specyficzne dla iOS. apple-mobile-web-app-capable i apple-mobile-web-app-status-bar-style spowoduje renderowanie zawartości strony w trybie pełnoekranowym podobnym do aplikacji i sprawi, że pasek stanu będzie półprzezroczysty:

 <meta name="apple-mobile-web-app-capable" content="yes">
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">

Więcej informacji o wszystkich dostępnych opcjach meta znajdziesz w dokumentacji Safari.

Ikony na ekranie głównym

Urządzenia z iOS i Androidem obsługują też formaty rel="apple-touch-icon" (iOS) i rel="apple-touch-icon-precomposed" (Android) dla linków. Gdy użytkownik doda Twoją witrynę do zakładek, na ekranie głównym pojawi się ikona przypominająca ikonę aplikacji:

 <link rel="apple-touch-icon"
      href="/static/images/identity/HTML5_Badge_64.png" />
 <link rel="apple-touch-icon-precomposed"
      href="/static/images/identity/HTML5_Badge_64.png" />

Jak html5rocks używa mobilnych metatagów

Oto fragment kodu z sekcji <head> na stronie html5rocks:

 <head>
  ...
   <meta name="viewport"
        content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />

   <link rel="apple-touch-icon"
        href="/static/images/identity/HTML5_Badge_64.png" />
   <link rel="apple-touch-icon-precomposed"
        href="/static/images/identity/HTML5_Badge_64.png" />
  ...
 </head>

Układ pionowy

Na mniejszych ekranach wygodniej jest przewijać w pionie niż w poziomie. Na urządzeniach mobilnych preferowany jest pionowy układ treści, który zawiera jedną kolumnę. W przypadku html5rocks do utworzenia takiego układu użyliśmy zapytań medialnych CSS3. Ponownie bez zmiany znaczników.

Indeks samouczków. Samouczek. Strona funkcji HTML5. Strona profili autorów.
Jednokolumnowy pionowy układ w witrynie.

Optymalizacja pod kątem urządzeń mobilnych

Większość wprowadzonych przez nas optymalizacji to rzeczy, które powinny zostać zrobione na samym początku. Chodzi m.in. o zmniejszenie liczby żądań sieciowych, kompresję JS/CSS, gzip (bezpłatną w App Engine) czy zminimalizowanie manipulacji DOM. Te techniki to sprawdzone metody, które czasami są pomijane, gdy trzeba szybko wdrożyć witrynę.

Automatyczne ukrywanie paska adresu

Przeglądarki mobilne nie mają tyle miejsca na ekranie co ich odpowiedniki na komputery. Co gorsza, na różnych platformach czasem na górze ekranu pojawia się wielki pasek adresu... nawet po zakończeniu wczytywania strony.

Jednym z łatwych sposobów na rozwiązanie tego problemu jest przewijanie strony za pomocą JavaScriptu. Wystarczy przesunąć o jeden piksel, aby pozbyć się paska adresu. Aby wymusić ukrycie paska adresu w html5rocks, do obiektu window dołączyłem obiekt onload i przewinąłem stronę w pionowej o jeden piksel:

Pasek adresu.
Nieprzyzwoity pasek adresu zajmuje zawartość ekranu.
  // Hides mobile browser's address bar when page is done loading.
  window.addEventListener('load', function(e) {
    setTimeout(function() { window.scrollTo(0, 1); }, 1);
  }, false);

Zmienną szablonu is_mobile użyliśmy też w tym odbiorniku, ponieważ nie jest on potrzebny na komputerach.

Ograniczanie liczby żądań sieciowych i oszczędzanie przepustowości

Wiadomo, że zmniejszenie liczby żądań HTTP może znacznie poprawić wydajność. Urządzenia mobilne jeszcze bardziej ograniczają liczbę jednoczesnych połączeń, które może nawiązywać przeglądarka, więc witryny mobilne jeszcze bardziej skorzystają na ograniczeniu tych niepotrzebnych żądań. Poza tym liczy się każdy bajt, ponieważ na telefonach często występuje ograniczona przepustowość. Możesz narażać użytkowników na koszty.

Oto kilka metod, które zastosowaliśmy, aby zminimalizować żądania sieciowe i zredukować wykorzystanie przepustowości w przypadku html5rocks:

  • Usuń elementy iframe – są one wolne. Duża część opóźnień wynikała z użycia przez zewnętrznych dostawców widżetów do udostępniania (Buzz, Google Friend Connect, Twitter, Facebook) na stronach samouczników. Te interfejsy API zostały uwzględnione za pomocą tagów <script> i tworzą ramki iframe, które zmniejszają szybkość strony. Widżety zostały usunięte z wersji mobilnej.

  • display:none – w niektórych przypadkach ukrywałyśmy znaczniki, jeśli nie pasowały do profilu mobilnego. Dobrym przykładem są 4 zaokrąglone pola u góry strony głównej:

Przyciski Box na stronie głównej
Przyciski Box na stronie głównej

Brakuje ich na stronie mobilnej. Pamiętaj, że przeglądarka nadal wysyła żądanie dotyczące każdej ikony, mimo że kontener jest ukryty za pomocą display:none. Dlatego nie wystarczyło zwykłe ukrycie tych przycisków. Nie tylko marnowałby on przepustowość, ale użytkownik nie widziałby też żadnych korzyści z tego marnowania przepustowości. Rozwiązaniem było utworzenie wartości logicznej „is_mobile” w szablonie Django, która warunkowo pomija sekcje kodu HTML. Gdy użytkownik przegląda witrynę na urządzeniu inteligentnym, przyciski nie są wyświetlane.

  • Pamięć podręczna aplikacji – zapewnia obsługę offline i przyspiesza uruchamianie.

  • Kompresja CSS/JS – zamiast kompilatora Closure używamy kompresora YUI, głównie dlatego, że obsługuje on zarówno CSS, jak i JS. Jeden z problemów, na które się natknęliśmy, polegał na tym, że w tekście zapytania o media (zapytania o media pojawiające się w arkuszu stylów) w kompresorze YUI 2.4.2 (zobacz ten problem). Problem został rozwiązany dzięki zastosowaniu narzędzia YUI Compressor w wersji 2.4.4 lub nowszej.

  • Użycie sprite'ów CSS tam, gdzie jest to możliwe.

  • Do kompresji obrazu użyto narzędzia pngcrush.

  • Użyto identyfikatorów dataURI na potrzeby małych obrazów. Kodowanie Base64 zwiększa rozmiar obrazu o ok. 30%, ale oszczędza przesyłanie żądań do sieci.

  • Automatycznie wczytywanie niestandardowej wyszukiwarki Google za pomocą pojedynczego tagu skryptu zamiast wczytywania go dynamicznie za pomocą tagu google.load(). Ta druga metoda wysyła dodatkowe żądanie.

<script src="//www.google.com/jsapi?autoload={"modules":[{"name":"search","version":"1"}]}"> </script>
  • Nasza ładna drukarka i usługa Modernizr były widoczne na każdej stronie, nawet jeśli nigdy nie były używane. Modernizr jest świetny, ale wykonuje mnóstwo testów przy każdym wczytaniu. Niektóre z tych testów wprowadzają kosztowne modyfikacje DOM i spowolniają wczytywanie strony. Obecnie uwzględniamy te biblioteki tylko na stronach, na których są one rzeczywiście potrzebne. -2 żądania :)

Dodatkowe ulepszenia wydajności:

  • Przeniesienie wszystkich plików JS na sam dół strony (w miarę możliwości).
  • Usunięto tagi <style> w tekście.
  • Wyszukiwania DOM w pamięci podręcznej i minimalne manipulowanie DOM – za każdym razem, gdy dotykasz DOM, przeglądarka wykonuje reflow. Na urządzeniu mobilnym ponowne formatowanie jest jeszcze bardziej kosztowne.
  • Przesłano na serwer niepotrzebny kod po stronie klienta. W szczególności chodzi o ustawienie stylu nawigacji na bieżącej stronie: js var lis = document.querySelectorAll('header nav li'); var i = lis.length; while (i--) { var a = lis[i].querySelector('a'); var section = a.getAttribute("data-section"); if (new RegExp(section).test(document.location.href)) { a.className = 'current'; } }
  • Elementy o stałyej szerokości zostały zastąpione przez elementy płynne width:100% lub width:auto.

Pamięć podręczna aplikacji

Mobilna wersja html5rocks korzysta z pamięci podręcznej aplikacji, aby przyspieszyć wczytywanie i umożliwić użytkownikom czytanie treści offline.

Bardzo ważne jest, aby podczas implementacji pamięci podręcznej aplikacji nie buforować pliku manifestu (bezpośrednio w pliku manifestu lub domyślnie w szczegółowych nagłówkach pamięci podręcznej). Jeśli przeglądarka przechowuje manifest w pamięci podręcznej, debugowanie może być bardzo trudne. Systemy iOS i Android bardzo dobrze radzą sobie z przechowywaniem tego pliku w pamięci podręcznej, ale nie oferują wygodnego sposobu na wyczyszczenie pamięci podręcznej, tak jak przeglądarki na komputery.

Aby zapobiec buforowaniu w przypadku naszej witryny, najpierw ustawiliśmy App Engine tak, aby nigdy nie buforował plików manifestu:

- url: /(.*\.(appcache|manifest))
  static_files: \1
  mime_type: text/cache-manifest
  upload: (.*\.(appcache|manifest))
  expiration: "0s"

Po drugie użyliśmy interfejsu JS API, aby poinformować użytkownika o zakończeniu pobierania nowego pliku manifestu. Użytkownicy otrzymują prośbę o odświeżenie strony:

window.applicationCache.addEventListener('updateready', function(e) {
  if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
    window.applicationCache.swapCache();
    if (confirm('A new version of this site is available. Load it?')) {
      window.location.reload();
    }
  }
}, false);

Aby oszczędzać ruch sieciowy, uprość plik manifestu. Chodzi o to, aby nie wskazywać każdej strony w witrynie. Wystarczy, że podasz ważne obrazy, pliki CSS i JavaScript. Nie chcesz zmuszać przeglądarki mobilnej do pobierania dużej liczby komponentów przy każdej aktualizacji pamięci podręcznej aplikacji. Pamiętaj, że przeglądarka automatycznie umieszcza w pamięci podręcznej stronę HTML, gdy użytkownik ją odwiedza (i zawiera atrybut <html manifest="...">).