Kết hợp trang web HTML5

Eric Bidelman

Giới thiệu

Phát triển web dành cho thiết bị di động là một chủ đề nóng ngày nay. Năm nay, lần đầu tiên điện thoại thông minh bán hết máy tính. Ngày càng có nhiều người dùng sử dụng thiết bị di động để lướt web. Điều này đồng nghĩa với việc các nhà phát triển cần tối ưu hoá trang web cho trình duyệt cho thiết bị di động.

Chiến trường "thiết bị di động" vẫn là một chiến trường chưa được khám phá đối với một số lượng lớn các nhà phát triển. Nhiều người có sẵn các trang web cũ mà hoàn toàn bỏ qua người dùng thiết bị di động. Thay vào đó, trang web này chủ yếu được thiết kế để duyệt web trên máy tính và có chất lượng kém ở trình duyệt cho thiết bị di động. Trang web này (html5rock.com) cũng không phải là ngoại lệ. Khi ra mắt, chúng tôi đầu tư ít công sức vào phiên bản trang web dành cho thiết bị di động.

Tạo html5rock.com thân thiện với điện thoại di động

Như một bài tập, tôi nghĩ sẽ thú vị nếu bạn sử dụng html5rock (một trang web HTML5 hiện có) và tăng cường nó với một phiên bản thân thiện với thiết bị di động. Tôi chủ yếu lo ngại về lượng công việc tối thiểu cần thiết để nhắm mục tiêu đến điện thoại thông minh. Mục tiêu của tôi không phải là tạo một trang web hoàn toàn mới dành cho thiết bị di động và duy trì hai cơ sở mã. Việc đó sẽ mất mãi mãi và rất lãng phí thời gian. Chúng tôi đã xác định cấu trúc của trang web (mã đánh dấu). Chúng tôi đã có giao diện (CSS). Chức năng cốt lõi (JS) ở đó. Vấn đề là có nhiều địa điểm nằm trong chính chiếc thuyền này.

Bài viết này tìm hiểu cách chúng tôi tạo phiên bản html5rock được tối ưu hoá cho thiết bị di động cho các thiết bị Android và iOS. Chỉ cần tải html5rock.com trên một thiết bị hỗ trợ một trong các hệ điều hành đó để thấy sự khác biệt. Không có chuyển hướng nào đến m.html5rock.com hoặc tomfoolery khác có tính chất đó. Bạn tải html5rock như hiện tại... cộng với lợi ích bổ sung là thứ gì đó trông tuyệt vời và hoạt động tốt trên thiết bị di động.

Máy tính để bàn html5rock.com Điện thoại di động html5rock.com
html5rock.com trên máy tính (bên trái) và thiết bị di động (bên phải)

Truy vấn nội dung đa phương tiện CSS

HTML4 và CSS2 đã hỗ trợ biểu định kiểu phụ thuộc vào nội dung đa phương tiện trong một thời gian. Ví dụ:

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

sẽ nhắm mục tiêu các thiết bị in và cung cấp kiểu cụ thể cho nội dung trang khi in ra. CSS3 đưa ý tưởng về loại nội dung đa phương tiện tiến thêm một bước và cải thiện chức năng bằng các truy vấn nội dung đa phương tiện. Truy vấn nội dung nghe nhìn giúp mở rộng mức độ hữu ích của các loại nội dung nghe nhìn bằng cách cho phép gắn nhãn chính xác hơn cho các biểu định kiểu. Điều này cho phép tuỳ chỉnh bản trình bày nội dung theo một loạt thiết bị đầu ra cụ thể mà không phải thay đổi chính nội dung. Âm thanh rất phù hợp với bố cục hiện có cần chỉnh sửa!

Bạn có thể sử dụng các truy vấn nội dung đa phương tiện trong thuộc tính media của biểu định kiểu bên ngoài để nhắm mục tiêu chiều rộng màn hình, chiều rộng thiết bị, hướng, v.v. Để biết danh sách đầy đủ, hãy xem quy cách truy vấn nội dung nghe nhìn W3C.

Kích thước màn hình nhắm mục tiêu

Trong ví dụ sau, phone.css sẽ áp dụng cho các thiết bị mà trình duyệt xem là "cầm tay" hoặc thiết bị có màn hình <= 320px.

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

