it-swarm-vi.com

Tại sao JavaScript không được biên dịch sang mã byte trước khi gửi qua mạng?

Bạn thường thấy rằng JavaScript thực sự đang được vận chuyển qua web với tất cả những thứ vô dụng không cần phải ở đó - Nhận xét, đặc biệt là những người có giấy phép, thụt lề ( '\ t' , '\ n' ), v.v ... Cho đủ thời gian, nó có thể sẽ lãng phí terabyte dữ liệu trên toàn thế giới! Liệu một mã byte JavaScript sẽ gây ra một vấn đề lớn hơn hay chưa ai nghĩ đến điều này?

155
Vivek Yadav

Tại sao JavaScript không được biên dịch sang mã byte trước khi gửi qua mạng?

Bối cảnh: Tôi đã tham gia ủy ban kỹ thuật ECMAScript vào cuối những năm 1990 và là một trong những người triển khai công cụ JScript của Microsoft.

Hãy để tôi bắt đầu bằng cách nói những gì tôi luôn nói khi đối mặt với "tại sao không?" câu hỏi: các nhà thiết kế ngôn ngữ không bắt buộc phải đưa ra lý do chính đáng tại sao họ không chi hàng trăm triệu đô la của người khác cho một tính năng mà ai đó tình cờ thích. Thay vào đó, người đưa ra tính năng được yêu cầu đưa ra lý do chính đáng tại sao đó là cách tốt nhất để sử dụng thời gian, công sức và tiền bạc đó. Bạn đã đưa ra một đối số không có số nào được đính kèm với nó rằng mã byte sẽ là một khoản tiết kiệm chi phí về mặt băng thông. Tôi sẽ khuyến khích bạn tăng số lượng thực tế và so sánh với chi phí tạo ra một ngôn ngữ khác; những chi phí đó là đáng kể. Hãy nhớ trong phân tích của bạn rằng "thực hiện" là một trong những chi phí nhỏ nhất. Ngoài ra trong phân tích của bạn bao gồm ai tiết kiệm tiền so với ai chi tiêu tiền, và bạn sẽ thấy rằng những người tiêu tiền không phải là những người tiết kiệm tiền; vấn đề ưu đãi.

Điều đó nói rằng, đây là một trong những "hợp lý hơn" tại sao không? câu hỏi bởi vì đó là một tính năng chúng tôi xem xét và từ chối vì lý do.

Chúng tôi đã xem xét một kế hoạch như vậy, cả trong Microsoft và ở cấp độ TC; do JScript đã được triển khai dưới dạng biên dịch sang ngôn ngữ mã nguyên tắc được thiết kế tốt, nguyên tắc, nên chúng tôi sẽ đề xuất nó như một tiêu chuẩn và chúng tôi đã xem xét làm như vậy.

Chúng tôi quyết định không, vì nhiều lý do bao gồm:

  • Chúa ơi, thật khó để chuẩn hóa JavaScript. Mọi người và con chó của họ sẽ có ý kiến ​​về các đặc điểm lý tưởng của ngôn ngữ mã byte là gì, và nó sẽ là nhiều năm đi xe đạp. Không ai thực sự muốn đến đó.
  • Đó là một giải pháp đắt tiền không có vấn đề tốn kém liên quan. Không có lý do gì để cho rằng một ngôn ngữ mã byte sẽ hiệu quả hơn về kích thước hoặc tốc độ. JavaScript đã giảm thiểu hợp lý tốt và có khả năng nén cao.
  • Nó sẽ tạo ra một khối lượng công việc khổng lồ cho các nhà cung cấp trình duyệt, những người đã bị làm phiền bởi chi phí sản xuất một triển khai JS tuân thủ, hiệu quả.
  • Tạo một triển khai JS an toàn chống lại các cuộc tấn công của các tác nhân xấu là đủ khó; chúng ta nên tăng gấp đôi diện tích bề mặt có sẵn để tấn công? Chắc là không.
  • Các tiêu chuẩn là một trở ngại cho sự đổi mới. Nếu chúng tôi phát hiện ra rằng một thay đổi nhỏ đối với ngôn ngữ mã byte của chúng tôi sẽ tạo ra sự khác biệt lớn trong một số kịch bản người dùng trước đây không lường trước hoặc không quan trọng, chúng tôi có thể tự do thực hiện điều đó thay đổi. Nếu đó là một tiêu chuẩn, chúng tôi sẽ không được tự do tạo ra lợi ích người dùng đó.

Nhưng phân tích đó giả định rằng lý do để thực hiện tính năng này là hiệu suất. Thật thú vị, các yêu cầu của khách hàng có động lực xem xét tính năng này trở lại trong những năm 1990 không chủ yếu là về hiệu suất.

