Generowanie przychodu w witrynie HTML5

Wprowadzenie

Tworzenie oprogramowania pod kątem internetu mobilnego to obecnie bardzo gorący temat. W tym roku po raz pierwszy smartfony sprzedają się w telefonach. Coraz więcej użytkowników korzysta z urządzeń mobilnych do przeglądania internetu, dlatego tak ważne jest dla deweloperów optymalizowanie stron pod kątem przeglądarek mobilnych.

Dla wielu deweloperów to wciąż niezbadane pole bitwy. Wiele osób ma starsze witryny, które całkowicie zaniedbują użytkowników urządzeń mobilnych. Witryna została zaprojektowana głównie z myślą o przeglądaniu na komputerach i słabo działa w przeglądarkach mobilnych. Ta witryna (html5rocks.com) nie jest wyjątkiem. Niewiele pracy wkładaliśmy na początku w mobilną wersję witryny.

Tworzenie witryny html5rocks.com dostosowanej do komórek

Pomyślałem, że ciekawe będzie dodanie html5rocks (dotychczasowej witryny HTML5) do jej wersji dostosowanej do komórek. Martwiłam się głównie o minimalną ilość pracy, jaką trzeba w ten sposób skierować na smartfony. Celem mojego ćwiczenia nie było stworzenie zupełnie nowej witryny mobilnej i utrzymanie dwóch baz kodu. Cały proces trwałby całe życie i byłby stratą czasu. Zdefiniowaliśmy już strukturę witryny (znaczniki). Wzięliśmy sobie do serca odpowiedni wygląd i styl (CSS). Głównym elementem funkcji (JS) jest właśnie ta funkcja. W jednej łodzi jest wiele miejsc.

W tym artykule pokazujemy, jak opracowaliśmy mobilną wersję HTML5rock zoptymalizowaną pod kątem urządzeń z Androidem i iOS. Aby zobaczyć różnicę, wczytaj stronę html5rocks.com na urządzeniu obsługującym jeden z tych systemów operacyjnych. Nie ma żadnych przekierowań do witryny m.html5rocks.com ani do innej witryny tego typu. Otrzymujesz HTML5rocka w niezmienionej postaci... plus coś, co wygląda świetnie i działa dobrze na urządzeniach mobilnych.

html5rocks.com na komputery Mobilna html5rocks.com
html5rocks.com na komputerze (po lewej) i na urządzeniu mobilnym (po prawej)

Zapytania o media CSS

W HTML4 i CSS2 od jakiegoś czasu obsługiwane są arkusze stylów zależnych od multimediów. Na przykład:

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

będzie kierować reklamy na urządzenia drukowania i zapewniać określony styl treści strony na stronie. CSS3 rozszerza możliwości typów mediów o krok dalej i zwiększa ich funkcjonalność za pomocą zapytań o media. Zapytania o multimedia zwiększają przydatność typów mediów, umożliwiając bardziej precyzyjne oznaczanie arkuszy stylów etykietami. Dzięki temu można dostosować prezentację treści do określonej gamy urządzeń wyjściowych bez konieczności zmiany treści. To idealny wybór w przypadku już istniejących układów, które trzeba zmodyfikować.

Możesz używać zapytań o media w atrybucie media zewnętrznych arkuszy stylów, aby kierować reklamy na szerokość ekranu, szerokość urządzenia, orientację itd. Pełną listę znajdziesz w specyfikacji zapytań o media W3C.

Kierowanie na rozmiary ekranu

W poniższym przykładzie reguła phone.css będzie miała zastosowanie do urządzeń, które przeglądarka uważa za urządzenia przenośne lub urządzeń o szerokości mniejszej niż 320 pikseli.

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

Podanie zapytania o multimedia słowem kluczowym „only” spowoduje, że przeglądarki niezgodne z CSS3 zignorują regułę.

Tak wygląda kierowanie na rozmiary ekranów od 641 do 800 pikseli:

 <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>. W orientacji pionowej kierujemy te typy multimediów na all:

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

media="handheld"