Việc thêm từ khoá "only" vào tiền tố cho truy vấn nội dung nghe nhìn sẽ khiến các trình duyệt không tương thích CSS3 bỏ qua quy tắc này.

Giá trị sau sẽ nhắm mục tiêu kích thước màn hình từ 641px đến 800px:

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

Truy vấn nội dung đa phương tiện cũng có thể xuất hiện trong các thẻ <style> cùng dòng. Các mục sau đây nhắm mục tiêu các loại nội dung nghe nhìn all khi theo hướng dọc:

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

media="handheld"

Chúng ta cần dừng lại một phút và thảo luận về media="handheld". Trên thực tế, Android và iOS sẽ bỏ qua media="handheld". Tuyên bố rằng người dùng sẽ bỏ lỡ nội dung cao cấp do các biểu định kiểu nhắm mục tiêu media="screen" cung cấp và nhà phát triển ít có khả năng duy trì phiên bản media="handheld" có chất lượng thấp hơn. Vì vậy, một phần trong phương châm "web đầy đủ" của họ, hầu hết các trình duyệt điện thoại thông minh hiện đại chỉ cần bỏ qua các biểu định kiểu cầm tay.

Bạn nên sử dụng tính năng này để nhắm mục tiêu đến các thiết bị di động, nhưng các trình duyệt khác nhau đã triển khai tính năng này theo những cách khác nhau:

  • Một số mẫu chỉ có thể đọc biểu định kiểu cầm tay.
  • Một số trang web chỉ có thể đọc biểu định kiểu cầm tay nếu có, nhưng nếu không thì sẽ mặc định biểu định kiểu màn hình được đọc.
  • Một số người dùng đọc cả biểu định kiểu cầm tay và biểu định kiểu màn hình.
  • Một số trang chỉ có thể đọc biểu định kiểu màn hình.

Opera Mini không bỏ qua media="handheld". Mẹo để Windows Mobile nhận ra media="handheld" là viết hoa giá trị thuộc tính đa phương tiện cho biểu định kiểu màn hình:

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

Cách html5rock sử dụng truy vấn phương tiện

Các truy vấn phương tiện được sử dụng rất nhiều trong html5rock dành cho thiết bị di động. Chúng cho phép chúng tôi điều chỉnh bố cục mà không cần thực hiện những thay đổi đáng kể đối với mã đánh dấu mẫu Django... một giải pháp cứu cánh thực sự! Ngoài ra, khả năng hỗ trợ trên nhiều trình duyệt là khá tốt.

Trong <head> của mỗi trang, bạn sẽ thấy các biểu định kiểu sau:

 <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 luôn xác định giao diện chính của html5rock.com, nhưng hiện tại chúng tôi đang áp dụng các kiểu mới (mobile.css) cho chiều rộng màn hình dưới 800px. Truy vấn phương tiện của nó bao gồm điện thoại thông minh (~320px) và iPad (~768px). Kết quả: chúng tôi sẽ từng bước ghi đè các kiểu trong base.css (chỉ khi cần) để làm cho mọi thứ trở nên tốt hơn trên thiết bị di động.

Một số thay đổi về kiểu mà mobile.css thực thi:

  • Giảm bớt khoảng trắng/khoảng đệm thừa trên trang web. Màn hình nhỏ nghĩa là không gian ở mức cao!
  • Xoá trạng thái :hover. Những thông tin này sẽ không bao giờ xuất hiện trên các thiết bị cảm ứng.
  • Điều chỉnh bố cục thành một cột duy nhất. Chúng ta sẽ nói thêm về điều này ở phần sau.
  • Xoá box-shadow xung quanh div vùng chứa chính của trang web. Bóng hộp lớn làm giảm hiệu suất của trang.
  • Sử dụng mô hình hộp linh hoạt của CSS box-ordinal-group để thay đổi thứ tự của từng phần trên trang chủ. Bạn sẽ thấy "TÌM HIỂU THEO NHÓM TÍNH NĂNG HTML5 CHÍNH" xuất hiện trước phần "TUTORIALS" trên trang chủ nhưng sau phần này trên phiên bản dành cho thiết bị di động. Thứ tự này phù hợp hơn với thiết bị di động và không yêu cầu thay đổi mã đánh dấu. CSS flexbox FTW!
  • Xoá opacity thay đổi. Việc thay đổi giá trị alpha là yếu tố ảnh hưởng đến hiệu suất trên thiết bị di động.

