Cải thiện trải nghiệm gỡ lỗi web bằng bản đồ nguồn.
Hôm nay, chúng ta sẽ nói về bản đồ nguồn, 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 rất nhiều. Trong bài viết này, chúng ta sẽ khám phá thông tin cơ bản về bản đồ nguồn, cách tạo bản đồ nguồn và cách chúng cải thiện trải nghiệm gỡ lỗi.
Nhu cầu của bản đồ nguồn
Thuở xưa, chúng tôi đã xây dựng các ứng dụng web bằng HTML, CSS và JavaScript thuần tuý, đồng thời đã triển khai các tệp tương tự lên web.
Tuy nhiên, hiện nay chúng tôi đang xây dựng các ứng dụng web phức tạp hơn, nên quy trình phát triển của bạn có thể liên quan đến việc sử dụng nhiều công cụ khác nhau. Ví dụ:
- Các ngôn ngữ tạo mẫu và bộ tiền xử lý HTML: Pug, Nunjucks, Markdown.
- Bộ tiền xử lý CSS: SCSS, LESS, PostCSS.
- Khung JavaScript: Angular, React, Vue, Svelte.
- Các khung meta JavaScript: Next.js, Nuxt, Astro.
- Ngôn ngữ lập trình cấp cao: TypeScript, Dart, CoffeeScript.
- Và hơn thế nữa. Danh sách này có thể còn mãi!
Các công cụ này yêu cầu quy trình xây dựng để chuyển mã mã của bạn thành HTML, JavaScript và CSS chuẩn mà các trình duyệt có thể hiểu. Ngoài ra, để tối ưu hoá hiệu suất, một phương pháp phổ biến là nén (ví dụ: sử dụng Terser để thu nhỏ và huỷ bỏ JavaScript) và kết hợp các tệp này, giảm kích thước và nâng cao hiệu quả cho web.
Ví dụ: sử dụng công cụ bản dựng, chúng ta có thể chuyển mã và nén tệp TypeScript sau thành một dòng JavaScript. Bạn có thể xem bản minh hoạ trong kho lưu trữ GitHub của tôi.
/* 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, quá trình tối ưu hoá này có thể khiến việc gỡ lỗi trở nên khó khăn hơn. Mã nén chứa mọi thông tin trong một dòng và tên biến ngắn hơn có thể gây khó khăn cho việc xác định nguồn gốc của vấn đề. Đó là nơi bản đồ nguồn xuất hiện. Bản đồ này ánh xạ mã đã biên dịch trở lại mã gốc.
Đang 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 đồ này, chẳng hạn như Vite, webpack, Rollup, Parcel, esbuild, v.v.
Một số công cụ bao gồm bản đồ nguồn theo mặc định, trong khi một số khác có thể cần cấu hình bổ sung để tạo bản đồ nguồn.
/* 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 bản đồ nguồn
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 ánh xạ với mã gốc, cho phép nhà phát triển gỡ lỗi dễ dàng. Sau đâ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 này, bạn có thể đọc thông số kỹ thuật của bản đồ nguồn hoặc bài viết cổ điển này về cấu trúc của bản đồ nguồn.
Khía cạnh quan trọng nhất của bản đồ nguồn là trường mappings
. Hàm này sử dụng chuỗi được mã hoá VLQ cơ sở 64 để ánh xạ các đường và vị trí trong tệp đã biên dịch với tệp gốc tương ứng. Bạn có thể trực quan hoá 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-trực quan hoá và Hình ảnh hoá bản đồ nguồn.
Cột đã tạo ở bên trái hiển thị nội dung nén và cột gốc hiển thị nguồn gốc.
Màu của trình hiển thị hình ảnh mã hoá từng dòng trong cột gốc và mã tương ứng trong cột đã tạo.
Phần ánh xạ cho thấy các ánh xạ đã 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 từ dòng 2 và cột 2 trong nội dung gốc.
Bằng cách này, nhà phát triển có thể nhanh chóng xác định mối quan hệ giữa mã đã giảm thiểu và mã gốc, giúp quá trình gỡ lỗi diễn ra suôn sẻ hơn.
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 xác định các sự cố gỡ lỗi nhanh hơn, ngay trong trình duyệt.
Hình ảnh này cho thấy cách Công cụ cho nhà phát triển của trình duyệt áp dụng bản đồ nguồn và cho thấy mối liên kết giữa các tệp.
Tiện ích bản đồ nguồn
Bản đồ nguồn hỗ trợ các tiện ích. Tiện ích là các trường tuỳ chỉnh bắt đầu bằng quy ước đặt tên x_
. Một ví dụ là trường tiện ích x_google_ignoreList
do Công cụ của Chrome cho nhà phát triển đề xuất. 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ã.
Không hoàn hảo
Trong ví dụ của chúng tôi, biến greet
đã được tối ưu hoá trong quá trình xây dựng. Giá trị này được nhúng trực tiếp vào dữ liệu đầu ra của 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 suy luận được và hiển thị giá trị thực tế. Đây không chỉ là những thách thức đối với công cụ cho nhà phát triển của trình duyệt. Điều này cũng khiến việc theo dõi và phân tích mã trở nên khó khăn hơn.
Tất nhiên, đây là vấn đề có thể giải quyết được. Một trong những cách là đưa thông tin phạm vi vào bản đồ nguồn như các ngôn ngữ lập trình khác thực hiện 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 làm việc cùng nhau để cải thiện việc triển khai và đặc tả kỹ thuật bản đồ nguồn. Có một cuộc thảo luận đang diễn ra về việc cải thiện khả năng gỡ lỗi bằng bản đồ nguồn.
Chúng tôi mong muốn cải thiện bản đồ nguồn và giúp cho việc gỡ lỗi trở nên dễ dàng hơn nữa!