Musimy zatrzymać się na chwilę i porozmawiać o media="handheld". Android i iOS ignorują media="handheld". Stwierdzono, że użytkownicy nie zobaczą wysokiej jakości treści dostarczanych przez arkusze stylów kierowane na język media="screen", a deweloperzy będą mniej skłonni do utrzymywania niższej jakości wersji media="handheld". Zgodnie z mottem „pełnego internetu” większość nowoczesnych przeglądarek na smartfonach po prostu ignoruje przenośne arkusze stylów.

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

  • Niektórzy odczytują tylko arkusz stylów na urządzeniu mobilnym.
  • Niektórzy odczytują tylko arkusz stylów w ręku, jeśli taki istnieje. W przeciwnym razie domyślnie korzystają z arkusza stylów ekranu.
  • Niektórzy odczytują zarówno arkusz stylów w ręku, jak i arkusz stylów ekranu.
  • Niektórzy odczytują tylko arkusz stylów ekranu.

Opera Mini nie ignoruje urządzenia media="handheld". Aby system Windows Mobile rozpoznał atrybut media="handheld", należy zapisać wartość atrybutu media w arkuszu stylów ekranu wielką literą:

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

Jak html5rocks używa zapytań o media

Zapytania o media są intensywnie używane w mobilnych witrynach HTML5rockowych. Dzięki nim mogliśmy dostosować układ bez wprowadzania istotnych zmian w znacznikach szablonu Django, co okazało się prawdziwym ratunkiem. Poza tym obsługują różne przeglądarki na wysokim poziomie.

W <head> każdej strony zobaczysz te 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ł główny wygląd i styl strony HTML5rocks.com, ale teraz używamy nowych stylów (mobile.css) do ekranów o szerokości poniżej 800 pikseli. Zapytanie o media obejmuje smartfony (ok. 320 pikseli) i iPady (ok. 768 pikseli). Efekt: stopniowo zastępujemy style w base.css (tylko w razie potrzeby), aby poprawić wygląd na urządzeniach mobilnych.

Oto niektóre zmiany stylu, których mobile.css wymusza:

  • Redukuje dodatkowe odstępy/dopełnienie w witrynie. Małe ekrany oznaczają, że miejsce na dane jest na wagę złota.
  • Usuwa :hover stany. Nigdy nie pojawią się na urządzeniach dotykowych.
  • Zmienia układ, by był jednokolumnowy. Więcej na ten temat później.
  • Usuwa element box-shadow wokół głównego elementu div kontenera witryny. Cienie dużych pól zmniejszają wydajność strony.
  • Do zmiany kolejności poszczególnych sekcji na stronie głównej użyto modelu box-ordinal-group Flex box. Komunikat „LEARN BY GŁÓWNE GRUPY FUNKCJI HTML5” jest widoczny przed sekcją „SAMOUCZKI” na stronie głównej, a w wersji mobilnej – po niej. To zamówienie było bardziej odpowiednie w przypadku urządzeń mobilnych i nie wymagało zmian w znacznikach. FTW! CSS flexbox
  • Usuwa opacity zmian. Zmiana wartości alfa to działanie związane ze skutecznością na urządzeniach mobilnych.

Metatagi na urządzenia mobilne

Mobile WebKit obsługuje kilka gadżetów, które zapewniają użytkownikom lepsze wrażenia podczas przeglądania stron na niektórych urządzeniach.

Ustawienia widocznego obszaru

Pierwszym ustawieniem meta (i tym, którego będziesz najczęściej używać) jest właściwość widocznego obszaru. Wskazuje on przeglądarce, w jaki sposób treść powinna mieścić się na ekranie urządzenia, a przeglądarka informuje, że strona 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ę, że ma on ustawić widoczny obszar na szerokość urządzenia ze skalę początkową 1. Ten przykład umożliwia też powiększanie, co może być pożądane w przypadku strony internetowej, ale nie aplikacji internetowej. Moglibyśmy uniemożliwić powiększanie za pomocą 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 widocznego obszaru, umożliwiając programistom określenie rozdzielczości ekranu, dla której przeznaczona jest witryna:

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

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

Jeśli chcesz dostosować swoją stronę internetową do różnych gęstości ekranu, użyj zapytania o media -webkit-device-pixel-ratio w CSS lub właściwości window.devicePixelRatio w JavaScripcie, a potem ustaw wartość meta właściwości target-densitydpi na device-dpi. Uniemożliwia to Androidowi skalowanie na stronie internetowej i umożliwia wprowadzanie niezbędnych dostosowań do poszczególnych gęstości za pomocą CSS i JavaScript.

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

Przeglądanie na pełnym ekranie

