Nén tệp bằng Closure Compiler Service API

Dịch vụ biên dịch đóng không được dùng nữa và sẽ bị xoá. Thay vào đó, vui lòng cân nhắc chạy trình biên dịch cục bộ.

Tổng quan

Trao đổi với API mô tả những kiến thức cơ bản về cách giao tiếp với dịch vụ Trình biên dịch đóng cửa, nhưng chỉ minh hoạ cách sử dụng dịch vụ này để loại bỏ bình luận khỏi một dòng JavaScript. Hướng dẫn này minh hoạ cách sử dụng dịch vụ Closure Compiler trong một tình huống phát triển thực tế hơn: xử lý toàn bộ tệp JavaScript để giảm đáng kể kích thước.

Hướng dẫn này giả định rằng bạn đã quen thuộc với JavaScript và HTTP. Mặc dù mã này sử dụng tập lệnh Python để gửi JavaScript đến dịch vụ compile Compiler, nhưng bạn không cần biết Python để làm theo ví dụ này.

  1. Nén tệp
  2. Cải thiện độ nén
    1. Mã này nhỏ hơn bao nhiêu?
    2. Làm thế nào để Dịch vụ biên dịch đóng cửa thu nhỏ chương trình?
  3. Bước tiếp theo

Nén tệp

Ví dụ trong bài viết Trao đổi với API đã chuyển một chuỗi JavaScript dưới dạng tham số dòng lệnh đến tập lệnh biên dịch. Tuy nhiên, phương pháp này sẽ không hiệu quả đối với chương trình JavaScript có kích thước thực tế, vì chuỗi JavaScript nhanh chóng trở nên khó sử dụng khi mã dài hơn vài dòng. Đối với các chương trình lớn hơn, bạn có thể sử dụng tham số yêu cầu code_url để chỉ định tên của tệp JavaScript cần xử lý. Bạn có thể sử dụng code_url ngoài js_code hoặc thay thế cho js_code.

Ví dụ: hãy xem xét chương trình JavaScript sau:

/**
 * A simple script for adding a list of notes to a page. The list diplays
 * the text of each note under its title.
 */

/**
 * Creates the DOM structure for a note and adds it to the document.
 */
function makeNoteDom(noteTitle, noteContent, noteContainer) {
  // Create DOM structure to represent the note.
  var headerElement = document.createElement('div');
  var headerText = document.createTextNode(noteTitle);
  headerElement.appendChild(headerText);

  var contentElement = document.createElement('div');
  var contentText = document.createTextNode(noteContent);
  contentElement.appendChild(contentText);

  var newNote = document.createElement('div');
  newNote.appendChild(headerElement);
  newNote.appendChild(contentElement);

  // Add the note's DOM structure to the document.
  noteContainer.appendChild(newNote);
}

/**
 * Iterates over a list of note data objects and creates a DOM
 */
function makeNotes(data, noteContainer) {
  for (var i = 0; i < data.length; i++) {
    makeNoteDom(data[i].title, data[i].content, noteContainer);
  }
}

function main() {
  var noteData = [
      {title: 'Note 1', content: 'Content of Note 1'},
      {title: 'Note 2', content: 'Content of Note 2'}];
  var noteListElement = document.getElementById('notes');
  makeNotes(noteData, noteListElement);
}

main();

Bạn có thể chuyển chương trình này đến dịch vụ Trình biên dịch đóng cửa dưới dạng một tệp thuận tiện hơn là một chuỗi lớn. Làm theo các bước sau để xử lý tệp bằng dịch vụ:

  1. Lưu JavaScript trong một tệp.
  2. Đặt tệp này trên web (bằng cách tải tệp lên máy chủ web của bạn chẳng hạn).
  3. Tạo một yêu cầu POST cho dịch vụ Closure Compiler như được minh hoạ trong phần Truyền thông với API, nhưng đối với tham số js_code thay thế tham số code_url. Giá trị của code_url phải là URL của tệp JavaScript tạo ở Bước 1.

Ví dụ: bạn có thể tìm thấy JavaScript cho ví dụ này trong tệp tutorial2.js. Để xử lý tệp này bằng API dịch vụ Trình biên dịch đóng, hãy thay đổi chương trình python từ Giao tiếp với API để sử dụng code_url, như sau:

#!/usr/bin/python2.4

import httplib, urllib, sys

# Define the parameters for the POST request and encode them in
# a URL-safe format.

params = urllib.urlencode([
    ('code_url', sys.argv[1]), # <--- This parameter has a new name!
    ('compilation_level', 'WHITESPACE_ONLY'),
    ('output_format', 'text'),
    ('output_info', 'compiled_code'),
  ])

# Always use the following value for the Content-type header.
headers = { "Content-type": "application/x-www-form-urlencoded" }
conn = httplib.HTTPSConnection('closure-compiler.appspot.com')
conn.request('POST', '/compile', params, headers)
response = conn.getresponse()
data = response.read()
print data
conn.close()

Lưu ý: Để tái tạo ví dụ này, người dùng Windows có thể cần cài đặt Python. Xem Câu hỏi thường gặp về Python Windows để biết hướng dẫn về cách cài đặt và sử dụng Python trong Windows.