Thẻ meta dành cho thiết bị di động

WebKit dành cho thiết bị di động hỗ trợ một số tiện ích mang lại cho người dùng trải nghiệm duyệt web tốt hơn trên một số thiết bị nhất định.

Cài đặt khung nhìn

Cài đặt meta đầu tiên (và là cài đặt bạn sẽ sử dụng thường xuyên nhất) là thuộc tính khung nhìn. Việc đặt khung nhìn cho trình duyệt biết cách nội dung phù hợp với màn hình của thiết bị và thông báo cho trình duyệt biết rằng trang web được tối ưu hoá cho thiết bị di động. Ví dụ:

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

yêu cầu trình duyệt đặt khung nhìn theo chiều rộng của thiết bị với tỷ lệ ban đầu là 1. Ví dụ này cũng cho phép thu phóng – điều có thể mong muốn đối với trang web chứ không phải ứng dụng web. Chúng tôi có thể ngăn thu phóng bằng user-scalable=no hoặc giới hạn tỷ lệ ở một mức nhất định:

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

Android mở rộng thẻ meta cửa sổ xem bằng cách cho phép nhà phát triển chỉ định độ phân giải màn hình mà trang web được phát triển:

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

Giá trị target-densitydpi có thể có là device-dpi, high-dpi, medium-dpi, low-dpi.

Nếu bạn muốn sửa đổi trang web cho các mật độ màn hình khác nhau, hãy dùng truy vấn nội dung đa phương tiện CSS -webkit-device-pixel-ratio và/hoặc thuộc tính window.devicePixelRatio trong JavaScript, sau đó đặt thuộc tính meta target-densitydpi thành device-dpi. Điều này ngăn Android thực hiện việc mở rộng trên trang web của bạn và cho phép bạn thực hiện các điều chỉnh cần thiết cho từng mật độ, thông qua CSS và JavaScript.

Xem tài liệu WebView của Android để biết thêm thông tin về độ phân giải thiết bị nhắm mục tiêu.

Duyệt web ở chế độ toàn màn hình

Có hai giá trị meta khác là iOS-sfic. apple-mobile-web-app-capableapple-mobile-web-app-status-bar-style sẽ hiển thị nội dung trang ở chế độ toàn màn hình giống như ứng dụng và làm cho thanh trạng thái trong suốt:

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

Để biết thêm thông tin về tất cả các tuỳ chọn meta có sẵn, hãy xem Tài liệu tham khảo về Safari.

Biểu tượng trên màn hình chính

Các thiết bị iOS và Android cũng chấp nhận đường liên kết rel="apple-touch-icon" (iOS) và rel="apple-touch-icon-precomposed" (Android). Các đoạn mã này sẽ tạo ra một biểu tượng trông giống ứng dụng đẹp mắt trên màn hình chính của người dùng khi họ đánh dấu trang web của bạn:

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

Cách html5rock sử dụng thẻ meta dành cho thiết bị di động

Kết hợp mọi thứ lại với nhau, đây là đoạn mã từ phần <head> của html5rock:

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

Bố cục dọc

Trên các màn hình nhỏ hơn, việc cuộn theo chiều dọc sẽ thuận tiện hơn nhiều so với chiều ngang. Giữ nội dung trong một cột, bố cục dọc được ưu tiên cho thiết bị di động. Đối với html5rock, chúng tôi đã sử dụng các truy vấn phương tiện CSS3 để tạo bố cục như vậy. Xin nhắc lại là không cần thay đổi mã đánh dấu.

Chỉ mục hướng dẫn. Hướng dẫn. Trang Tính năng HTML5. Trang hồ sơ tác giả.
Bố cục dọc một cột trên toàn bộ trang web.

Tối ưu hóa cho thiết bị di động

Hầu hết các biện pháp tối ưu hoá mà chúng tôi thực hiện đều là những việc cần được thực hiện từ đầu. Những việc như giảm số lượng yêu cầu mạng, nén JS/CSS, nén gzip (miễn phí trên App Engine) và giảm thiểu các thao tác DOM. Những kỹ thuật này là các phương pháp hay nhất phổ biến, nhưng đôi khi bị bỏ qua khi nhanh chóng truy cập vào một trang web.