Są jeszcze dwie inne metawartości: iOS-sfic. apple-mobile-web-app-capable i apple-mobile-web-app-status-bar-style renderują zawartość strony w trybie pełnoekranowym (jak w przypadku aplikacji), a pasek stanu jest 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 metaopcjach znajdziesz w dokumentacji referencyjnej Safari.

Ikony na ekranie głównym

Urządzenia z iOS i Androidem także akceptują zasady rel="apple-touch-icon" (iOS) i rel="apple-touch-icon-precomposed" (Android). Tworzą one pulsującą ikonę przypominającą aplikację na ekranie głównym, gdy użytkownik doda Twoją witrynę do zakładek:

 <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 metatagów mobilnych

Po zebraniu wszystkiego, oto fragment z sekcji <head> witryny 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 o wiele wygodniejsze jest przewijanie w pionie niż w poziomie. W przypadku urządzeń mobilnych preferowany jest układ pionowy, gdzie treść znajduje się w jednej kolumnie. Do utworzenia takiego układu w przypadku HTML5rocks użyliśmy zapytań o media CSS3. I znów bez zmiany znaczników.

Indeks samouczków. Samouczek. Strona funkcji HTML5. na stronie profili autorów.
Jednokolumnowy pionowy układ całej witryny.

Optymalizacje pod kątem urządzeń mobilnych

Większość wprowadzonych przez nas optymalizacji to rzeczy, które należałoby wykonać na samym początku. Można w nich między innymi zmniejszyć liczbę żądań sieciowych, kompresję JS/CSS, gzipping (dostępne bezpłatnie w App Engine) oraz zminimalizować manipulacje DOM. Te techniki to typowe sprawdzone metody, ale czasami jest pomijane, gdy przyspieszasz działanie witryny.

Automatycznie ukrywaj pasek adresu

Przeglądarki mobilne nie mają wystarczająco dużo miejsca na ekranie niż ich komputery stacjonarne. Co najgorsze, na różnych platformach czasami u góry ekranu wyświetla się rozbudowany pasek adresu... nawet po zakończeniu wczytywania strony.

Łatwym sposobem na radzenie sobie z tym problemem jest przewijanie strony za pomocą JavaScriptu. Nawet jeśli zrobisz to o jeden piksel, pasek adresu nie będzie męczący. Aby wymusić ukrycie paska adresu w HTML5rocks, do obiektu window dołączono moduł obsługi zdarzeń onload i przewinąłem stronę w pionie o jeden piksel:

Pasek adresu.
Zły pasek adresu zajmuje miejsce na ekranie.
  // Hides mobile browser's address bar when page is done loading.
  window.addEventListener('load', function(e) {
    setTimeout(function() { window.scrollTo(0, 1); }, 1);
  }, false);

Ten odbiornik jest też naszą zmienną szablonu is_mobile, ponieważ nie jest potrzebny na komputerach.

Zmniejsz liczbę żądań sieciowych, oszczędzaj przepustowość

Jak powszechnie wiadomo, zmniejszenie liczby żądań HTTP może znacznie poprawić wydajność. Urządzenia mobilne jeszcze bardziej ograniczają liczbę jednoczesnych połączeń, które może nawiązać przeglądarka, więc witryny mobilne będą miały jeszcze większe korzyści z ograniczania liczby takich niepotrzebnych żądań. Ponadto usuwanie każdego bajta jest kluczowe, ponieważ przepustowość sieci na telefonach jest często ograniczona. Może to powodować naliczanie opłat przez użytkowników.

Poniżej przedstawiamy niektóre rozwiązania, które podjęliśmy, aby zminimalizować liczbę żądań sieciowych i zmniejszyć przepustowość w HTML5rocks:

  • Usuń elementy iframe - elementy iframe działają wolno. Znaczna część opóźnień występowała w widżetach udostępnianych przez inne firmy (Buzz, Sieć znajomych Google, Twitter, Facebook) na stronach samouczka. Te interfejsy API zostały umieszczone za pomocą tagów <script> i utworzyły elementy iframe, które zmniejszają szybkość działania strony. Usunęliśmy widżety na urządzenia mobilne.

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

Przyciski Box na stronie głównej.
Przyciski w polu skrzynki na stronie głównej.

