Giới thiệu về Source Maps

Bài viết được dịch từ bài An Introduction to Source Maps của tác giả Matt West

Một trong những thành tích về hiệu năng mà bạn có thể đạt được cho website của mình là ghép và nén các file JavaScript và CSS. Nhưng nếu bạn cần phải debug trên code đã được nén đó thì sao? Đó có thể là một cơn ác mộng. Tuy nhiên đừng sợ, có một giải pháp đang xuất hiện và nó có tên là source maps.

Một source map cung cấp cách ánh xạ code ở trong một file đã được nén với vị trí gốc ở trong file nguồn. Điều đó có nghĩa là - với một chút trợ giúp của phần mềm - bạn có thể dễ dàng debug ứng dụng của bạn ngay cả khi các asset của bạn đã được tối ưu hóa. Công cụ dành cho nhà phát triển (developer tools) của Chrome và Firefox đều hỗ trợ cho source maps.

Trong bài viết này bạn sẽ học được cách source maps hoạt động và cách tạo ra nó. Chúng ta sẽ chủ yếu tập trung vào source map dành cho JavaScript, nguyên lý của nó cũng tương tự với CSS source maps.


Chú ý: Sự hỗ trợ dành cho source map mặc định được bật ở Firefox developer tools. Bạn cần phải bật bằng tay ở Chrome. Để làm điều này, mở Chrome dev tools, mở bảng Settings (hình bánh răng ở góc dưới bên phải). Trong tab General tích chọn Enable JS source mapsEnable CSS source maps.


Cách source maps hoạt động

Như tên gọi của nó, một source map chứa toàn bộ thông tin được sử dụng để ánh xạ code trong một file đã nén với nguồn gốc của nó. Bạn có thể chỉ định các source map khác nhau cho các file đã được nén của bạn.

Bạn cho trình duyệt biết rằng có source map bằng cách thêm một dòng comment đặc biệt vào dưới cùng của file đã được tối ưu hóa.

//# sourceMappingURL=/path/to/script.js.map

Comment này thường được thêm vào bởi chương trình được sử dungjddeer sinh ra source map. Developer tools sẽ chỉ nạp file này nếu sự hỗ trợ cho source map được bật và developer tools được mở lên.

Bạn cũng có thể cho biết có source map bằng cách gửi HTTP header X-SourceMap trong response trả về file Javascript được nén.

X-SourceMap: /path/to/script.js.map

File source map chứa một đối tượng JSON gồm thông tin về ánh xạ và các file JavaScript gốc. Dưới đây là một ví dụ đơn giản:

{
  version: 3,
  file: "script.js.map",
  sources: [
    "app.js",
    "content.js",
    "widget.js"
  ],
  sourceRoot: "/",
  names: ["slideUp", "slideDown", "save"],
  mappings: "AAA0B,kBAAhBA,QAAOC,SACjBD,OAAOC,OAAO..."
}

Hãy xem xét rõ hơn về các thuộc tính này.

  • version - Thuộc tính này xác dịnh phiên bản của source map spec mà file này tuân theo.
  • file - Tên của file source map.
  • sources - Một mảng chứa các URL của các file gốc.
  • sourceRoot - (tùy chọn) URL mà tất cả các file trong mảng source sẽ được xác định.
  • names - Một mảng chứa tất cả các tên biến và hàm trong các file gốc.
  • mappings - Một xâu Base64 VLQs chứa ánh xạ code (đây là nơi mà ma thuật xảy ra).

Sinh source maps bằng UglifyJS

UglifyJS là một tiện ích phổ biến cho phép bạn ghép và nén các file JavaScript. Phiên bản 2 hỗ trợ một số tùy chọn giúp sinh ra source maps.

  • --source-map - tên file xuất ra source map.
  • --source-map-root - (tùy chọn) điền giá trị cho thuộc tính sourceRoot trong map file.
  • --source-map-url - (tùy chọn) đường dẫn đến source map trên server của bạn. Giá trị này sẽ được sử dụng trong comment được thêm vào file đã được tối ưu hóa. //# sourceMappingURL=/path/to/script.js.map
  • --in-source-map - (tùy chọn) source map đầu vào. Tùy chọn này được dùng nếu bạn nén các file JavaScript đã được sinh từ các file nguồn khác. Ví dụ như các thư viện JavaScript.
  • --prefix hoặc -p - (tùy chọn) Loại bỏ n thư mục trong đường dẫn ở thuộc tính sources. Ví dụ, -p 3 sẽ loại bỏ 3 thư mục đầu tiên trong đường dẫn, từ one/two/three/file.js sẽ trở thành file.js. Dùng -p relative sẽ để UglifyJS tự xác định đường dẫn tương đối giữa source map và các file gốc cho bạn.

Dưới đây là một lệnh ví dụ sử dụng một số tùy chọn phía trên.

uglifyjs [input files] -o script.min.js --source-map script.js.map --source-map-root http://example.com/js -c -m

Chú ý: nếu bạn dùng plugin grunt-contrib-uglify của Grunt, hãy xem tài liệu để chỉ định các tùy chọn này trong Gruntfile của bạn.


Cũng có các tiện ích khác hỗ trợ cho việc sinh source maps. Dưới đây là danh sách của một số tiện ích đó.

Source maps trong Chrome Dev Tools

Tab Sources trong Chrome Dev Tools

Nếu bạn đã cài đặt đúng source maps, bạn sẽ thấy các file JavaScript gốc được liệt kê ở cột file trong tab Source

Xem mã HTML của trang của bạn sẽ cho thấy chỉ có file JavaScript nén được tham chiếu đến. Dev tools sẽ tải source map cho bạn và nạp các file gốc.

Demo

Source maps trong Firefox Developer Tools

Tab Debugger trong Firefox Developer Tools

Người dùng Firefox sẽ thấy các file gốc riêng biệt trong tab Debugger của developer tools. Dev tool nhận thấy có source map và nạp các file gốc.

Nếu bạn muốn xem phiên bản được nén, nhấn vào biểu tượng bánh răng ở góc trên bên phải của tab và bỏ chọn Show original sources

Demo

Lời cuối

Sử dụng source map cho phép lập trình viên duy trì một môi trường debug thuận tiện, trong khi tối ưu hiệu năng trang web của họ.

Trong bài viết này bạn đã biết được cách source map hoạt động và cách sinh source map bằng UglifyJS. Nếu bạn từng bàn giao một website với asset được nén (bạn nên làm vậy), sẽ rất đáng để tích hợp source map vào trong luồng làm việc của mình.