Phân phát mã hiện đại cho các trình duyệt hiện đại để tải trang nhanh hơn

Việc xây dựng các trang web hoạt động tốt trên tất cả trình duyệt chính là nguyên tắc cốt lõi của hệ sinh thái web mở. Tuy nhiên, điều này có nghĩa là bạn cần phải làm thêm việc để đảm bảo rằng tất cả mã bạn viết đều được hỗ trợ trong từng trình duyệt mà bạn dự định nhắm đến. Nếu muốn sử dụng các tính năng ngôn ngữ JavaScript mới, bạn cần chuyển đổi các tính năng này sang các định dạng tương thích ngược cho những trình duyệt chưa hỗ trợ các tính năng đó.

Babel là công cụ được sử dụng rộng rãi nhất để biên dịch mã chứa cú pháp mới hơn thành mã mà các trình duyệt và môi trường khác nhau (chẳng hạn như Node) có thể hiểu được. Hướng dẫn này giả định rằng bạn đang sử dụng Babel, vì vậy, bạn cần làm theo hướng dẫn thiết lập để đưa Babel vào ứng dụng của mình nếu chưa thực hiện. Chọn webpack trong Build Systems nếu bạn đang sử dụng webpack làm trình đóng gói mô-đun trong ứng dụng.

Để sử dụng Babel chỉ biên dịch những gì người dùng cần, bạn cần:

  1. Xác định những trình duyệt mà bạn muốn nhắm đến.
  2. Sử dụng @babel/preset-env với các mục tiêu trình duyệt thích hợp.
  3. Sử dụng <script type="module"> để ngừng gửi mã được biên dịch sang trình duyệt không cần mã đó.

Xác định trình duyệt mà bạn muốn nhắm đến

Trước khi bắt đầu sửa đổi cách mã trong ứng dụng được biên dịch, bạn cần xác định những trình duyệt nào truy cập vào ứng dụng của mình. Phân tích những trình duyệt mà người dùng của bạn hiện đang sử dụng cũng như những trình duyệt mà bạn dự định nhắm đến để đưa ra quyết định sáng suốt.

Sử dụng @babel/preset-env

Việc chuyển đổi mã thường dẫn đến tệp có kích thước lớn hơn so với các dạng ban đầu. Bằng cách giảm thiểu số lần biên dịch, bạn có thể giảm kích thước gói để cải thiện hiệu suất của trang web.

Thay vì đưa các trình bổ trợ cụ thể vào để biên dịch có chọn lọc một số tính năng ngôn ngữ nhất định mà bạn đang sử dụng, Babel cung cấp một số chế độ cài đặt trước giúp gói các trình bổ trợ lại với nhau. Sử dụng @babel/preset-env để chỉ bao gồm các phép biến đổi và polyfill cần thiết cho các trình duyệt mà bạn dự định nhắm đến.

Đưa @babel/preset-env vào mảng presets trong tệp cấu hình Babel, .babelrc:

{
 "presets": [
   [
     "@babel/preset-env",
     {
       "targets": ">0.25%"
     }
   ]
 ]
}

Sử dụng trường targets để chỉ định phiên bản trình duyệt mà bạn muốn đưa vào bằng cách thêm một truy vấn thích hợp vào trường browsers. @babel/preset-env tích hợp với danh sách trình duyệt, một cấu hình nguồn mở được chia sẻ giữa các công cụ nhắm mục tiêu trình duyệt. Danh sách đầy đủ các truy vấn tương thích có trong tài liệu về danh sách trình duyệt. Một lựa chọn khác là sử dụng tệp .browserslistrc để liệt kê các môi trường mà bạn muốn nhắm đến.

Giá trị ">0.25%" yêu cầu Babel chỉ bao gồm các phép biến đổi cần thiết để hỗ trợ các trình duyệt chiếm hơn 0,25% mức sử dụng trên toàn cầu. Điều này đảm bảo gói của bạn không chứa mã chuyển đổi không cần thiết cho các trình duyệt mà chỉ một tỷ lệ rất nhỏ người dùng sử dụng.

Trong hầu hết các trường hợp, đây là phương pháp tốt hơn so với việc sử dụng cấu hình sau:

  "targets": "last 2 versions"

Giá trị "last 2 versions" sẽ biên dịch mã của bạn cho 2 phiên bản mới nhất của mọi trình duyệt, nghĩa là sẽ hỗ trợ các trình duyệt không còn hoạt động như Internet Explorer. Điều này có thể làm tăng kích thước gói của bạn một cách không cần thiết nếu bạn không dự kiến sử dụng các trình duyệt này để truy cập vào ứng dụng của mình.

