5 điểm bởi GN⁺ 2024-05-05 | 1 bình luận | Chia sẻ qua WhatsApp
  • Figma đã chuyển toàn bộ mã Skew sang TypeScript sau khi ngôn ngữ nội bộ Skew dùng cho rendering di động và trình xem prototype chạm tới giới hạn về onboarding, tích hợp và hệ sinh thái
  • Điều kiện tiên quyết cho quá trình chuyển đổi gồm việc hỗ trợ WebAssembly trên trình duyệt di động được mở rộng, thay thế engine C++ cho các đường đi cốt lõi, và sự phát triển của các nhóm prototyping và mobile
  • Quá trình migration diễn ra theo 3 giai đoạn: Write Skew, build SkewWrite Skew, build TypeScriptWrite TypeScript, build TypeScript, trong đó transpiler Skew-to-TypeScript giúp duy trì luồng phát triển
  • Trong quá trình chuyển đổi thực tế, nhiều vấn đề tương thích đã lộ ra như hiệu năng destructuring mảng, khác biệt về devirtualization, thứ tự khởi tạo, liên kết source map và việc thiếu conditional compilation
  • Cuối cùng, Figma đã có được codebase TypeScript vượt qua unit test và đạt hiệu năng tương tự Skew; bước tiếp theo là tích hợp mã nội bộ và bên ngoài, quản lý package và tận dụng hệ sinh thái TypeScript

Vì sao chuyển từ Skew sang TypeScript

  • Skew bắt đầu từ một side project ở giai đoạn đầu của Figma và đáp ứng nhu cầu tạo nhanh trình xem prototype hỗ trợ cả web lẫn mobile
  • Khi phát triển thành một ngôn ngữ biên dịch sang JavaScript, nó cung cấp tối ưu hóa nâng cao và thời gian biên dịch nhanh, nhưng chi phí bảo trì tăng dần khi mã tích lũy trong trình xem prototype
    • Nhân viên mới khó làm quen
    • Không dễ tích hợp với phần còn lại của codebase
    • Không có hệ sinh thái nhà phát triển bên ngoài Figma
  • Figma kỳ vọng việc chuyển sang TypeScript sẽ mở rộng tốc độ phát triển và phạm vi cộng tác
    • Đơn giản hóa tích hợp mã nội bộ và bên ngoài nhờ static import và quản lý package native
    • Tận dụng công cụ do cộng đồng nhà phát triển lớn xây dựng như linter, bundler và static analyzer
    • Sử dụng các tính năng JavaScript hiện đại như async/await cùng hệ thống kiểu linh hoạt hơn
    • Giảm rào cản onboarding cho lập trình viên mới và cho các nhóm khác tham gia

Những điều kiện khiến việc chuyển đổi chỉ mới khả thi gần đây

  • Khi Figma lần đầu xây dựng codebase mobile, trình duyệt di động chưa hỗ trợ WebAssembly, và cũng khó tải các bundle lớn với hiệu năng tốt
  • TypeScript khi đó vẫn còn ở giai đoạn đầu, nên Skew với static type và hệ thống kiểu chặt chẽ hơn là lựa chọn thực tế hơn vào thời điểm đó
  • Đến năm 2018, WebAssembly đã được hỗ trợ rộng rãi trên mobile, và theo thử nghiệm của Figma, đến năm 2020 hiệu năng mobile đã đạt mức đáng tin cậy
  • Thế mạnh ban đầu của Skew là các tối ưu hóa compiler truyền thống như constant folding và devirtualization, cùng các tối ưu hóa đặc thù web như sinh JavaScript dùng phép toán số nguyên thực sự
  • Benchmark năm 2020 cho thấy việc tải prototype Figma bằng TypeScript trên Safari có thể chậm gần gấp đôi, và do Safari là engine trình duyệt duy nhất được phép trên iOS nên đây là rào cản lớn cho việc chuyển đổi
    • Từ iOS 17.4, Apple mở các engine trình duyệt khác cho người dùng EU, nhưng với người dùng ở khu vực khác thì WebKit vẫn là engine duy nhất
  • Sau đó, nhiều thành phần cốt lõi của Skew engine được thay bằng các thành phần tương ứng trong C++ engine, làm giảm rủi ro hiệu năng khi chuyển sang TypeScript
    • Bao gồm những đường đi mã nóng nhất như file loading
    • Từ đó có thêm tự tin rằng tổn thất hiệu năng khi chuyển sang TypeScript là chấp nhận được
  • Khi các nhóm prototyping và mobile phát triển thành tổ chức lớn hơn, Figma có thể đầu tư nguồn lực vào migration tự động và cải thiện trải nghiệm lập trình viên