Nie ma ich na stronie mobilnej Pamiętaj, że przeglądarka nadal wysyła żądanie do każdej ikony, mimo że ich kontener jest ukryty za pomocą funkcji display:none. Nie wystarczyło więc ukryć tych przycisków. W takim przypadku nie tylko nadmiernie byłoby to zużywać, ale też nie dostrzegłby on korzyści, jakie wiążą się z wykorzystaniem tej przepustowości. Rozwiązaniem było utworzenie w szablonie Django wartości logicznej „is_mobile” w celu warunkowego pomijania sekcji kodu HTML. Gdy użytkownik przegląda stronę na urządzeniu, przyciski są niewidoczne.

  • Pamięć podręczna aplikacji – umożliwia nie tylko obsługę offline, ale także przyspiesza uruchamianie aplikacji.

  • Kompresja CSS/JS – zamiast kompresora Closure używamy kompresora YUI, głównie dlatego, że obsługuje on zarówno CSS, jak i JS. Napotkaliśmy jeden problem, który polegał na tym, że wbudowane zapytania o media (zapytania o media, które pojawiają się w arkuszu stylów) zostały zablokowane w kompresorze YUI w wersji 2.4.2 (zobacz ten problem). Użycie programu YUIPressor w wersji 2.4.4+ rozwiązało problem.

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

  • Do kompresji obrazów użyto programu pngcrush.

  • Zastosowano identyfikatory dataURI na potrzeby małych obrazów. Kodowanie Base64 zwiększa rozmiar obrazu o ponad 30%, ale powoduje zapisanie żądania sieciowego.

  • Automatycznie ładuj Twoją wyszukiwarkę niestandardową Google za pomocą jednego tagu skryptu, zamiast dynamicznie wczytywać ją za pomocą google.load(). Ten drugi wysyła do niego dodatkowe żądanie.

<script src="//www.google.com/jsapi?autoload={"modules":[{"name":"search","version":"1"}]}"> </script>
  • Nasza drukarka kodu i usługa Modernizr były widoczne na każdej stronie, nawet jeśli nigdy nie były używane. Modernizr to świetne rozwiązanie, ale wykonuje testy przy każdym obciążeniu. Niektóre z tych testów wprowadzają kosztowne zmiany w DOM i spowalniają wczytywanie stron. Teraz włączamy te biblioteki tylko na stronach, na których rzeczywiście są potrzebne. -2 prośby :)

Dodatkowe poprawki w zakresie wydajności:

  • Jeśli to możliwe, przenieśliśmy cały JS na dół strony.
  • Usunięto wbudowane tagi <style>.
  • Wyszukiwania DOM w pamięci podręcznej i zminimalizowane manipulacje DOM – przy każdym dotknięciu DOM przeglądarka przeformatuje. Przeformatowanie jest jeszcze droższe na urządzeniu mobilnym.
  • Przesłać niepotrzebny kod po stronie klienta na serwer. W szczególności opcja ta określa styl nawigacji bieżącej strony: 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łej szerokości zostały zastąpione elastyczną wartością width:100% lub width:auto.

Pamięć podręczna aplikacji

Mobilna wersja html5rocks wykorzystuje pamięć podręczną aplikacji, aby przyspieszyć wstępne wczytywanie i umożliwia użytkownikom czytanie treści offline.

Gdy implementujesz AppCache w witrynie, bardzo ważne jest, aby nie zapisywać pliku manifestu w pamięci podręcznej (bezpośrednio w pliku manifestu lub pośrednio w nagłówkach sterowania pamięcią podręczną). Jeśli plik manifestu jest zapisywany w pamięci podręcznej przeglądarki, jego debugowanie jest kłopotliwe. iOS i Android dobrze radzą sobie z zapisywaniem tego pliku, ale nie zapewniają wygodnego sposobu czyszczenia pamięci podręcznej, jak ma to miejsce w przeglądarkach na komputerach.

Aby zapobiec takiemu buforowaniu w naszej witrynie, najpierw ustawiliśmy App Engine tak, aby pliki manifestu nigdy nie były zapisywane w pamięci podręcznej:

- 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. Pojawi się prośba 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 ograniczyć ruch sieciowy, manifest musi być prosty. Nie należy na nich opisywać każdej strony witryny. Wymień tylko ważne obrazy oraz pliki CSS i JavaScript. Ostatnią rzeczą, jaką możesz zrobić, jest wymuszanie w przeglądarce mobilnej pobierania dużej liczby zasobów przy każdej aktualizacji pamięci podręcznej aplikacji. Pamiętaj, że gdy użytkownik wejdzie na stronę, przeglądarka domyślnie zapisze stronę HTML w pamięci podręcznej (i zawiera atrybut <html manifest="...">).