Wprowadzenie
Obecnie tworzenie aplikacji na potrzeby internetu mobilnego to gorący temat. 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, dlatego deweloperzy muszą optymalizować swoje witryny pod kątem przeglądarek mobilnych.
„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 komputerów, a jej jakość spada w przeglądarkach mobilnych. 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
Postanowiłem wykorzystać html5rocks (dotychczasową witrynę HTML5) i dodać do niej wersję dostosowaną do urządzeń mobilnych. 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. To zajęłoby wieki i byłoby ogromną stratą czasu. Strukturę witryny (oznaczanie) mieliśmy już zdefiniowaną. Sprawdziliśmy to (CSS). Główna funkcjonalność (JS) była obecna. Chodzi o to, że wiele witryn ma ten sam problem.
W tym artykule opisujemy, jak utworzyć wersję mobilną 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 przekierowań do m.html5rocks.com ani innych stron o podobnej nazwie. 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.


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 ekranu
W tym przykładzie phone.css
będzie dotyczyć urządzeń, które przeglądarka uzna za „przenośne” lub urządzeń z ekranem o szerokości ≤ 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ą też pojawiać się w tagach wbudowanych <style>
. Te typy mediów all
są kierowane 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. Dlatego większość nowoczesnych przeglądarek na smartfony po prostu ignoruje arkuszy stylów dla urządzeń mobilnych.
Najlepiej używać tej funkcji do kierowania na urządzenia mobilne, ale różne przeglądarki implementują ją na różne sposoby:
- Niektóre czytają tylko arkusz stylów urządzenia przenośnego.
- Niektóre urządzenia odczytują tylko arkusz stylów dla urządzeń przenośnych, jeśli taki istnieje, w przeciwnym razie używają domyślnie arkusza stylów dla ekranu.
- Niektóre urządzenia odczytują zarówno arkusz stylów dla urządzeń przenośnych, 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 w przypadku atrybutu media w stylu ekranu użyć wielkich 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 korzysta z zapytań dotyczących multimediów
Zapytania o multimedia są często używane w html5rocks na urządzeniach mobilnych. Dzięki nim mogliśmy dostosować układ bez wprowadzania znaczących zmian w tagach szablonu Django. To prawdziwa ulga! Poza tym ich obsługa w różnych przeglądarkach jest całkiem dobra.
W sekcji <head>
każdej strony znajdziesz 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ł 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 stany
:hover
. 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”, na stronie głównej przed sekcją „PORADY”, ale w wersji mobilnej po niej. 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
WebKit na urządzeniach mobilnych obsługuje kilka funkcji, które zapewniają użytkownikom większą wygodę przeglądania na niektórych 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ć przydatne w przypadku witryny, ale nie aplikacji internetowej. Możemy 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 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ą na potrzeby różnych gęstości ekranu, użyj zapytania o multimedia CSS -webkit-device-pixel-ratio
lub właściwości window.devicePixelRatio
w JavaScript, a następnie ustaw wartość właściwości meta target-densitydpi
na device-dpi
. Zapobiega to skalowaniu przez Androida Twojej strony internetowej i umożliwia wprowadzanie 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 w trybie pełnoekranowym
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 aplikację:
<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 strona html5rocks używa metatagów mobilnych
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 zalecamy stosowanie układu pionowego z jedną kolumną. W przypadku html5rocks do utworzenia takiego układu użyliśmy zapytań medialnych CSS3. Ponownie bez zmiany znaczników.




Optymalizacja pod kątem urządzeń mobilnych
Większość wprowadzonych przez nas optymalizacji to rzeczy, które powinny zostać zrobione na samym początku. Na przykład zmniejszenie liczby żądań sieciowych, kompresja kodu JS/CSS, kompresja gzip (dostępna bezpłatnie w App Engine) i minimalizowanie 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:

// 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 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:

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 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 w szablonie Django typu logicznego „is_mobile”, aby 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, ponieważ obsługuje on zarówno CSS, jak i JS. Jednym z problemów, na który natrafiliśmy, były zapytania o multimedia w kodze (zapytania o multimedia, które pojawiają się w arkuszu stylów) w kompresorze YUI 2.4.2 (patrz ten problem). Problem został rozwiązany dzięki zastosowaniu narzędzia YUI Compressor w wersji 2.4.4 lub nowszej.
W miarę możliwości używaj sprite'ów obrazów CSS.
Do kompresji obrazu użyto narzędzia pngcrush.
Użyto danych URI w przypadku 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ą
google.load()
. Ta druga metoda wysyła dodatkowe żądanie.
<script src="//www.google.com/jsapi?autoload={"modules":[{"name":"search","version":"1"}]}"> </script>
- Na każdej stronie były uwzględnione nasza drukarka kodu i biblioteka Modernizr, 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ą rzeczywiście potrzebne. -2 żądania :)
Dodatkowe ulepszenia wydajności:
- Przeniesienie wszystkich plików JS na 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 przeformatowanie jest jeszcze bardziej kosztowne.
- Przeniesiono na serwer nieefektywny kod po stronie klienta. W szczególności pole wyboru, które pozwala sprawdzić 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 niezmiennej szerokości zostały zastąpione przez elementy płynne
width:100%
lubwidth: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.
Podczas implementowania pamięci podręcznej AppCache w witrynie bardzo ważne jest, aby nie buforować pliku manifestu (ani jawnie w tym pliku, ani domyślnie za pomocą nagłówków kontroli 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 opróżnienie 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 zostaną poproszeni 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, zachowaj prosty manifest. Oznacza to, że nie musisz wymieniać wszystkich stron 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="...">
).