Chuyển đổi codebase theo 3 giai đoạn

  • Ở nguyên mẫu migration đầu tiên năm 2020, hiệu năng TypeScript chậm gần gấp đôi
  • Sau khi hỗ trợ WebAssembly và việc chuyển mobile engine sang C++ đã đủ chín muồi, Figma đã tận dụng Maker Week để chỉnh lại nguyên mẫu cũ và trình diễn một bản migration hoạt động, vượt qua toàn bộ test
  • Mục tiêu là chuyển toàn bộ codebase sang TypeScript, nhưng viết lại thủ công có thể làm chậm tốc độ phát triển và gây lỗi runtime hoặc suy giảm hiệu năng
  • Khác biệt ngữ nghĩa giữa Skew và TypeScript lớn hơn một lần chuyển đổi đơn giản giữa các biến thể “JavaScript có kiểu”
    • TypeScript chỉ khởi tạo namespace và class sau khi file được import
    • Nếu thứ tự import không như dự kiến thì có thể xảy ra lỗi runtime
    • Skew cho phép mọi symbol khả dụng ở runtime trên toàn bộ codebase ngay khi tải
  • Figma đã phát triển transpiler Skew-to-TypeScript dựa trên công việc Evan Wallace từng khởi đầu trước đó
  • Phase 1: Viết Skew, build Skew

    • Phát triển transpiler trong khi vẫn giữ nguyên quy trình build cũ
    • Check in mã TypeScript được sinh ra lên GitHub để lập trình viên có thể xem hình dạng của codebase mới
  • Phase 2: Viết Skew, build TypeScript

    • Sau khi tạo được bundle TypeScript vượt qua toàn bộ unit test, Figma dần rollout traffic production sang bản build từ codebase TypeScript
    • Lập trình viên vẫn tiếp tục viết Skew, còn transpiler chuyển mã Skew sang TypeScript và cập nhật mã TypeScript trên GitHub
    • Các lỗi kiểu trong mã sinh ra cũng tiếp tục được sửa
    • TypeScript vẫn có thể tạo bundle hợp lệ ngay cả khi còn lỗi kiểu
  • Phase 3: Viết TypeScript, build TypeScript

    • Sau khi toàn bộ người dùng đã chạy qua quy trình build TypeScript, Figma chuyển mã TypeScript thành nguồn chân lý duy nhất cho phát triển
    • Họ chọn thời điểm không có code merge để dừng quy trình sinh mã tự động và xóa mã Skew khỏi codebase
    • Tối thứ Sáu, họ merge việc bỏ sinh mã tự động và thay đổi các job CI sang chạy trực tiếp file TypeScript
    • Trong quá trình rollout dần, họ phát hiện nội bộ tính năng Smart Animate bị hỏng; nhờ cơ chế rollout theo gate, họ có thể tắt rollout, sửa lỗi rồi xem xét lại kế hoạch

