Hướng dẫn 2 cách Optimize front-end tiếp theo

>>Hướng dẫn Optimize front-end để nâng cao tốc độ load webpage

Phần 3

Trong các phần trước, mình giới thiệu tới mọi người những kỹ thuật nhằm làm giảm số lượng request tới server. Vì nếu số lượng request lên server càng ít nhưng vẫn đảm bảo được chất lượng trang web thì đều đó đã làm tăng đáng kể về mặt load trang.

Hôm nay mình giới thiệu thêm những kỹ thuật nằm làm tăng tốc việc hiển thị trang web HTML. Phần này chủ yếu xoay quanh vấn đề về các file javascript, và file CSS.

1 - Đặt các file CSS trên đầu (phần <HEAD>) của trang web

Việc render HTML sẽ được thực hiện tuần tự từ trên xuống, nếu chúng ta đã khai báo các style sheet ngay trên đầu, thì việc hiển thị nội dung tới đâu nó sẽ map với các class của CSS tương ứng và render ngay. Nếu chúng ta đặt CSS ngay cuối trang web (gần thẻ </body>) thì trang web sẽ hiển thị một cách "kinh dị" vì thiếu các file định dạng CSS cho tới khi nó load xong hết các thành phần nội dung thì mới hiển thị định dạng. Ấy là chưa kể có những hình được khai báo trong CSS, nó sẽ không được hiển thị và trông trang web rất xấu. Và đôi khi, đối với trình duyệt IE, nó sẽ hiển thị trang web trắng cho đến khi việc render được thực hiện 100% thì nó mới show ra, điều này càng chậm hơn.

2 - Đặt các file Javascript (JS) dưới cùng của trang web

Ngược lại với các file CSS, chúng ta phải đặt các file JS nằm dưới cùng. Lý giải cho điều này, chúng ta cần biết cơ chế request và download của các trình duyệt. Chúng request song song các thành phần của 1 trang web như hình ảnh, flash, CSS... Nhưng đặc biệt khi load các file JS thì chúng lại chỉ load từng file chứ không áp dụng việc load song song. Tại sao lại như vậy. Câu trả lời đó là trong JS, đôi khi chúng ta tạo động các thành phần của trang web, nên nếu request song song nhiều file JS cùng lúc, sẽ không đảm bảo các thành phần phát sinh động được thực hiện đúng thứ tự. Mặc khác, nếu download song song, thì hẳn nhiên file nào nhỏ nhất sẽ xuống trước, nhưng biết đâu file đó có thứ tự thực thi cuối cùng, đều này cũng dẫn tới lỗi. Cho nên, khi trình duyệt load file JS xuống thì sẽ block lại để không download tiếp các file khác. Và chính điều này sẽ làm chậm đáng kể việc hiển thị nội dung website.

3 - Làm nhỏ dung lượng các file CSS, JS

Dĩ nhiên, 1 file có dung lượng càng nhỏ thì việc download nó xuống càng nhanh, điều này chắc chắn ai cũng biết ^^. Cho nên, nếu chúng ta có thể làm giảm dung lượng của các file này xuống càng thấp thì việc download chúng xuống càng nhanh. Sở dĩ các file này có thể làm nhỏ được đó là bởi vì khi chúng ta lập trình sẽ có những khoảng trắng vô nghĩa đối với trình dịch, những cái xuống dòng, những dòng ghi chú, tên biến thì đặt dài dòng (nhưng dễ hiểu)... điều này tăng kích thước của tập tin. Nếu chúng ta có thể dồn chúng lại, bỏ hết khoảng trắng và xuống dòng, bỏ luôn dòng ghi chú thì sẽ làm giảm dung lượng tập tin đáng kể.
Nhưng nếu viết kiểu đó thì chỉ có "thánh" mới đọc code nổi. Chúng ta cứ viết như bình thường, và sau đó dùng tool gom nó lại là xong. Dưới đây mình giới thiệu mọi người các tool online xử lý cho các chuyện này như sau:
1 - Làm nhỏ dung lượng file CSS: http://tools.arantius.com/css-compressor
2 - Làm nhỏ dung lượng file JS: http://dean.edwards.name/packer/
3 - Bỏ các ghi chú file JS: http://closure-compiler.appspot.com/home
Ghi chú: Nên dùng số 3 trước rồi mới dùng số 2.

4 - Dùng các file CSS, JS external. Không dùng dạng inline

Nếu chúng ta dồn hết các CSS, JS vào trong cùng 1 file HTML thì chúng ta chỉ mất 1 request để download tất cả xuống, và dĩ nhiên sẽ nhanh hơn so với việc chúng ta tách CSS, JS, HTML thành các file riêng lẽ vì khi đó chúng ta sẽ tốn nhiều request để lấy hết các file này. Tuy nhiên, chúng ta dùng external files vì trình duyệt sẽ cache lại chúng, và lần sau request page, nó chỉ request HTML còn CSS, JS thì nó lấy từ cache trình duyệt. Như vậy sẽ nhanh hơn nhiều so với inline.

Phần 4