Tại sao không? Những năm 1990 là thời điểm rất khác biệt đối với JS so với ngày nay; kịch bản chủ yếu là nhỏ. Quan niệm rằng một ngày nào đó sẽ có những khuôn khổ với hàng trăm ngàn đường thậm chí không gần với radar của chúng ta. Tải xuống và phân tích cú pháp JS là một phần rất nhỏ thời gian để tải xuống và phân tích cú pháp HTML.

Cũng không phải là động lực mở rộng cho các ngôn ngữ khác, mặc dù đó là mối quan tâm của Microsoft vì chúng tôi cũng có VBScript chạy trên trình duyệt, sử dụng ngôn ngữ mã byte rất giống nhau. (Được phát triển bởi cùng một nhóm và được tổng hợp từ cùng một nguồn và tất cả.)

Thay vào đó, kịch bản khách hàng chính để thúc đẩy mã byte trong trình duyệt là làm cho mã khó đọc, hiểu, dịch ngược, kỹ sư đảo ngược và giả mạo. Rằng ngôn ngữ mã byte hầu như không có công việc bổ sung nào để hiểu đối với bất kỳ kẻ tấn công nào có tài nguyên hợp lý là điểm chính chống lại việc này; chúng tôi không muốn tạo ra cảm giác an toàn sai lầm.

Về cơ bản có rất nhiều chi phí và một vài lợi ích quý giá, vì vậy nó đã không được thực hiện. Một cái gì đó đã thay đổi giữa năm 1998 và 2015 khiến WebAssugging có mức giá hợp lý để hưởng lợi; Những yếu tố đó là gì, tôi không biết. Bạn phải hỏi một chuyên gia về WebAssugging.

381
Eric Lippert

Xem nguồn

"Xem nguồn" đã bắt đầu và vẫn ở một mức độ nào đó, được coi là một tính năng quan trọng của web. Đó là cách các thế hệ nhà phát triển web học phát triển web và các cơ quan tiêu chuẩn có liên quan (ECMA TC39, W3C, WHATWG) vẫn rất coi trọng vấn đề này.

Giảm thiểu

Các tệp ECMAScript thường được "rút gọn" trước khi được triển khai. Điều này bao gồm xóa tất cả các nhận xét, tất cả khoảng trắng và đổi tên của tất cả các số nhận dạng càng ngắn càng tốt, cộng với một số tối ưu hóa cấp cao hơn như xóa mã chết.

Nén

Hỗ trợ nén tồn tại trong HTTP kể từ HTTP/1.0 (đầu năm 1996). ECMAScript là văn bản và văn bản nén thực sự tốt. Trên thực tế, ECMAScript là văn bản có rất nhiều dư thừa (rất nhiều lần xuất hiện của ;, {, }, (, ), ,, ., function, var, if, for, v.v.) và thuật toán nén phát triển mạnh về sự dư thừa. Vì vậy, lượng dữ liệu được truyền đi nhỏ hơn nhiều so với mức bạn thực hiện. Như một thử nghiệm, hãy thử nén tệp nguồn ECMAScript bằng một trong các thuật toán nén điển hình được sử dụng trên web (ví dụ: gzip hoặc defat) và so sánh với kích thước của mã byte được biên dịch của cùng một tệp.

Định dạng mã byte

Điều này dẫn chúng ta đến vấn đề tiếp theo: không có định dạng mã byte chuẩn hóa cho ECMAscript. Trong thực tế, một số triển khai thậm chí có thể không sử dụng mã byte! Ví dụ, trong vài năm đầu tiên, V8 đã biên dịch ECMAScript thẳng sang mã máy gốc, không có bước mã byte ở giữa. Chakra, SquirrelFish Extreme và SpiderMonkey đều sử dụng mã byte, nhưng chúng sử dụng mã byte khác nhau. dyn.js, TruffleJS, Nashorn và Rhine không sử dụng mã byte dành riêng cho ECMAScript, chúng biên dịch thành mã byte JVML. Tương tự như vậy, IronJS biên dịch thành mã byte CLI CIL.

Bây giờ, bạn có thể nói: tại sao không xác định một định dạng mã byte chuẩn hóa cho ECMAScript? Các vấn đề với điều này là hai lần:

  1. Một định dạng mã byte ràng buộc thiết kế của công cụ thực thi. Ví dụ, hãy xem các JVM: Các JVM tương tự nhau hơn nhiều so với các công cụ ECMAScript. Cá nhân, tôi tin rằng "cuộc đua hiệu suất" vào cuối những năm 2000/đầu những năm 2010 sẽ không thể thực hiện được nếu không có phạm vi thử nghiệm rộng rãi mà thiếu định dạng mã byte chuẩn hóa.

  2. Không chỉ khó để khiến tất cả các nhà cung cấp công cụ ECMAScript đồng ý về định dạng mã byte được tiêu chuẩn hóa phổ biến, mà hãy xem xét điều này: không có ý nghĩa gì khi chỉ thêm định dạng mã byte cho ECMAScript cho trình duyệt. Nếu bạn thực hiện định dạng mã byte thông dụng, sẽ rất tuyệt nếu được hỗ trợ ActionScript, VBScript, Python, Ruby, Perl, Lua, PHP, v.v. tốt. Nhưng bây giờ bạn có cùng một vấn đề như ở # 1, ngoại trừ tăng theo cấp số nhân: không chỉ tất cả các nhà cung cấp công cụ ECMAScript cần phải đồng ý về định dạng mã byte thông thường, bạn cũng phải lấy PHP, Perl, Ruby, Python, Lua, v.v. cộng đồng cũng đồng ý!