Những vấn đề lộ ra từ transpiler

  • Compiler thường gồm frontend và backend
    • Frontend phân tích mã đầu vào, kiểm tra kiểu và cú pháp rồi chuyển sang biểu diễn trung gian (IR)
    • Backend chuyển IR sang ngôn ngữ khác
    • Backend của compiler Skew tạo ra JavaScript đã được obfuscate và minify
  • Transpiler là một dạng compiler đặc biệt có backend sinh ra mã mà con người có thể đọc được; Figma cần sinh TypeScript dễ đọc từ Skew IR
  • Bản triển khai ban đầu tương đối suôn sẻ vì lấy nhiều cảm hứng từ JavaScript backend của Skew, nhưng về sau xuất hiện nhiều vấn đề khó theo dõi và xử lý
  • Hiệu năng destructuring mảng

    • Khi điều tra chênh lệch hiệu năng offline giữa Skew và TypeScript trong prototype mẫu, Figma thấy TypeScript có frame rate thấp hơn
    • Nguyên nhân là array destructuring của JavaScript
    • Với thao tác như const [a, b] = function_that_returns_an_array(), JavaScript không truy cập mảng trực tiếp theo chỉ số mà tạo iterator để duyệt
    • Figma dùng cách này để lấy đối số từ từ khóa arguments của JavaScript, và trong một số test case cụ thể điều đó gây chậm
    • Khi sinh mã truy cập trực tiếp mảng arguments thay vì destructuring, độ trễ mỗi frame được cải thiện tới 25%
  • Tối ưu devirtualization của Skew

    • Compiler Skew thực hiện tối ưu devirtualization bằng cách trong một số điều kiện nhất định đưa hàm bên trong class ra ngoài thành hàm toàn cục
    • myObject.myFunc(a, b) có thể trở thành myFunc(myObject, a, b)
    • TypeScript không làm tối ưu hóa này
    • Lỗi Smart Animate xảy ra khi myObject là null
    • Lời gọi đã devirtualize vẫn chạy bình thường, nhưng lời gọi chưa devirtualize ném ra ngoại lệ truy cập null
    • Figma thêm logging vào tất cả hàm có thể tham gia devirtualization để tìm các điểm gọi có cùng vấn đề
    • Sau một thời gian ngắn bật logging, họ phân tích log production và sửa các điểm gọi lỗi
  • Khác biệt về thứ tự khởi tạo

    • Trong Skew, có thể khai báo biến, class, namespace và hàm ở bất kỳ đâu mà không cần quan tâm đến thứ tự
    • Trong TypeScript, thứ tự khởi tạo của biến toàn cục hoặc định nghĩa class là quan trọng
    • Nếu khởi tạo biến static của class trước khi định nghĩa class thì sẽ gây lỗi compile-time
    • Transpiler ban đầu không dùng namespace mà làm phẳng mọi hàm vào global scope để giữ hành vi gần giống Skew
    • Kết quả là mã khó đọc, nên sau đó Figma sửa transpiler để xuất TypeScript theo đúng thứ tự và thêm lại namespace để cải thiện khả năng đọc
    • Cuối cùng họ đã tạo được một transpiler có thể biên dịch ra mã TypeScript vượt qua unit test và đạt hiệu năng ngang Skew
    • Một số vấn đề nhỏ được xử lý bằng cách sửa thủ công trong mã nguồn Skew hoặc sửa sau khi đã chuyển sang TypeScript thay vì tiếp tục chỉnh transpiler

Duy trì trải nghiệm debug bằng source map

  • Figma coi source map là yếu tố quan trọng để lập trình viên vẫn có thể debug liền mạch trong suốt quá trình chuyển sang TypeScript
  • Trình debugger của trình duyệt chỉ hiểu JavaScript, nhưng lập trình viên lại đặt breakpoint trong mã Skew hoặc TypeScript
  • Source map liên kết vị trí trong JavaScript đã biên dịch với vị trí trong mã nguồn gốc
    • Ví dụ có thể ánh xạ như helper → c, myInt → a, arrayOfInts → b
  • Thông thường sẽ có một file source map đuôi .map gắn với bundle JavaScript cuối cùng
  • Hạ tầng cũ tạo source map Skew → JavaScript, nhưng ở Phase 2 pipeline đổi sang luồng Skew → TypeScript → bundling bằng esbuild
  • Nếu dùng nguyên source map cũ, ánh xạ giữa JavaScript và mã Skew sẽ bị sai lệch, khiến lập trình viên không thể debug
  • Quy trình build mới tạo source map theo 3 bước
    • Step 1: esbuild tạo source map TypeScript → JavaScript là ts-to-js.map
    • Step 2: transpiler tạo source map Skew → TypeScript cho từng file Skew
    • Step 3: hợp thành hai source map để tạo source map cuối cùng Skew → JavaScript
  • Nhờ source map cuối cùng này, bundle JavaScript mới vẫn có thể được ánh xạ về mã Skew, giúp duy trì trải nghiệm lập trình viên trong Phase 2