Tự động ẩn thanh địa chỉ

Trình duyệt dành cho thiết bị di động không có diện tích màn hình giống như trình duyệt trên máy tính. Tình trạng tồi tệ nhất là trên nhiều nền tảng, đôi khi bạn sẽ thấy một thanh địa chỉ lớn ở đầu màn hình... ngay cả sau khi trang tải xong.

Một cách dễ dàng để xử lý vấn đề này là cuộn trang bằng JavaScript. Ngay cả khi làm như vậy một pixel sẽ xử lý thanh địa chỉ khó chịu. Để buộc ẩn thanh địa chỉ trên html5rock, tôi đã đính kèm trình xử lý sự kiện onload vào đối tượng window và cuộn trang theo chiều dọc một pixel:

Thanh địa chỉ.
Thanh địa chỉ xấu chiếm không gian màn hình.
  // Hides mobile browser's address bar when page is done loading.
  window.addEventListener('load', function(e) {
    setTimeout(function() { window.scrollTo(0, 1); }, 1);
  }, false);

Chúng tôi cũng gói trình nghe này là biến mẫu is_mobile vì biến này không cần thiết trên máy tính.

Giảm yêu cầu mạng, tiết kiệm băng thông

Có một thực tế là việc giảm số lượng yêu cầu HTTP có thể cải thiện đáng kể hiệu suất. Thiết bị di động cũng giới hạn số lượng kết nối đồng thời mà trình duyệt có thể thực hiện, vì vậy, các trang web dành cho thiết bị di động sẽ được hưởng lợi nhiều hơn nữa từ việc giảm các yêu cầu không liên quan này. Hơn nữa, việc loại bỏ từng byte là rất quan trọng vì băng thông thường bị giới hạn trên điện thoại. Bạn có thể đang khiến người dùng tốn tiền!

Dưới đây là một số phương pháp chúng tôi đã thực hiện để giảm thiểu các yêu cầu mạng và giảm băng thông trên html5rock:

  • Xóa iframe - iframe chậm! Phần lớn thời gian trễ của chúng tôi đến từ các tiện ích chia sẻ của bên thứ ba (Buzz, Kết nối Bạn bè của Google, Twitter, Facebook) trên các trang hướng dẫn. Các API này được đưa vào thông qua các thẻ <script> và tạo iframe làm giảm tốc độ của trang. Đã xoá các tiện ích dành cho thiết bị di động.

  • display:none – Trong một số trường hợp, chúng tôi đã ẩn mã đánh dấu nếu mã đó không phù hợp với hồ sơ dành cho thiết bị di động. Một ví dụ điển hình là 4 hộp được bo tròn ở đầu trang chủ:

Các nút hộp trên trang chủ.
Hộp nút trên trang chủ.

Trang web dành cho thiết bị di động còn thiếu thông tin này. Điều quan trọng cần nhớ là trình duyệt vẫn đưa ra yêu cầu cho từng biểu tượng, mặc dù vùng chứa của trình duyệt đang bị ẩn bằng display:none. Do đó, việc chỉ ẩn các nút này là chưa đủ. Việc đó không chỉ làm lãng phí băng thông, mà thậm chí người dùng sẽ không thấy những kết quả của việc lãng phí băng thông đó! Giải pháp là tạo một boolean "is_mobile" trong mẫu Django của chúng tôi để bỏ qua các phần của HTML có điều kiện. Khi người dùng đang xem trang web trên một thiết bị thông minh, các nút sẽ không hiển thị.

  • Bộ nhớ đệm của ứng dụng – Việc này không chỉ giúp chúng tôi hỗ trợ ngoại tuyến mà còn giúp khởi động nhanh hơn.

  • Nén CSS/JS – chúng tôi đang sử dụng trình nén YUI thay vì Trình biên dịch đóng chủ yếu vì trình biên dịch này xử lý cả CSS và JS. Một vấn đề mà chúng tôi gặp phải là các truy vấn phương tiện nội tuyến (truy vấn phương tiện xuất hiện bên trong biểu định kiểu) bị chặn trong trình nén YUI 2.4.2 (xem vấn đề này). Sử dụng YUI Compressor 2.4.4+ đã khắc phục sự cố.

  • Sử dụng các sprite hình ảnh CSS nếu có thể.

  • Sử dụng pngcrush để nén hình ảnh.

  • Sử dụng dataURI cho hình ảnh nhỏ. Phương thức mã hoá Base64 sẽ thêm khoảng 30%kích thước vào hình ảnh nhưng lưu yêu cầu mạng.

  • Đã tự động tải Tìm kiếm tuỳ chỉnh của Google bằng cách sử dụng một thẻ tập lệnh duy nhất thay vì tải động bằng google.load(). Người thứ hai đưa ra một yêu cầu bổ sung.