Bộ nhớ đệm

Các thư viện được sử dụng rộng rãi được biết đến được lưu trữ tại các URI chính tắc, nơi chúng có thể được tham chiếu từ nhiều trang web. Do đó, chúng chỉ cần được tải xuống một lần và có thể được lưu trữ phía máy khách.

CDN

Nhiều thư viện sử dụng CDN, vì vậy chúng thực sự được phục vụ từ một địa điểm gần với người dùng.

Wasm/asm.js

WebAssugging (Wasm) là định dạng hướng dẫn nhị phân nhỏ gọn hiện đang được W3C chuẩn hóa và đã được chuyển trong Firefox, Chrome, Safari và Edge. Tuy nhiên, nó không được thiết kế dưới dạng định dạng mã byte cho ECMAScript, mà nó được thiết kế dưới dạng mã máy di động cấp thấp và mục tiêu biên dịch cho các ngôn ngữ như C, C++ và Rust.

Trước Wasm, đã có asm.js, có các mục tiêu tương tự, nhưng nó được thiết kế dưới dạng tập hợp cú pháp và ngữ nghĩa của ECMAScript, vì vậy bạn có thể chạy nó không được sửa đổi trong một công cụ không nhận biết asm.js và nó sẽ hoạt động, chỉ chậm hơn nhiều.

114
Jörg W Mittag

JavaScript được phát minh bởi Netscape. Mục tiêu thiết kế là làm cho các trang web tương tác thông qua một ngôn ngữ kịch bản nhúng. Ban đầu, nó không dành cho ứng dụng phức tạp - những thứ phức tạp được cho là được viết là Java applet hoặc plugin và JavaScript được định vị là mã "keo" đơn giản có thể kết nối các phần tử HTML với = Java applet và các trình cắm thêm tập lệnh khác.

JavaScript được thiết kế để được nhúng trực tiếp vào HTML, như <input type="button" onclick="alert('hello world')">. Ngày nay, người ta không thích nhúng JavaScript vào HTML, nhưng vào thời đó, đây là cách tiêu chuẩn để kết nối các trình xử lý sự kiện. Với trường hợp sử dụng này, JavaScript về cơ bản phải dựa trên văn bản.

Ngoài ra còn có các phương tiện để tạo HTML bằng JavaScript, như:

<script>
  document.write("<input type=\"button\" onclick=\"alert('hello world')\">"
</script>

Một lần nữa, điều này về cơ bản đòi hỏi JavaScript phải là định dạng văn bản để có ích.

Hơn nữa, một định dạng văn bản là nhiề dễ dàng hơn cho các nhà phát triển thông thường, vì bạn không cần môi trường phát triển để biên dịch nó thành mã byte. Bạn chỉ cần gõ văn bản và tải lại trình duyệt để xem nó chạy. Vào thời điểm JavaScript được giới thiệu, các trình soạn thảo HTML chuyên dụng hầu như không tồn tại. Mọi người đã viết các trang web trong notepad. Không có thứ gọi là xây dựng đường ống cho các trang web.

Nhược điểm mà bạn đề cập không thực sự được xem xét tại thời điểm đó. Vì nó được thiết kế cho các tập lệnh nhỏ, nên phần trên của định dạng văn bản là hoàn toàn không đáng kể.

18
JacquesB

Việc sử dụng dữ liệu có thể không thực sự là vấn đề.

Để trả lời cho giả định trong cơ thể (vì tuyệt vời phản hồi của Eric Lippert dường như có các câu hỏi thực tế được bảo hiểm khá tốt):

Cho dù bạn đang nói về giới hạn dữ liệu hoặc băng thông, Google-Fu của tôi đã không thể khai quật được bất kỳ nghiên cứu nào cho thấy Javascript thực sự là "lãng phí terabyte dữ liệu" (bất kể điều đó có nghĩa là gì).

Đối với phần còn lại của câu hỏi của bạn, trong nhiều điều, sẽ ít hữu ích hơn khi hỏi "vấn đề này sẽ gây ra vấn đề gì?" đầu tiên là hỏi "điều này sẽ tạo ra lợi ích gì?".

1
sp88