Xử lý conditional compilation trong TypeScript

  • Skew hỗ trợ conditional compilation bằng câu lệnh if ở cấp cao nhất và tùy chọn defines truyền cho compiler
  • Tính năng này cho phép tạo các bundle khác nhau từ cùng một codebase
    • Bundle thực tế được triển khai cho người dùng
    • Bundle chỉ dành cho unit test
    • Các hàm hoặc class dùng implementation khác nhau giữa build debug và release
  • Vì TypeScript không có conditional compilation, Figma dùng defines của esbuild cùng dead code elimination sau bước type checking để xử lý ở giai đoạn bundling
  • Cách này có nghĩa là defines không thể ảnh hưởng đến quá trình type checking
    • Các đoạn như testOnlyFunction chỉ tồn tại khi BUILD == "TEST" không thể giữ nguyên trong TypeScript
  • Cách giải quyết là luôn định nghĩa class và method, rồi rẽ nhánh theo giá trị BUILD bên trong method
    • Nếu testOnlyFunction bị gọi trong build không dành cho test thì sẽ ném lỗi Unexpected call to test-only function
  • JavaScript cuối cùng vẫn có thể được biên dịch giống với JavaScript mà mã Skew ban đầu tạo ra
  • Tuy nhiên, một số symbol vốn chỉ tồn tại ở một số chế độ compile nhất định nay lại xuất hiện trong mọi chế độ, khiến bundle cuối hơi lớn hơn
  • Trong thử nghiệm, mức tăng kích thước bundle là chấp nhận được, và các top-level symbol không export có thể bị loại bỏ bằng tree-shaking

Hướng đi sau chuyển đổi

  • Việc chuyển toàn bộ mã Skew sang TypeScript đã hiện đại hóa một trong các codebase cốt lõi của Figma
  • Việc tích hợp với mã nội bộ và bên ngoài trở nên dễ hơn, và lập trình viên có thể làm việc hiệu quả hơn
  • Với nhu cầu và năng lực của Figma ở thời điểm trước đó, quyết định khởi đầu codebase bằng Skew là phù hợp
  • Khi công nghệ trưởng thành hơn, TypeScript — vốn trước đây chưa phù hợp — nay đã trở thành lựa chọn thích hợp
  • Figma đang tiếp tục khám phá các khả năng tiếp theo
    • Tích hợp với phần còn lại của codebase
    • Quản lý package dễ dàng hơn nhiều
    • Dùng trực tiếp các tính năng mới từ hệ sinh thái TypeScript năng động
  • Trong quá trình chuyển đổi, họ cũng học được nhiều khía cạnh của TypeScript như phân giải import, hệ thống module và sinh mã JavaScript