<script src="//www.google.com/jsapi?autoload={"modules":[{"name":"search","version":"1"}]}"> </script>
  • Chúng tôi đã đưa mã máy in đẹp và hiện đại hoá vào mọi trang, ngay cả khi chúng chưa từng được sử dụng. Modernizr rất tuyệt, nhưng nó chạy rất nhiều thử nghiệm trên mỗi lần tải. Một số thử nghiệm trong số đó thực hiện các sửa đổi tốn kém đối với DOM và làm chậm quá trình tải trang. Giờ đây, chúng tôi chỉ đưa các thư viện này vào những trang thực sự cần thiết. -2 yêu cầu :)

Các tinh chỉnh hiệu suất khác:

  • Đã di chuyển tất cả JS xuống cuối trang (nếu có thể).
  • Đã xoá thẻ <style> cùng dòng.
  • Tra cứu DOM được lưu trong bộ nhớ đệm và các thao tác DOM ở mức tối thiểu – Mỗi khi bạn chạm vào DOM, trình duyệt sẽ thực hiện quy trình chỉnh lại luồng. Việc chỉnh lại luồng thậm chí còn tốn kém hơn trên thiết bị di động.
  • Giảm tải mã phía máy khách lãng phí sang máy chủ. Cụ thể, hãy đánh dấu để xem thiết lập kiểu điều hướng của trang hiện tại: 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'; } }
  • Các phần tử có chiều rộng cố định đã được thay thế bằng width:100% hoặc width:auto linh hoạt.

Bộ nhớ đệm của ứng dụng

Phiên bản html5rock dành cho thiết bị di động sử dụng Bộ nhớ đệm ứng dụng để tăng tốc độ tải ban đầu và cho phép người dùng đọc nội dung ngoại tuyến.

Khi triển khai AppCache trên trang web, điều quan trọng là bạn không nên lưu tệp kê khai vào bộ nhớ đệm (thể hiện rõ ràng trong chính tệp kê khai hoặc ngầm ẩn với các tiêu đề kiểm soát bộ nhớ đệm nặng). Nếu tệp kê khai của bạn được trình duyệt lưu vào bộ nhớ đệm thì đó là một cơn ác mộng khi gỡ lỗi. iOS và Android làm rất tốt việc lưu tệp này vào bộ nhớ đệm nhưng không cung cấp cách thuận tiện để xoá bộ nhớ đệm như trình duyệt dành cho máy tính.

Để ngăn việc lưu vào bộ nhớ đệm đã nêu cho trang web của chúng tôi, trước tiên, chúng tôi đặt App Engine để không bao giờ lưu các tệp kê khai vào bộ nhớ đệm:

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

Thứ hai, chúng tôi sử dụng JS API để thông báo cho người dùng khi tệp kê khai mới đã tải xuống xong. Họ sẽ được nhắc làm mới trang:

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);

Để lưu lưu lượng truy cập mạng, hãy giữ tệp kê khai của bạn đơn giản. Điều đó có nghĩa là đừng chú thích mọi trang trên trang web của bạn. Chỉ cần liệt kê những hình ảnh, tệp CSS và JavaScript quan trọng. Điều cuối cùng bạn muốn làm là buộc trình duyệt dành cho thiết bị di động tải xuống một lượng lớn nội dung trên mỗi bản cập nhật appcache. Thay vào đó, hãy nhớ rằng trình duyệt sẽ ngầm lưu một trang html vào bộ nhớ đệm khi người dùng truy cập (và trang này có chứa thuộc tính <html manifest="...">).