- Tổng hợp các vấn đề gặp phải sau khi nâng cấp ứng dụng web gần đây lên Svelte 5
- Đã xuất hiện các hành vi ngoài dự kiến do tính năng deep reactivity và vòng đời đã thay đổi
- Dù đã gắn bó rất lâu với Svelte 3/4, nhưng có lẽ sẽ không chọn Svelte cho các dự án mới trong tương lai
Nhu cầu về tốc độ
- Đội ngũ Svelte đã thử tối ưu hiệu năng thông qua deep reactivity, và đạt được hiệu năng tốt hơn
- Trước đây, Svelte vốn đã cung cấp hiệu năng nhanh nhờ quá trình biên dịch, và đây từng là điểm mạnh tạo khác biệt với các framework khác
- Điều này tạo ra một framework kém minh bạch, khiến việc debug khó khăn hơn, nhưng vẫn được cảm nhận là một sự đánh đổi chấp nhận được về mặt hiệu năng và năng suất
Nhu cầu về tốc độ
- Thay đổi trọng tâm mà đội ngũ Svelte theo đuổi trong Svelte 5 là “deep reactivity”, nhằm tăng hiệu năng thông qua khả năng phản ứng chi tiết hơn
- Ở các phiên bản Svelte trước, mục tiêu này chủ yếu được đạt tới nhờ trình biên dịch Svelte
- Việc có thể tái cấu trúc logic nội bộ mà không buộc lập trình viên phải trực tiếp học thêm khái niệm mới là điểm làm nổi bật sự độc đáo của Svelte
- Đồng thời, quá trình biên dịch này cũng làm framework trở nên kém minh bạch, khiến việc debug các vấn đề phức tạp trở nên khó khăn
- Đã có những lỗi khó xác định nguyên nhân do chính bug của compiler gây ra, và đôi khi chỉ có thể giải quyết bằng cách refactor toàn bộ component có vấn đề
- Dù vậy, vì đây vẫn được xem là một sự đánh đổi hợp lý về tốc độ và năng suất, nên tác giả đã chấp nhận cả sự bất tiện khi phải định kỳ khởi tạo lại dự án
Svelte không phải là Javascript
- Svelte 5 nhân đôi sự đánh đổi này
- Khác biệt cốt lõi là điểm cân bằng giữa trừu tượng hóa và hiệu năng đã vượt qua giai đoạn biên dịch để xâm nhập cả vào phần runtime
- Sử dụng proxy để hỗ trợ deep reactivity
- Trạng thái vòng đời component mang tính ngầm định (implicit)
- Hai thay đổi này cải thiện hiệu năng, đồng thời khiến API cho lập trình viên trông mượt mà hơn
- Có gì để ghét ở đây? Đáng tiếc là hai tính năng này là ví dụ điển hình của leaky abstraction
- Cuối cùng lại dẫn tới một môi trường phức tạp hơn cho lập trình viên
Proxy không phải là object
- Nhờ dùng Proxy, đội ngũ Svelte có thể vắt thêm một chút hiệu năng của framework mà không đòi hỏi lập trình viên phải làm thêm việc gì
- Ở những framework như React, khi truyền state qua nhiều component thì rất dễ phát sinh re-render không cần thiết, và Svelte đưa Proxy vào nhằm giảm điều đó
- Trình biên dịch Svelte trước đây vốn đã tránh được một số vấn đề có thể phát sinh trong quá trình so sánh virtual DOM, nhưng có vẻ họ cho rằng có thể cải thiện hiệu năng thêm nữa bằng Proxy
- Đội ngũ Svelte cũng nói rằng Proxy góp phần cải thiện trải nghiệm lập trình viên, với lập luận rằng “có thể tối đa hóa cả hiệu quả lẫn tính dễ sử dụng”
- Vấn đề là Svelte 5 trông có vẻ đơn giản hơn ở bề ngoài, nhưng thực tế lại thêm nhiều lớp trừu tượng hơn
- Ví dụ, khi dùng Proxy để phát hiện các method của mảng, sẽ có lợi thế là không cần viết
value = value như ở Svelte 4
- Ở Svelte 4, để kích hoạt reactivity, lập trình viên cần hiểu ở mức nào đó cách compiler hoạt động. Ngược lại, Svelte 5 tạo cảm giác như “có thể quên compiler đi”, nhưng thực tế không phải vậy
- Sự tiện lợi có được từ lớp trừu tượng mới đi kèm với việc số quy tắc mà lập trình viên phải biết để compiler hoạt động đúng ý cũng tăng lên
- Sau thời gian dài dùng Svelte, cá nhân tác giả dần chuyển sang dùng Svelte store nhiều hơn và ít dùng reactive declaration hơn
- Về cơ bản, Svelte store gần với khái niệm JavaScript hơn, cách gọi method
update cũng đơn giản, còn cú pháp $ chỉ là một lợi thế bổ sung
- Proxy, cũng giống như reactive declaration, gây ra vấn đề “nhìn có vẻ là một thứ, nhưng ở các ranh giới thực tế lại hoạt động khác đi”
- Lần đầu dùng Svelte 5 thì mọi thứ đều chạy tốt, nhưng khi cố lưu trạng thái Proxy vào IndexedDB thì phát sinh
DataCloneError
- Tệ hơn nữa, để chắc chắn một giá trị có phải Proxy hay không, phải thử structured clone bằng
try/catch, mà cách này lại tốn kém về hiệu năng
- Cuối cùng, người dùng buộc phải nhớ thứ gì là Proxy, và ở các ngữ cảnh bên ngoài không nhận diện được Proxy thì phải luôn dùng
$state.snapshot
- Kết quả là, trái với ý định ban đầu rằng “trừu tượng hóa sẽ tăng sự tiện lợi cho lập trình viên”, tình huống này lại buộc họ phải tuân theo nhiều quy tắc và quy trình phức tạp hơn
Component không phải là function
Kết luận
- Cái gì dễ dùng rõ ràng cũng hấp dẫn, nhưng như Rich Hickey từng nói, dễ không đồng nghĩa với đơn giản
- Cũng như Joel Spolsky từng nói, tác giả không thích những hành vi bất ngờ xảy ra ngoài dự tính
- Svelte từ trước đến nay đã thể hiện rất nhiều “phép màu”, nhưng ở phiên bản này, để dùng được những phép màu đó, số thứ phải ghi nhớ đã tăng lên đến mức gánh nặng lớn hơn lợi ích
- Mục đích của bài viết này không phải để chỉ trích đội ngũ Svelte; ngược lại, tác giả hiểu rằng vẫn có rất nhiều người ưa thích Svelte 5 (và React Hooks)
- Điều quan trọng là sự cân bằng giữa việc mang lại tiện lợi cho người dùng và việc để người dùng nắm được quyền chủ động
- Phần mềm thực sự tốt không dựa trên sự “khôn khéo”, mà dựa trên “sự thấu hiểu”
- Khi các công cụ AI tiếp tục phát triển, điều quan trọng là chọn những công cụ giúp tận dụng trí tuệ đã tích lũy và hỗ trợ hiểu sâu hơn, thay vì những công cụ khiến người dùng không biết mình đang làm gì
- Cảm ơn Rich Harris và cả đội vì quãng thời gian phát triển đầy thú vị. Mong rằng bài viết này sẽ trở thành một phản hồi không phải là thiếu chính xác
7 bình luận
proxygiúp người tạo ra nó thấy tiện hơn, nhưng người phải debug thì phát bực lên ấy chứ hahaDự án phụ có DX của solidjs là số một >m< / hạnh phúc
Tôi nghĩ chính vì có những lựa chọn thay thế như Svelte nên React/Next.js cũng đã có thể nhận được cú hích lớn. Về bản chất, Svelte là một ngôn ngữ, nên tôi cũng hy vọng nó sẽ chỉ ra thật rõ hướng đi mà một ngôn ngữ dùng để mô tả UI nên tiến tới.
Tôi sẽ dùng React.
Làm quá hóa dở
Tẩu hỏa nhập ma
Chồng chất thêm tầng lớp vô ích
Tôi nghĩ nó đã trở nên kỳ lạ khi chịu ảnh hưởng không ít từ React, đặc biệt là next.
+pagerất khó hiểu nếu nhìn vào mà không biết svelte, còn các rune như$state,$derivedthì có vẻ như đang đi theo React; tôi còn thấy thời dùng$:trước biến lại tốt hơn. Cú pháp kiểu cũ như{#each a in array} {/each}thì vẫn có thể chịu được, nhưng vẫn khá phiền. Nếu là cải thiện hiệu năng nhờ reactivity tùy chọn, tôi nghĩ solidjs là hướng đi tốt hơn nhiều. Vì dùng nguyênjsx, nên việc chuyển từ react sang cũng tương đối dễ hơn. Đến mức solidjs tương đối không được chú ý nhiều mới khiến tôi thấy khó hiểu.Có vẻ như Signals đang hướng tới giai đoạn Trough of disillusionment trong Gartner hype cycle 🤔 Khi các trường hợp sử dụng dần được định hình rõ hơn, có lẽ cách đánh giá cũng sẽ được cải thiện.
Ý kiến Hacker News
Lúc đầu tôi không mấy hứng thú với runes. Nhưng tôi đã đổi ý khi có thể đưa các thành phần phản ứng từ bên ngoài vào template
.sveltevà đóng gói tính phản ứng ở bên trong. Điều đó có nghĩa là bạn vẫn có thể viết các bài kiểm thử bằng vitest mà vẫn tận dụng được lợi ích của reactivity. Điều này thực sự rất mạnh và theo như tôi biết thì là khá độc nhất trong thế giới frontendTôi đang tích cực phát triển một ứng dụng SvelteKit đã được triển khai thương mại và muốn chia sẻ một vài suy nghĩ về trải nghiệm này
+page. Bạn có thể đặt file Svelte ở bất kỳ đâu mình muốn và nó vẫn được render trơn tru trong khi vẫn hưởng lợi từ framework hiện đạiThật tiếc khi EmberJS đã biến mất. API của nó khá ổn định trong suốt 10 năm qua. Trớ trêu thay, người đã viết ứng dụng EmberJS trong 10 năm qua có lẽ sẽ gặp ít khó khăn khi di chuyển hơn so với người làm cùng công việc bằng React, Svelte, Vue v.v.
Hai liên kết Github mà tác giả liệt kê ở đầu bài viết đều trỏ đến cùng một vấn đề, và vấn đề đó có cách giải quyết (dùng
$state.raw)Svelte 5 là kiểu <i>không phải JavaScript</i> theo cách <i>tệ nhất</i>. Nó không giải quyết được vấn đề của js, mà chỉ cung cấp những lớp trừu tượng bị rò rỉ cho một số vấn đề frontend. Tôi nghĩ Solid đi theo hướng tốt hơn Svelte, vì Solid không phụ thuộc vào một ngôn ngữ mới. Tuy nhiên, cũng có bản năng muốn tạo ra thứ gì đó không phải js vì js không lý tưởng. Elm là tiền thân của svelte. Nhưng tôi nghĩ chúng ta có thể tạo ra thứ tốt hơn...[0]
Tôi bắt đầu dùng Svelte 5 vì cực kỳ ghét store trong Svelte 4. Tôi đang dùng Sveltekit và Svelte 5 cho một dự án mới, và phải nói rằng... năng suất của React vẫn là vô đối, dù về mặt kỹ thuật Sveltekit và công nghệ Svelte tốt hơn
+page.server.tshoặc+page.sveltehay các biến thể của chúng, khiến việc tìm kiếm mã không hề dễ dàng. Công cụ của Svelte tồn tại tách biệt vớitscvà ESLint nên việc tích hợp vào CI và dùng trong quá trình phát triển khó hơnNói rằng Svelte không phải JavaScript chỉ vì hành vi bất ngờ khi truyền closure vào callback nghe có vẻ kỳ quặc. Một tiêu đề tốt hơn có lẽ là "Tôi ghét Svelte 5 vì nó khiến tôi bất ngờ"
Nếu bạn đang tìm một thư viện cho phép xây dựng component và ứng dụng bằng JavaScript thuần, hãy xem Lit: Lit
Muốn có trải nghiệm frontend hợp lý hơn? Hãy dùng JavaScript thuần, web components, htmx, Blazor