1 bình luận

 
GN⁺ 2024-05-05
Các ý kiến trên Hacker News
  • Việc Figma từng có ngôn ngữ tùy chỉnh cho JS đã đáng ngạc nhiên, và việc nó nhanh hơn TS còn đáng ngạc nhiên hơn
    Nhưng cũng thú vị là cuối cùng họ vẫn chuyển sang TS chậm hơn
    Những chuyện như vậy khá thường thấy: ban đầu công ty tự xây công nghệ riêng, rồi sau khi lớn lên thì chuyển sang thứ “chuẩn” hơn

    • Có vẻ là một diễn tiến khá điển hình. Ban đầu một cá nhân xuất sắc như Evan thiết lập toàn bộ toolchain và phần cốt lõi của sản phẩm, rồi sau đó rời đi, bị gạt ra, hoặc mất hứng thú
      Khi đội ngũ và sản phẩm lớn hơn nhiều, họ lại chuyển nền tảng sang một stack quen thuộc và được dùng rộng rãi hơn
      Thành công của quá trình chuyển đổi như vậy phụ thuộc rất lớn vào việc văn hóa kỹ thuật của tổ chức vững đến đâu. Không có bằng chứng, nhưng có vẻ Evan và các nhà sáng lập đã xây dựng một văn hóa kỹ thuật tuyệt vời ở Figma, và tổ chức trông có đủ khả năng phục hồi để sửa sai nếu có lỗi xảy ra
    • Nếu đọc kỹ thì thấy tất cả các phần nhạy cảm về hiệu năng đều đã được chuyển sang C++/WASM
      Đến thời điểm đó chỉ còn lại mã kết dính, và ngôn ngữ tùy chỉnh không còn lý do để tồn tại nữa
    • Cộng đồng PHP cũng từng có chuyện tương tự. Facebook là ví dụ tiêu biểu, nhưng Yahoo cũng có khá nhiều tối ưu nội bộ, và tôi cũng từng thấy các công ty khác tự chỉnh sửa vì hiệu năng hoặc bảo mật
      Rồi khi cộng đồng bắt kịp và có động lực lớn hơn cả công ty, việc chuyển sang triển khai chuẩn trở nên hợp lý
      Tôi cũng xem luồng từ Borg của Google đến k8s có phần tương tự. Tuy vậy, Google là bên mời cộng đồng tham gia quanh tiêu chuẩn do chính họ tạo ra
    • Nhanh hơn TS trong một phạm vi hẹp là một chuẩn so sánh tương đối thấp. Nhưng khi quy mô lớn dần, chuẩn đó phải được cân nhắc cùng với nguồn lập trình viên có thể tuyển trên thị trường
      Cần so sánh chi phí của lập trình viên có thể học được một framework hoàn toàn mới ngay lần đầu nhìn thấy, với giá trị của lập trình viên đã có kinh nghiệm được ghi nhận bằng tài liệu trên nền tảng hoặc công nghệ đang dùng
      Nếu tự phát triển hoàn toàn, bạn có thể vắt ra hiệu năng cực lớn từ bất kỳ ngôn ngữ hay framework nào, nhưng khi dự án phải xử lý nhiều tình huống hơn, số lập trình viên cần để bảo trì tăng lên, và cuối cùng sẽ đến lúc phần mềm có sẵn trở nên tốt hơn, dù nó chậm và không khớp hoàn hảo với yêu cầu
      Nếu về dài hạn có thể duy trì tiêu chuẩn tuyển dụng cấp kỳ lân thì có lẽ vẫn duy trì được một stack hoàn toàn tùy chỉnh. Nhưng đa số tổ chức phải chuyển sang hướng mà các nhân sự mới ở mức trung bình có thể duy trì trong tương lai, và thường điều đó có nghĩa là sản phẩm của các nhà cung cấp phần mềm nổi tiếng và nhàm chán
    • Những thứ đặc thù và kỳ quặc như ngôn ngữ tùy chỉnh là bất lợi trên CV nếu bạn không phải người triển khai nó mà chỉ là người dùng đơn thuần, chẳng hạn lập trình viên dùng ngôn ngữ đó
      Với người có tham vọng, đó có thể là lý do để rời đi; việc tuyển dụng cũng khó hơn và onboarding dài hơn. Về sau, khi bỏ ngôn ngữ tùy chỉnh, còn cần một dự án chuyển đổi lớn
      Đôi khi việc đó đáng giá nếu mức tăng hiệu năng là cực lớn, hoặc nếu có thể viết mã an toàn hơn, hoặc nếu chủ đích là chỉ tuyển những người thích học ngôn ngữ mới
  • Tôi đã làm trong dự án này. Tôi có viết thêm một chút trên Twitter: https://twitter.com/andrew_k_chan/status/1786769203912925477
    Tiêu đề bài viết dễ gây hiểu nhầm. Ở Figma, chúng tôi đã dùng Typescript trong các phần khác của codebase gần 10 năm, và trong gần như toàn bộ thời gian đó, lượng mã Typescript nhiều hơn mã Skew
    Như bài blog giải thích, Skew được dùng cho engine di động, rồi sau đó cho trình phát prototyping, tính năng mirroring, và một hoặc hai khu vực sản phẩm nào đó tôi không nhớ

  • Skew không chỉ nhanh hơn TypeScript một chút
    Theo Evan Wallace, cựu CTO của Figma, nhờ các tối ưu mà hệ thống kiểu chặt chẽ hơn cho phép, nó nhanh hơn 1,5~2 lần

    • Thật tiếc là trình duyệt đã không tiếp tục phát triển chế độ "use strong" của JS
      Có vẻ nó gặp vài vấn đề khá lớn, nhưng việc giảm bớt một phần tính động để tối ưu dễ dự đoán hơn nghe như một đánh đổi tốt cho các ứng dụng cấp production
    • Câu “nhờ hệ thống kiểu chặt chẽ hơn nên nhanh hơn 1,5~2 lần” có lẽ không đơn giản như vậy
      Nếu tối ưu các đường thực thi nóng, lợi thế 2 lần rất có khả năng sẽ biến mất
      Tất nhiên khi đó có thể nói rằng bạn sẽ phải viết JS đã tối ưu ở nhiều nơi, ảnh hưởng đến khả năng đọc. Đúng vậy, nhưng phương án thay thế là dùng một ngôn ngữ biên dịch sang JS hoàn toàn mới, ít được hỗ trợ công cụ và ít được biết đến
      Nhìn lại thì có vẻ không đáng, và bài blog có cảm giác đang tô điểm phần nào cho một lựa chọn công nghệ trước đây vốn gây tranh luận
    • Trong cả bài, chênh lệch tốc độ 2 lần là điều làm tôi ngạc nhiên nhất
      Tôi tự hỏi liệu có thể giới hạn việc dùng TypeScript trong một tập con đạt được hiệu năng đó hay không
  • Điều thú vị là khi hoàn tất một thao tác như const [a, b] = function_that_returns_an_array(), JavaScript không index trực tiếp vào mảng mà tạo một iterator để duyệt mảng
    Vì sao JS không đơn giản index trực tiếp vào mảng khi gán destructuring?

    • Vì bất kỳ object nào cũng có thể trở thành iterable object nếu thêm Symbol.iterator, và destructuring phải hoạt động cả với những object như vậy. Thậm chí bản thân Symbol.iterator của mảng cũng có thể bị patch, nên VM phải xử lý
      Array.prototype[Symbol.iterator] = function*() { yield 1; yield 2; yield 3; }
      [...[4, 5, 6]]
      [1, 2, 3]
      Hiệu năng tệ hại của iterator protocol đã được bàn luận ngay từ lúc đó, nhưng bị phớt lờ với lập luận rằng escape analysis sẽ giải quyết [0]. Đến giờ gần 10 năm trôi qua, escape analysis vẫn chưa giải quyết được, dùng GC rất nhiều và vẫn chẳng tốt. Đây là một đặc tả tệ do những người không quan tâm đến hiệu năng thiết kế
      Nếu người dùng không patch Symbol.iterator, việc engine chuyên biệt hóa destructuring và splicing của mảng để loại bỏ overhead của iterator protocol cũng có lý, nhưng đó lại là một vấn đề đau đầu khác
      [0] https://esdiscuss.org/topic/performance-of-iterator-next-as-...
    • Có vẻ là vì những thứ như proxy tồn tại
      Điều kỳ lạ hơn là trong một số engine JavaScript, khi destructuring mảng có hai ba phần tử, destructuring object kiểu {0: foo, 1: bar} có thể nhanh hơn
  • Bài viết không đề cập nhiều đến tác động lâu dài lên trải nghiệm lập trình viên khi mất các tính năng tiện lợi của Skew, mà chỉ nói về các chuyển đổi thực hiện một lần khi di chuyển codebase
    Ví dụ, trong TypeScript rất dễ gặp trường hợp phải import file theo đúng thứ tự, nếu không có thể bị hỏng. Ngoài ra destructuring chậm, nên nếu hiệu năng dù chỉ hơi quan trọng thì không nên dùng
    Sau vài năm dùng TypeScript, tôi thấy có hàng chục cái bẫy như vậy; một số kế thừa từ JavaScript, một số thì không. Nếu có nhiều kỹ sư, ít nhất cũng cần một style guide đồ sộ
    Tôi tự hỏi liệu có kỹ sư nào tiếc khi Skew biến mất không

    • Việc bảo đảm các lập trình viên hài lòng với kết quả chắc chắn là quan trọng. Vì vậy trong quá trình rollout, chúng tôi đưa vào một giai đoạn mà lập trình viên vẫn tiếp tục viết Skew, nhưng các thay đổi được tự động check-in dưới dạng TS được tạo ra
      Nhờ vậy, lập trình viên có thể xem kết quả trông thế nào trong PR review và báo cáo vấn đề
      Về hiệu năng và tính đúng đắn khi chạy, đúng là TS có vài cái bẫy. Những vấn đề như destructuring mảng được phát hiện bằng instrumentation và giám sát nghiêm ngặt
      Việc mất một số tính năng của Skew, chẳng hạn operator overloading và kiểu số nguyên, chắc chắn là đáng tiếc. Nhưng cuối cùng việc di chuyển là quyết định của toàn đội, và tôi cũng nghĩ đó là quyết định đúng
  • Bài viết nói “các tính năng JavaScript hiện đại như async/await và hệ thống kiểu linh hoạt hơn”, vậy Skew chỉ có callback thôi sao?

    • Có lẽ vẫn có Promise chăng?
  • Với tư cách người không rành về Figma, tôi tò mò vì sao họ dùng WebAssembly

    • Chắc bạn cũng biết Figma là phần mềm thiết kế UX. Tức về cơ bản nó là một chương trình đồ họa. Vẽ hình, cuộn, phóng to/thu nhỏ
      Figma làm những việc đó cực kỳ tốt. Ngay cả trên một canvas rất lớn với nhiều màn hình UI phức tạp, nó vẫn phản hồi nhanh đến khó tin
      Ngay cả trong các ứng dụng desktop ngày nay, hiếm có thứ nào chạy tốt đến mức này. Tôi tin chắc dạng tối ưu hóa này là một phần quan trọng trong thành công của Figma
    • Chỉnh sửa vector có nhiều tác vụ bị giới hạn bởi CPU. Evan có viết một bài về việc chuyển sang WASM: https://medium.com/figma-design/webassembly-cut-figmas-load-...
    • Mục tiêu ban đầu là Photoshop trong trình duyệt
  • Một bài blog khác cũng có các chi tiết thú vị về cách Figma tạo TypeScript DSL + compiler tùy chỉnh để giải quyết vấn đề bảo mật, tức là quyền hạn
    https://www.figma.com/blog/how-we-rolled-out-our-own-permiss...

  • Nghe hơi đau lòng. Công ty lớn nào cũng có công cụ, ngôn ngữ, thứ kiểu Kubernetes nội bộ của riêng mình. Sao họ không chia sẻ nhỉ
    Nếu Skew là mã nguồn mở, có lẽ nó đã trở thành một TypeScript tốt hơn

    • Skew là mã nguồn mở nhưng không còn được bảo trì: https://github.com/evanw/skew
    • Tôi không thích lắm góc nhìn này; nó thường xuất phát từ thiếu kinh nghiệm với mã nguồn mở
      Mã nguồn mở không có nghĩa là sẽ tự nhiên có đóng góp miễn phí. Mỗi PR không tầm thường đều cần review dài, thảo luận, thậm chí có thể phải viết lại
  • Tôi thích TypeScript và cũng có hệ thống full-stack bằng TypeScript, nhưng nó không hoàn hảo. Việc cấu hình TypeScript trong monorepo đúng là ác mộng
    Để làm cho mọi thứ dễ hiểu cùng các package nội bộ dưới pnpm monorepo, phải chỉnh tay rất nhiều trong tsconfig.json sao cho mọi đường dẫn khớp với nhau
    Và cho đến trước khi package tsx tuyệt vời xuất hiện, toolchain cho production về cơ bản là không thể bảo trì
    Ngoài ra nó còn chậm đến vô lý. Do Zod có vấn đề làm hiệu năng TypeScript language server chậm đi đáng kể, cuối cùng đã phải đưa vào project references và tắt project reference redirects
    Tổng hợp lại thì TypeScript vẫn còn rất nhiều chỗ để cải thiện. Đặc biệt là ở khía cạnh monorepo và hiệu năng

    • Cần lưu ý rằng Zod là một trường hợp khá ngoại lệ về mức độ có thể làm chậm tốc độ kiểm tra kiểu. Ví dụ, một bài test tại https://dev.to/nicklucas/typescript-runtime-validators-and-d... gần chạm mức 300ms, nhưng các thư viện khác hầu như không chạm tới 100ms
    • Zod vốn nổi tiếng là chậm. Ví dụ Typebox nhanh hơn nhiều. Không có ý bảo phải đổi, mà ý là đây không phải vấn đề của TypeScript, cũng không phải vấn đề TypeScript cần giải quyết
      Vấn đề monorepo nghe giống như không dùng cùng một cấu hình cho tất cả package. Nếu vậy, tôi sẽ sửa trước bằng cách ép dùng cùng cấu hình và chuẩn coding. Đây cũng không phải vấn đề của TypeScript
      Có phải trước tsx bạn dùng ts-node không? Nếu đúng thì tsx vững chắc hơn nhiều. Nó cứ thế hoạt động tốt
    • Không phải TypeScript cần hỗ trợ một tổ hợp lựa chọn công cụ và thư viện cụ thể; ngược lại, phía công cụ và thư viện mới cần thích nghi
      Tôi đang vận hành một monorepo cỡ trung, nhiều app và nhiều service hầu hết bằng TypeScript, và ngay cả với cấu hình dựa trên npm workspaces khá nhàm chán thì vẫn chạy ổn
    • Nói TypeScript chậm vì Zod chậm cũng giống như nói C++ chậm vì JavaScript chậm
      Hoàn toàn không có ý nói TypeScript nhanh, nhưng vì nó được viết bằng JavaScript nên cũng khó mà nhanh được
      Tuy nhiên, để TypeScript chạy code nhằm suy luận kiểu trong một ứng dụng quy mô lớn thì trông giống như vấn đề tự tạo ra