Cuối cùng, bạn nên chọn tổ hợp cụm từ tìm kiếm phù hợp để chỉ nhắm đến những trình duyệt phù hợp với nhu cầu của bạn.

Bật các bản sửa lỗi hiện đại

@babel/preset-env nhóm nhiều tính năng cú pháp JavaScript thành các bộ sưu tập và bật/tắt các tính năng đó dựa trên trình duyệt mục tiêu được chỉ định. Mặc dù cách này hoạt động tốt, nhưng toàn bộ bộ sưu tập các tính năng cú pháp sẽ được chuyển đổi khi một trình duyệt được nhắm mục tiêu chứa lỗi chỉ với một tính năng. Điều này thường dẫn đến việc tạo ra nhiều mã đã chuyển đổi hơn mức cần thiết.

Ban đầu được phát triển dưới dạng một tuỳ chọn đặt trước riêng, tuỳ chọn sửa lỗi trong @babel/preset-env giải quyết vấn đề này bằng cách chuyển đổi cú pháp hiện đại bị hỏng trong một số trình duyệt thành cú pháp tương đương gần nhất không bị hỏng trong các trình duyệt đó. Kết quả là mã hiện đại gần giống nhau với một vài điều chỉnh nhỏ về cú pháp để đảm bảo khả năng tương thích trong tất cả trình duyệt mục tiêu. Để sử dụng tính năng tối ưu hoá này, hãy đảm bảo bạn đã cài đặt @babel/preset-env 7.10 trở lên, sau đó đặt thuộc tính bugfixes thành true:

{
 "presets": [
   [
     "@babel/preset-env",
     {
       "bugfixes": true
     }
   ]
 ]
}

Trong Babel 8, tuỳ chọn bugfixes sẽ được bật theo mặc định.

Sử dụng <script type="module">

Mô-đun JavaScript hoặc mô-đun ES là một tính năng tương đối mới được hỗ trợ trong tất cả trình duyệt chính. Bạn có thể sử dụng các mô-đun để tạo tập lệnh có thể nhập và xuất từ các mô-đun khác, nhưng bạn cũng có thể sử dụng các mô-đun đó với @babel/preset-env để chỉ nhắm đến các trình duyệt hỗ trợ các mô-đun đó.

Thay vì truy vấn các phiên bản trình duyệt hoặc thị phần cụ thể, hãy cân nhắc việc chỉ định "esmodules" : true bên trong trường targets của tệp .babelrc.

{
   "presets":[
      [
         "@babel/preset-env",
         {
            "targets":{
               "esmodules": true
            }
         }
      ]
   ]
}

Nhiều tính năng ECMAScript mới hơn được biên dịch bằng Babel đã được hỗ trợ trong các môi trường hỗ trợ mô-đun JavaScript. Vì vậy, bằng cách này, bạn sẽ đơn giản hoá quy trình đảm bảo rằng chỉ sử dụng mã được biên dịch cho các trình duyệt thực sự cần mã đó.

Các trình duyệt hỗ trợ mô-đun sẽ bỏ qua các tập lệnh có thuộc tính nomodule. Ngược lại, những trình duyệt không hỗ trợ mô-đun sẽ bỏ qua các phần tử tập lệnh có type="module". Điều này có nghĩa là bạn có thể đưa một mô-đun cũng như một bản dự phòng đã biên dịch vào.

Lý tưởng nhất là hai tập lệnh phiên bản của một ứng dụng được đưa vào như sau:

  <script type="module" src="main.mjs"></script>
  <script nomodule src="compiled.js" defer></script>

Các trình duyệt hỗ trợ mô-đun tìm nạp và thực thi main.mjs và bỏ qua compiled.js. Các trình duyệt không hỗ trợ mô-đun sẽ làm ngược lại.

Nếu sử dụng webpack, bạn có thể đặt các mục tiêu khác nhau trong cấu hình cho hai phiên bản riêng biệt của ứng dụng:

  • Phiên bản chỉ dành cho các trình duyệt hỗ trợ mô-đun.
  • Phiên bản bao gồm một tập lệnh đã biên dịch hoạt động trong mọi trình duyệt cũ. Tệp này có kích thước lớn hơn vì quá trình chuyển đổi mã cần hỗ trợ nhiều trình duyệt hơn.

Cảm ơn Connor Clark và Jason Miller đã xem xét.