Bản đồ nguồn là một công cụ quan trọng trong quá trình phát triển web hiện đại, giúp gỡ lỗi dễ dàng hơn đáng kể. Trang này khám phá các kiến thức cơ bản về bản đồ nguồn, cách tạo bản đồ nguồn và cách bản đồ nguồn cải thiện trải nghiệm gỡ lỗi.
Nhu cầu về bản đồ nguồn
Các ứng dụng web ban đầu được xây dựng với độ phức tạp thấp. Các nhà phát triển đã triển khai trực tiếp các tệp HTML, CSS và JavaScript lên web.
Các ứng dụng web hiện đại và phức tạp hơn có thể cần nhiều công cụ trong quy trình phát triển. Ví dụ:
- Ngôn ngữ tạo mẫu và trình xử lý trước HTML: Pug, Nunjucks, Markdown.
- Trình xử lý trước CSS: SCSS, LESS, PostCSS.
- Khung JavaScript: Angular, React, Vue, Svelte.
- Khung meta JavaScript: Next.js, Nuxt, Astro.
- Ngôn ngữ lập trình cấp cao: TypeScript, Dart, CoffeeScript.
Các công cụ này yêu cầu một quy trình xây dựng để biên dịch mã của bạn thành HTML, JavaScript và CSS tiêu chuẩn mà trình duyệt có thể hiểu được. Một phương pháp phổ biến khác là tối ưu hoá hiệu suất bằng cách rút gọn và kết hợp các tệp này, sử dụng một công cụ như Terser.
Ví dụ: bằng cách sử dụng các công cụ xây dựng, chúng ta có thể biên dịch và nén tệp TypeScript sau thành một dòng JavaScript. Bạn có thể tự mình dùng thử trong bản minh hoạ này trên GitHub.
/* A TypeScript demo: example.ts */
document.querySelector('button')?.addEventListener('click', () => {
const num: number = Math.floor(Math.random() * 101);
const greet: string = 'Hello';
(document.querySelector('p') as HTMLParagraphElement).innerText = `${greet}, you are no. ${num}!`;
console.log(num);
});
Phiên bản nén sẽ là:
/* A compressed JavaScript version of the TypeScript demo: example.min.js */
document.querySelector("button")?.addEventListener("click",(()=>{const e=Math.floor(101*Math.random());document.querySelector("p").innerText=`Hello, you are no. ${e}!`,console.log(e)}));
Tuy nhiên, việc nén mã có thể khiến việc gỡ lỗi trở nên khó khăn hơn. Bản đồ nguồn có thể loại bỏ vấn đề này: bằng cách liên kết mã đã biên dịch của bạn trở lại mã ban đầu, bản đồ nguồn có thể giúp bạn nhanh chóng tìm thấy nguồn gốc của lỗi.
Tạo bản đồ nguồn
Bản đồ nguồn là các tệp có tên kết thúc bằng .map
(ví dụ: example.min.js.map
và styles.css.map
). Hầu hết các công cụ xây dựng đều có thể tạo bản đồ nguồn, bao gồm Vite, webpack, Rollup, Parcel và esbuild.
Một số công cụ có bản đồ nguồn theo mặc định. Các loại khác có thể cần thêm cấu hình để tạo:
/* Example configuration: vite.config.js */
/* https://vitejs.dev/config/ */
export default defineConfig({
build: {
sourcemap: true, // enable production source maps
},
css: {
devSourcemap: true // enable CSS source maps during development
}
})
Tìm hiểu về bản đồ nguồn
Để hỗ trợ gỡ lỗi, các tệp bản đồ nguồn này chứa thông tin thiết yếu về cách mã đã biên dịch liên kết với mã gốc. Dưới đây là ví dụ về bản đồ nguồn:
{
"mappings": "AAAAA,SAASC,cAAc,WAAWC, ...",
"sources": ["src/script.ts"],
"sourcesContent": ["document.querySelector('button')..."],
"names": ["document","querySelector", ...],
"version": 3,
"file": "example.min.js.map"
}
Để hiểu rõ từng trường trong số này, bạn có thể đọc thông số kỹ thuật của bản đồ nguồn hoặc Cấu trúc của bản đồ nguồn.
Phần quan trọng nhất của bản đồ nguồn là trường mappings
. Tệp này sử dụng chuỗi mã hoá VLQ cơ sở 64 để liên kết các dòng và vị trí trong tệp đã biên dịch với tệp gốc tương ứng. Bạn có thể xem mối liên kết này bằng cách sử dụng trình trực quan hoá bản đồ nguồn như source-map-visualization hoặc Source Map Visualization.
Cột đã tạo ở bên trái cho thấy nội dung đã nén và cột gốc cho thấy nguồn gốc.
Trình trực quan hoá sẽ mã hoá màu cho từng dòng trong cột gốc bằng mã tương ứng trong cột được tạo.
Phần mappings (mối liên kết) cho thấy các mối liên kết đã giải mã của mã. Ví dụ: mục nhập 65 -> 2:2
có nghĩa là:
- Mã đã tạo: Từ
const
bắt đầu ở vị trí 65 trong nội dung nén. - Mã gốc: Từ
const
bắt đầu ở dòng 2 và cột 2 trong nội dung gốc.
Điều này cho phép nhà phát triển nhanh chóng xác định mối quan hệ giữa mã đã rút gọn và mã gốc, giúp quá trình gỡ lỗi diễn ra suôn sẻ hơn.
Các công cụ dành cho nhà phát triển trình duyệt áp dụng các bản đồ nguồn này để giúp bạn nhanh chóng xác định các vấn đề gỡ lỗi trong trình duyệt.
Tiện ích bản đồ nguồn
Bản đồ nguồn hỗ trợ các trường phần mở rộng tuỳ chỉnh bắt đầu bằng tiền tố x_
. Một ví dụ là trường tiện ích x_google_ignoreList
do Chrome DevTools đề xuất. Hãy xem x_google_ignoreList để tìm hiểu thêm về cách các tiện ích này giúp bạn tập trung vào mã của mình.
Nhược điểm của bản đồ nguồn
Rất tiếc, không phải lúc nào mối liên kết nguồn cũng hoàn chỉnh như bạn cần.
Trong ví dụ đầu tiên, biến greet
đã được tối ưu hoá trong quá trình tạo bản dựng, mặc dù giá trị của biến này được nhúng trực tiếp vào đầu ra chuỗi cuối cùng.
Trong trường hợp này, khi bạn gỡ lỗi mã, các công cụ dành cho nhà phát triển có thể không thể suy luận và hiển thị giá trị thực tế. Loại lỗi này có thể khiến việc giám sát và phân tích mã trở nên khó khăn hơn.
Đây là vấn đề cần được giải quyết trong quá trình thiết kế bản đồ nguồn. Một giải pháp tiềm năng là đưa thông tin phạm vi vào bản đồ nguồn theo cách tương tự như các ngôn ngữ lập trình khác làm với thông tin gỡ lỗi.
Tuy nhiên, điều này đòi hỏi toàn bộ hệ sinh thái phải phối hợp với nhau để cải thiện việc triển khai và đặc tả bản đồ nguồn. Để theo dõi quá trình cải thiện khả năng gỡ lỗi liên tục bằng bản đồ nguồn, hãy tham khảo đề xuất về Bản đồ nguồn phiên bản 4 trên GitHub.