Sự phình to của JavaScript năm 2024
(tonsky.me)- Khi việc các trang web tải xuống JavaScript chưa nén lớn hơn rất nhiều so với nội dung thực tế trở nên phổ biến, gánh nặng cho trình duyệt tăng lên từ các trang landing đơn giản cho tới ứng dụng phục vụ công việc
- Phép đo được thực hiện trên Firefox trên macOS, tắt tiện ích mở rộng và cache, chỉ tính JavaScript, nhằm tập trung vào chi phí thực thi mã, loại trừ hình ảnh, video và style
- Wikipedia chỉ 0,2MB, nhưng ngay cả các trang đơn giản cũng tăng lên từ vài MB đến hai chữ số MB, như Linear 3MB, Zoom và Vercel 6MB, GitLab 13MB
- Trong nhóm ứng dụng, Gmail 20MB và FastMail 2MB chênh nhau 10 lần; lượng mã của các công cụ chat và làm việc đặc biệt lớn, như Jira khoảng 50MB và Slack 55MB
- Vì JavaScript sau khi tải xuống vẫn tạo ra chi phí phân tích cú pháp, giữ trong bộ nhớ và thực thi, cấu trúc cần các bundle mã khổng lồ chỉ để render nội dung nhỏ gây áp lực trực tiếp lên hiệu năng và pin
Phương pháp đo và tiêu chí so sánh
- Môi trường đo là Firefox trên macOS, với giả định rằng nhìn chung các trình duyệt khác cũng sẽ tương tự
- Điều kiện như sau
- Chế độ thường, không phải chế độ ẩn danh
- Tắt tất cả tiện ích mở rộng
- Chỉ đo JavaScript
- Tính theo kích thước chưa nén
- Bật Service Worker
- Cold load với cache bị vô hiệu hóa
- Nội dung bị loại khỏi đối tượng so sánh vì khác biệt giữa các website rất lớn
- Video của YouTube và tin nhắn văn bản của Slack vốn dĩ có kích thước khác nhau
- JavaScript được dùng như một chỉ số chung để so sánh độ phức tạp của tương tác
- Điểm cốt lõi là khối lượng công việc mà trình duyệt phải gánh để phân tích cú pháp và thực thi mã
- Làm mốc tham chiếu, chính blog tonsky.me được đo ở mức 0,004MB
Trang landing và nội dung tĩnh
- Trong ví dụ về các trang thông thường có một chút tương tác, Wikipedia ở mức khoảng 0,2MB
- Các trang landing nặng hơn như sau
- Linear: 3MB
- Zoom: 6MB
- Vercel: 6MB
- GitLab: 13MB
- Các con số trên là kích thước chỉ của mã JavaScript, không bao gồm hình ảnh, video và style
- Ngay cả các website hiển thị văn bản tĩnh cũng tải xuống vài MB JavaScript
- Medium: 3MB
- Substack: 4MB
- Quora: 4,5MB
- Pinterest: 10MB
- Patreon: 11MB
- Có những trường hợp dùng bundle JavaScript lớn cho tác vụ hiển thị nội dung vốn có vẻ có thể làm bằng trang tĩnh
Tìm kiếm và ứng dụng tương tác đơn giản
- Các ứng dụng tập trung vào tìm kiếm chủ yếu gồm nhập truy vấn và hiển thị danh sách kết quả, nhưng kích thước JavaScript không hề nhỏ
- StackOverflow: 3,5MB
- NPM: 4MB
- Airbnb: 7MB
- Booking.com: 12MB
- Google Search được đo ở mức 9MB dù giao diện chủ yếu là ô nhập văn bản và danh sách liên kết
- Những dịch vụ có UI nhập liệu đơn giản cũng dùng vài MB JavaScript
- Google Translate: 2,5MB
- ChatGPT: 7MB
- Dù độ phức tạp của ChatGPT nằm ở phía server, trình duyệt vẫn tải về 7MB JavaScript
Dịch vụ media và email
- Kích thước JavaScript của các dịch vụ video như sau
- Loom: 7MB
- YouTube: 12MB
- Pornhub: 1,4MB
- Với dịch vụ âm thanh, SoundCloud và Spotify đều được đo ở mức khoảng 12MB
- Ở dịch vụ email, mức chênh lệch rất lớn
- Google Mail: 20MB
- FastMail: 2MB
- Trong cùng nhóm dịch vụ email, FastMail dùng JavaScript ít hơn 10 lần so với Google Mail
- Con số 20MB của Google Mail lớn đến mức có thể so sánh với các ứng dụng như Figma, vốn bao gồm render C++/OpenGL tùy biến
Công cụ năng suất và chỉnh sửa tài liệu
- Các ứng dụng năng suất cũng có lượng JavaScript lớn so với tác vụ đơn giản
- Todoist: 9MB
- Dropbox: 10MB
- 1Password: 13MB
- Trello: 13,5MB
- Discord: 21MB
- Dropbox dùng hơn 10MB cho các tác vụ như danh sách file trong thư mục, 1Password cho danh sách mật khẩu, Trello cho hiển thị thẻ
- Các dịch vụ chỉnh sửa tài liệu ở mức hai chữ số MB
- Google Docs: 13,5MB
- Notion: 16MB
- Chỉnh sửa tài liệu có những tính năng khó như di chuyển con trỏ và đồng bộ hóa, nhưng kích thước JavaScript của các dịch vụ được so sánh vẫn rất lớn
Mạng xã hội và các trường hợp cực lớn
- Mạng xã hội thường dùng khoảng 12MB JavaScript cho các tính năng như thích, feed và nhắn tin
- Twitter: 11MB
- Facebook: 12MB
- TikTok: 12,5MB
- Instagram: 16MB
- LinkedIn: 31MB
- LinkedIn bao gồm blog, nền tảng, tìm kiếm, nhắn tin và tính năng xã hội, được đo ở mức 31MB
- Các ví dụ web app rất lớn gần như thuộc một nhóm riêng
- Jira: gần 50MB
- Slack: 55MB
- Slack là ứng dụng chat xử lý danh sách người dùng, tin nhắn và reaction, nhưng tải xuống 55MB JavaScript
- react.dev ban đầu bắt đầu ở 2MB, nhưng có hiện tượng JavaScript tiếp tục tăng khi cuộn lặp lại
- Ví dụ, có thể làm tăng lên tới 100MB
- Theo cập nhật, trong trải nghiệm người dùng thông thường, trình soạn thảo mã nhúng được lưu vào cache sau lần tải đầu tiên nên sau đó không thấy lưu lượng mạng
- Tuy nhiên, khi cuộn, 100MB JavaScript vẫn có thể tiếp tục được phân tích cú pháp, đánh giá và khởi tạo
Ý nghĩa của 10MB mã
- Năm 2015, kích thước trang web trung bình đang tiến gần tới 2,5MB của bản shareware Doom 1
- Năm 2024, chỉ riêng JavaScript của Slack đã đạt 55MB, tương đương toàn bộ kích thước tài nguyên của Quake 1 gốc
- 10MB mã trông như mức thông thường, nhưng nếu giả định một dòng mã trung bình dài 65 ký tự thì tương đương khoảng 150.000 dòng
- Vì mã này đã được minify, tính theo mã nguồn gốc có thể là hơn 300.000 dòng
- Google Maps thường được xem là ví dụ tiêu biểu của SPA, nhưng được đo ở mức 4,5MB; so với chuẩn web app hiện đại, nó lại được xem là khá nhỏ
- Figma là một ứng dụng frontend phức tạp nên kích thước tải xuống JavaScript lớn là điều tự nhiên, nhưng Gmail tương đương Figma, LinkedIn lớn gấp 1,5 lần, còn Slack ở mức gấp 2,5 lần
Chi phí mà trình duyệt phải trả
- Vấn đề không dừng lại ở kích thước tải xuống
- JavaScript tạo ra chi phí liên tục vì trình duyệt phải phân tích cú pháp, giữ trong bộ nhớ và thực thi nó
- Nếu xét theo tiêu chí kích thước nội dung phải lớn hơn kích thước mã, thì cấu trúc cần JavaScript lớn gấp 1000 lần để render một bài blog 10K ký tự là quá mức
- Website được nhắc đến như ví dụ tốt có thể hoạt động đủ tốt chỉ với 0,1MB JavaScript
- Trong cùng môi trường web, GitLab được so sánh như một trường hợp cần 13MB, tức hơn khoảng 500.000 dòng JavaScript, để hiển thị một trang landing tĩnh
1 bình luận
Ý kiến trên Hacker News
Cứ so những thứ như 10MB, 12MB với Pornhub 1,4MB, nơi thật sự quan tâm đến hiệu năng, là thấy
Các trang khiêu dâm luôn là web high-tech đúng nghĩa ngoài đời thực, kỹ thuật cũng tốt, khác với các tập đoàn “tech” lớn nghe như trò đùa
Tôi hầu như không nhớ có lần nào họ làm hỏng UI/UX cơ bản, truyền tải nội dung hay thiết kế hợp lý
Chỉ vì trong các ứng dụng web thực thụ, tải lại trang là hành vi không mong muốn, mà đột nhiên mọi người có vẻ sợ việc website tải lại trang
Tôi đã làm với ứng dụng doanh nghiệp suốt 20 năm, từng thấy cả những hệ thống được tạo ra trước khi tôi sinh ra, và tôi nghĩ React là frontend tốt nhất để thay thế các UI client/server tệ hại trước đây trong những hệ thống đó
Angular/Vue v.v. cũng cùng bối cảnh. Nhưng với các trang web thông thường thì gần như không cần, trừ khi tương tác và cập nhật thời gian thực là cốt lõi của sản phẩm như Gmail, Facebook
Những nơi như Pornhub dùng PHP cũng đã đủ, và đa số website cũng vậy. Cứ nhìn việc vẫn còn nhiều người thích HN hay old.reddit.com, và tôi nghĩ cũng sẽ có nhiều người thích old.Facebook hơn Facebook mới đã chậm hơn
Như popup, popunder, gửi người dùng sang các trang tổng hợp tương tự bằng nội dung giả, mở trang đối tác thay vì nội dung, làm bẩn kết quả tìm kiếm
Khiêu dâm không phải là ngành dẫn dắt công nghệ nhiều như mọi người nói; truyền thuyết đô thị về Betamax và VHS cũng không đúng, và nói ngành này dẫn đầu đổi mới Internet cũng là phóng đại
Có vài bên tạo ra sản phẩm chất lượng cao, nhưng không đại diện cho toàn ngành. Có rất nhiều link farm, nội dung rác, site nhân bản, quảng cáo sai sự thật, thao túng kết quả tìm kiếm
Việc các trang hàng đầu hiện nay nhanh nhạy có vẻ là kết quả của cạnh tranh. Nếu UX tệ, khiêu dâm miễn phí có đầy rẫy nên người dùng sẽ chuyển ngay sang chỗ khác, vì vậy họ phải tối ưu để giữ chân người dùng
Các website khác có những động lực khác như cổ đông, nhà cung cấp nội dung, hợp đồng độc quyền, vị thế độc quyền, nên không cần tối ưu trải nghiệm người dùng đến mức đó
Họ dành vô số thời gian để tối ưu đủ thứ như truyền tải video, phát sóng trực tiếp (trước đây là Flash, giờ là WebRTC), kích thước trang, v.v.
Tôi thắc mắc vì sao lại nhìn vào dữ liệu trước khi nén. Một số trang được nêu làm ví dụ xấu sau khi nén cũng dễ dàng nhỏ hơn 1,5MB của GMaps
Với các ứng dụng động như Spotify hay GMail, nếu điều hướng sau khi tải trang nhanh thì tôi thấy ổn
Một thứ như Discord, mất vài giây để cập nhật lúc khởi động, còn tốt hơn GitLab bắt chờ tối đa 2 giây mỗi lần bấm
Tôi nghĩ ưu tiên cold start và render tĩnh ngày nay ở một số site lại làm hỏng trải nghiệm
Thử duyệt cây tệp trên GitHub xem, trên máy tôi phần đó nhanh nhạy hơn hẳn các phần khác của GitHub. Tình cờ là đây cũng là một trong rất ít phần không render tĩnh
Mỗi ngày tôi bấm qua hàng trăm trang GitHub; tôi muốn họ gửi một lần một lượng JavaScript khổng lồ rồi cache nhiều nhất có thể, thay vì bắt tôi tải lại toàn bộ footer chỉ để xem một pipeline
[1]: GMail và Spotify chỉ là ví dụ, thực tế tôi không dùng
Vấn đề này thường xuất hiện trong các cuộc thảo luận về khả năng tiếp cận, vì khoảng cách hiệu năng CPU giữa iOS và Android rất lớn, và nếu tính cả các thiết bị giá rẻ mà số đông dùng, có những máy Android mới bán ra hôm nay còn chậm hơn iPhone năm 2014
Nếu lập trình viên chỉ dùng iPhone đời mới hoặc Android flagship, họ rất dễ bỏ lỡ việc code phình to ảnh hưởng lớn thế nào đến người dùng trung bình
https://infrequently.org/2024/01/performance-inequality-gap-...
Cache có thể giảm chi phí điện năng và thời gian cho tải xuống, giải nén, nhưng không loại bỏ chi phí sử dụng thực tế
Theo kinh nghiệm cá nhân của tôi, JavaScript trước khi nén càng lớn thì khi di chuột, nhấn phím hay cuộn, CPU càng phải liên tục chạy nhiều mã hơn
Thà hy sinh một chút hiệu quả thời gian để đổi lấy hiệu quả năng lượng; ở chỗ nào có thể thay bằng CSS, tôi thích dạng tĩnh hơn các hiệu ứng đẹp mắt
Hoặc vấn đề thật sự lớn hơn có thể là các site tải thêm tệp cho nhiều thao tác khác ngoài việc bấm để chuyển URL sang trang khác. Đó là sự phình to ẩn và cũng rất tệ cho lưu trữ
Tôi không muốn JavaScript làm cho thanh địa chỉ vẫn giữ nguyên URL nhưng lại hiện một “trang” khác. Điều này cũng cực kỳ tệ cho lưu trữ
Một kinh nghiệm khác là JavaScript trước khi nén càng lớn thì khả năng phiên bản site được lưu trữ hoạt động đúng càng thấp
Tuần trước Internet của tôi chậm; khi bấm tệp trên website GitHub, nó cố tải bằng script rồi thất bại, khiến cây tệp đúng nghĩa là không dùng được
Nhưng nếu sao chép URL của tệp rồi dán vào thanh địa chỉ trình duyệt thì lại tải đúng
Spotify có vấn đề lớn về kết nối mạng. Dù đã tải album xuống, chỉ cần mạng thay đổi là nó hoảng loạn hoàn toàn. Chế độ offline đơn thuần còn tốt hơn việc cứ cố duy trì trạng thái online
Khó mà nhìn vào đó để phán xét toàn bộ kiến trúc ấy; cũng giống như chỉ vào một SPA rất tệ rồi nói mọi SPA đều dở
Mọi phần mềm đều phản ánh hình dáng của tổ chức đã tạo ra nó
Phần lớn dữ liệu được truyền đi có khả năng không phải là JavaScript thực sự cần cho hoạt động của trang, mà là các công cụ phân tích và đủ loại script bên thứ ba
Chỉ nhóm “elephant” mới tương ứng với các module tải lười như React
Phần lớn những thứ này do đội marketing thúc đẩy, những người không biết hoặc không quan tâm đến vấn đề này
Nhiều khi các lập trình viên chỉ gắn Google Tag Manager hoặc một dịch vụ chèn script khác vào trang. Trong một số trường hợp, lập trình viên thậm chí không làm cả việc đó, mà proxy trong hạ tầng vận hành sửa đổi trang
Mối lo đáng kể hơn có thể là marketing có quyền kiểm soát sản phẩm đầu ra lớn hơn cả những người thực sự làm việc
Với các trang “elephant”, sự phình to nằm ở chính tổ chức. Đây không phải vấn đề của vài kẻ ngốc, mà là vấn đề của những kẻ ngốc đã được mở rộng quy mô
Ở công ty trước đây, một bộ phận phi kỹ thuật nắm Google Tag Manager, và chúng tôi phải liên tục giám sát đống rác được chèn vào các trang production
Tôi đã đấu tranh rất quyết liệt để loại bỏ nó
Google Search từng như vậy so với Yahoo, và Chrome khi ra mắt cũng như vậy so với IE/Firefox
Bản thân Chrome gần như không có UI, và đó chính là một tính năng
Tôi vừa trở về sau một chuyến roadtrip ở New Zealand, và ở rất nhiều vùng nông thôn tín hiệu di động rất yếu hoặc hoàn toàn không có
Khi cộng thêm roaming thì cảm giác còn chậm thêm một tầng nữa, nên dùng nhiều trang web thật sự rất khó chịu
Nếu có PM của Spotify ở đây, mong hãy xem lại UX offline. Offline là một trong những tính năng cốt lõi của gói Premium, nhưng khi thực sự dùng app ở trạng thái offline thì trải nghiệm ở nhiều mặt quá tệ
Nếu Spotify cho rằng có Internet, nó sẽ hỏi server toàn bộ nội dung của các menu ngữ cảnh, chờ phản hồi vài giây, rồi có lúc bỏ cuộc không hiện menu, có lúc quay về hành động vốn sẽ diễn ra ngay lập tức nếu đang ở chế độ offline
Tôi thật sự ghét trình phát này
Trong trạng thái trung gian khi độ trễ rất cao hoặc mất gói nhiều, thực tế nó nên hoạt động như offline, nhưng Spotify lại nghĩ là online
Tuy nhiên vấn đề này rất phổ biến, không chỉ Spotify thất bại, và có lẽ việc chọn ngưỡng đúng cũng khó
Tôi không hiểu vì sao Spotify lại bắt app chờ đến 30 giây để tải thứ gì đó khi không có tín hiệu. Tôi chỉ muốn tiếp tục nghe podcast đã tải xuống
Tôi tò mò không biết quyết định kỹ thuật nào đã khiến việc cân nhắc trọng số cho kịch bản này trở nên phức tạp đến vậy
Bài viết này hoàn toàn bỏ lỡ điểm rằng nó không mổ xẻ vì sao các file JavaScript trong ứng dụng web thực tế lại lớn đến thế
Ví dụ, nếu nhìn kỹ thì Google Translate không phải là một ứng dụng chỉ tương tác một lần rồi thôi. Nó có từ điển, gợi ý thay thế, chuyển tự, phát âm, nhiều phương thức nhập liệu, v.v.
Dù tính cả những điều đó thì 2.5MB vẫn là quá lớn, và tôi nghĩ một số tính năng tùy chọn có thể và nên được tải lười, nhưng bài hiện tại quá lười biếng nên không giúp ích nhiều cho một cuộc thảo luận sâu hơn
if data.transliteration show icon with audio embedthì cần bao nhiêu JavaScript chứ?Có thể vì ảnh lớn và nhiều nên hiểu được, nhưng vẫn hơi mỉa mai
Tôi hiểu hàm ý ở đây là “có quá nhiều JavaScript”, nhưng cũng cần nói đến việc trong số này có bao nhiêu là rác thuần túy để theo dõi
Tệ hơn nữa là một số thứ không được gắn với mã host mà được tải từ bên ngoài, làm tăng độ trễ và rủi ro bảo mật tiềm ẩn
Đó là công cụ cho phép marketer chèn bất kỳ thứ rác nào vào ứng dụng web mà không cần lập trình viên can thiệp
Quan hệ cũng hơi sứt mẻ, tôi cũng không thắng, và hiệu năng vẫn rất tệ
Thứ tiếp theo gây vấn đề hiệu năng là các thư viện nặng như bản đồ và biểu đồ, thường có thể giải quyết bằng tải lười thông minh
Những gì tôi từng trực tiếp gặp gồm: một tính năng rất nhỏ nhưng lại tải thư viện quét mã QR và thư viện bản đồ lúc khởi động; toàn bộ chuỗi quốc tế hóa được lấy bằng các request dạng thác nước lúc khởi động khiến mọi JS bị chặn trước khi chạy; Zendesk phá hỏng hoàn toàn hiệu năng trang nhưng vì là chỉ đạo từ cấp trên nên chỉ có thể gắn tải trễ cho nó
Tiếp theo là mã được thiết kế kém, gây ra quá nhiều phần tử DOM, render lại hoặc request dạng thác nước
Cuối cùng mới đến kích thước mã ở cấp ứng dụng; điều này cũng có thể sửa bằng tải lười, nhưng thường không cần thiết cho đến khi ứng dụng trở nên rất khổng lồ
Ví dụ, trang landing của GitLab từ 13MB giảm xuống “chỉ còn” 6MB khi chặn các script theo dõi
Bộ phận marketing lúc nào cũng sẽ làm mức độ phình to của phần mềm tăng gấp đôi
Nội dung so sánh các trang phổ biến tải bao nhiêu JavaScript khi cold load. Các điểm chính như sau
PornHub tải ít JS hơn khoảng 10 lần so với YouTube (1,4MB so với 12MB)
Gmail có footprint lớn đến mức khó hiểu (20MB). Fastmail nhẹ hơn 10 lần, chỉ 2MB, còn Figma dù là ứng dụng phức tạp hơn nhưng cũng khoảng 20MB tương tự
Jira lên tới 58MB, thật khủng khiếp
Jira có lẽ sau khi được tải xuống một lần sẽ được load cục bộ như ứng dụng offline cho đến lần cập nhật tiếp theo
Pornhub rất có khả năng chạy trong chế độ ẩn danh nên cache không giúp được gì
Jira cũng kinh khủng và chậm
Tất cả các trang của https://wordsandbuttons.online/ dù có animation và tương tác vẫn dưới 64KB
Ví dụ trang này https://wordsandbuttons.online/trippy_polynomials_in_arctang... là 51KB
Code cũng hoàn toàn không được viết tiết kiệm. 80% là copy-paste hơi khác nhau, và cũng không có nỗ lực rút gọn khôn khéo nào. Tất cả đều là vanilla JS cũ, không nén, không loại bỏ khoảng trắng
Mở bằng “View page source” thì code vẫn hoàn toàn đọc được
Bí quyết là chính sách 0 dependency. Không có bên thứ ba, cũng không có dependency nội bộ. Mọi code cần thiết đều được nhận cùng với file HTML
Nghịch lý là về lâu dài, copy-paste không phải nguyên nhân gây phình to mà là biện pháp ngăn chặn
Trên mobile, phần sát mép đúng nghĩa là không nhìn thấy
Bản thân dependency không phải nguyên nhân mà là triệu chứng. Vì website và các công ty không còn động lực giảm bớt sự phình to nữa, nên các dependency trùng lặp hầu như không được dọn dẹp
Nhớ đến bài The Website Obesity Crisis năm 2015 [1]. Từ đó đến nay [2] tình hình còn tệ hơn, và đã gần 10 năm trôi qua
Liệu có ngớ ngẩn không khi nói rằng 10 năm nữa, việc duyệt web bằng PC khoảng đời 2015 sẽ trở nên bất khả thi? Nếu không có gì thay đổi thì có vẻ là vậy
Ngay cả một chiếc MacBook cũ đời 2013 chạy Firefox mới nhất cũng không chịu nổi 23,98MB JavaScript của trang https://civitai.com, và bị đứng khoảng 30 giây khi cố render cái frontend web thảm họa đó
Đây không chỉ là vấn đề của web. Các ứng dụng all-in-one trên mobile cũng đã quá lớn đến mức điện thoại đời 2013 tương tự không load nổi, và một nửa trong số đó được viết trên nền web tech stack
Không hiểu vì sao các công ty có ngân sách lớn lại không đủ khả năng dùng ứng dụng native
[1] https://idlewords.com/talks/website_obesity.htm
[2] https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que...
Tình trạng của web thật rất buồn
Phần lớn người dùng kết nối cáp quang thậm chí không cảm nhận được web đã chậm đi đến mức nào
Nhưng nếu vẫn đang ở kết nối 2Mbps thì thật sự kinh khủng. Tôi đang ở tình cảnh đó, và rất khổ sở
Vì vậy việc không dùng trình chặn quảng cáo/theo dõi là điều không thể cân nhắc
Muốn xem bài test này khi bật Ublock Origin
Tôi nghĩ phần lớn code này là để theo dõi người dùng và quản lý quảng cáo
Tôi không hiểu vì sao lại nghĩ rằng dù đã có máy tính và tốc độ mạng tốt hơn, nhanh hơn, ta vẫn phải tiếp tục tập trung làm app và website nhỏ hơn
Nhờ định luật Moore, các lập trình viên đã có thể hy sinh tính tối ưu, đẩy nhiều thứ hơn và di chuyển nhanh hơn; rất nhiều trường hợp là như vậy