Cũng lâu không có bài viết nào cho blog cá nhân của mình. Hôm nay mình viết tiếp chuỗi bài về tối ưu hóa tầng front-end nhằm cải thiện tốc độ của website (webpage). Ở các phần trước, mọi người sẽ tập trung thao tác vào cấu trúc web như đặt CSS trên đầu, JS bên dưới, phải dùng càng ít file CSS/JS thì càng tốt. Thì ở phần 4 này, mình sẽ nói về một chủ đề đã cũ nhưng biết đâu bạn cũng chưa biết. Đó là dùng tập tin .htaccess để tối ưu hóa một số thông tin khác ví dụ như nén file với gzip, hoặc đặt thời gian cache cho các file static...

1 - Nén file static (HTML, CSS, JS, PNG, GIF, JPG...) với mod_gzip

<ifModule mod_gzip.c>
  mod_gzip_on Yes
  mod_gzip_dechunk Yes
  mod_gzip_item_include file \.(html?|txt|css|js|php|pl)$
  mod_gzip_item_include handler ^cgi-script$
  mod_gzip_item_include mime ^text/.*
  mod_gzip_item_include mime ^application/x-javascript.*
  mod_gzip_item_exclude mime ^image/.*
  mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</ifModule>

2 - Nếu không có mod_gzip, chúng ta có thể dùng mod_deflate thay thế

<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/text text/html text/plain text/xml text/css application/x-javascript application/javascript
</IfModule>

3 - Thêm header expire cho các file static

<ifModule mod_expires.c>
  ExpiresActive On
  ExpiresDefault "access plus 1 seconds"
  ExpiresByType text/html "access plus 1 seconds"
  ExpiresByType image/gif "access plus 2592000 seconds"
  ExpiresByType image/jpeg "access plus 2592000 seconds"
  ExpiresByType image/png "access plus 2592000 seconds"
  ExpiresByType text/css "access plus 604800 seconds"
  ExpiresByType text/javascript "access plus 216000 seconds"
  ExpiresByType application/x-javascript "access plus 216000 seconds"
</ifModule>

4 - Thêm header cache-control cho các file static

<ifModule mod_headers.c>
  <filesMatch "\\.(ico|pdf|flv|jpg|jpeg|png|gif|swf)$">
    Header set Cache-Control "max-age=2592000, public"
  </filesMatch>
  <filesMatch "\\.(css)$">
    Header set Cache-Control "max-age=604800, public"
  </filesMatch>
  <filesMatch "\\.(js)$">
    Header set Cache-Control "max-age=216000, private"
  </filesMatch>
  <filesMatch "\\.(xml|txt)$">
    Header set Cache-Control "max-age=216000, public, must-revalidate"
  </filesMatch>
  <filesMatch "\\.(html|htm|php)$">
    Header set Cache-Control "max-age=1, private, must-revalidate"
  </filesMatch>
</ifModule>

5 - Tắt ETag của các file static

<ifModule mod_headers.c>
  Header unset ETag
</ifModule>
FileETag None

6 - Xóa thông tin Last-Modified của file static

<ifModule mod_headers.c>
  Header unset Last-Modified
</ifModule>

Phần 5(Tip)

1 - Không dùng các biến chưa khai báo.

Nếu chúng ta thực hiện phép tăng hoặc giảm ( ++, +=, --, -= ) cho 1 biến chưa khai báo trước thì nó chậm gấp 9, 10 lần so với việc ta khai báo nó xong mới thực hiện toán tử.

2 - Hạn chế tối đa việc gọi hàm trong vòng lặp.

Hàm sẽ được thực thi xuyên suốt vòng lặp. Đặc biệt không dùng for($i = 0; $i < count($arr); $i++)

3 - Không dùng mis-constant

$arr = array('test' => 1);
$arr[test] = 2; // Very slow
$arr['test'] = 2; // Nhanh gấp 7 lần so với cách trên

4 - Không ngăn chặn lỗi bằng @.

Cực kỳ chậm và tốn tài nguyên

5 - Không gọi các hàm magic call (__get, __set, __autoload)

Cực kỳ chậm

6 - Tránh không xài include_one, require_one.

Rất chậm và tốn nhiều tài nguyên nên dùng include, require. Tuyệt đối không dùng include_path

7 - Sử dụng toán tử so sánh === NULL nhanh hơn so với dùng is_null()

Theo kết quả benchmark thì việc dùng hàm is_null() sẽ chậm hơn dùng toán tử so sánh === NULL tới gấp 5 lần. Thực hiện thí nghiệm dựa trên thông số máy tính như sau: CPU intel core-i3, RAM 2GB, OS: window, WAMP: PHP 5.3.9

Iterations: 100000  (10 Runs)
 #  | NULL     | rel %  | is_null() | rel %  
----+----------+--------+-----------+--------
  1 |  0.02470 | 19.5 % |   0.12686 |  513.5%
  2 |  0.02276 | 17.9 % |   0.12696 |  557.9%
  3 |  0.02409 | 18.0 % |   0.13379 |  555.3%
  4 |  0.02239 | 17.9 % |   0.12509 |  558.6%
  5 |  0.02381 | 19.0 % |   0.12526 |  526.0%
  6 |  0.02351 | 18.2 % |   0.12904 |  548.9%
  7 |  0.02265 | 18.3 % |   0.12349 |  545.1%
  8 |  0.02233 | 18.6 % |   0.12019 |  538.2%
  9 |  0.02252 | 18.5 % |   0.12152 |  539.6%
 10 |  0.02293 | 18.8 % |   0.12191 |  531.7%