Gửi mã đến dịch vụ Trình biên dịch đóng bằng lệnh sau:

$ python compile.py https://closure-compiler.appspot.com/closure/compiler/samples/tutorial2.js

Dịch vụ compile Compiler truy xuất tệp từ https://closure-compiler.appspot.com/closure/compiler/samples/tutorial2.js và trả về JavaScript nén trong phản hồi.

Để biên dịch nhiều tệp đầu ra cùng nhau thành một tệp đầu ra, hãy thêm nhiều thông số code_url, như trong ví dụ sau:

params = urllib.urlencode([
    # Multiple code_url parameters:
    ('code_url', 'http://yourserver.com/yourJsPart1.js'),
    ('code_url', 'http://yourserver.com/yourJsPart2.js'),
    ('compilation_level', 'WHITESPACE_ONLY'),
    ('output_format', 'text'),
    ('output_info', 'compiled_code'),
  ])

Cải thiện độ nén

Tính đến hiện tại, các ví dụ này đã sử dụng compilation_level WHITESPACE_ONLY, chỉ xoá các nhận xét và khoảng trắng. Với mức nén SIMPLE_OPTIMIZATIONS, bạn có thể đạt được tỷ lệ nén cao hơn nhiều. Để sử dụng nén SIMPLE_OPTIMIZATIONS, hãy thay đổi thông số compilation_level thành SIMPLE_OPTIMIZATIONS:

params = urllib.urlencode([
    ('code_url', sys.argv[1]),
    ('compilation_level', 'SIMPLE_OPTIMIZATIONS'),  # <--- This parameter has a new value!
    ('output_format', 'text'),
    ('output_info', 'compiled_code'),
  ])

rồi chạy tập lệnh như trước:

$ python compile.py https://closure-compiler.appspot.com/closure/compiler/samples/tutorial2.js

Kết quả đầu ra sẽ có dạng như sau:

var GLOBAL_document=document,$$PROP_appendChild="appendChild";function makeNoteDom(a,b,c){var d=GLOBAL_document.createElement("div");a=GLOBAL_document.createTextNode(a);d[$$PROP_appendChild](a);a=GLOBAL_document.createElement("div");b=GLOBAL_document.createTextNode(b);a[$$PROP_appendChild](b);b=GLOBAL_document.createElement("div");b[$$PROP_appendChild](d);b[$$PROP_appendChild](a);c[$$PROP_appendChild](b)}function makeNotes(a,b){for(var c=0;c<a.length;c++)makeNoteDom(a[c].title,a[c].content,b)}
function main(){var a=[{title:"Note 1",content:"Content of Note 1"},{title:"Note 2",content:"Content of Note 2"}],b=GLOBAL_document.getElementById("notes");makeNotes(a,b)}main();

Mã này khó đọc hơn chương trình nguồn, nhưng mã này nhỏ hơn.

Mã này nhỏ hơn bao nhiêu?

Nếu thay đổi output_info trong các tham số yêu cầu của mình từ compiled_code thành statistics, chúng ta có thể thấy chính xác dung lượng chúng tôi đã tiết kiệm được:

Original Size: 1372
Compressed Size: 677
Compilation Time: 0

JavaScript mới có kích thước nhỏ hơn một nửa so với JavaScript gốc.

Dịch vụ biên dịch khép kín đã làm cho chương trình nhỏ hơn như thế nào?

Trong trường hợp này, Trình biên dịch đóng đã đạt được kích thước một phần bằng cách đổi tên các biến cục bộ. Ví dụ: tệp gốc bao gồm dòng mã sau:

var headerElement = document.createElement('div');

Closure Compiler thay đổi câu lệnh này thành:

var d=document.createElement("div");

Trình biên dịch đóng thay đổi biểu tượng headerElement thành d ở mọi nơi trong hàm makeNoteDom, do đó giữ nguyên chức năng. Nhưng 13 ký tự của headerElement đã được rút ngắn thành một ký tự ở mỗi vị trí trong số đó. Điều này giúp tiết kiệm tổng cộng 36 ký tự.

Việc biên dịch bằng SIMPLE_OPTIMIZATIONS luôn giữ nguyên chức năng của JavaScript hợp lệ về mặt cú pháp, miễn là mã đó không truy cập vào các biến cục bộ bằng tên chuỗi (ví dụ: bằng câu lệnh eval()).

Các bước tiếp theo

Giờ thì bạn đã làm quen với SIMPLE_OPTIMIZATIONS và cơ chế sử dụng dịch vụ cơ bản. Bước tiếp theo là tìm hiểu về cấp độ biên dịch ADVANCED_OPTIMIZATIONS. Cấp độ này yêu cầu bạn thực hiện thêm một số bước để đảm bảo rằng JavaScript hoạt động giống như trước và sau khi biên dịch, nhưng đồng thời giảm kích thước JavaScript. Xem phần Biên dịch nâng cao và phương thức cũ để tìm hiểu về ADVANCED_OPTIMIZATIONS.