21 điểm bởi GN⁺ 2025-08-18 | 7 bình luận | Chia sẻ qua WhatsApp
  • Node.js đã được cải tiến để chạy trực tiếp các tệp TypeScript
  • Giờ đây có thể chạy ngay các tệp .ts mà không cần cấu hình bổ sung hay transpile
  • Nhà phát triển có thể nâng cao hiệu quả làm việc mà không cần tsconfig.json hay cài thêm bundler riêng
  • Tính năng này đã được chính thức tích hợp từ Node.js v22.18.0 (LTS)
  • Kỳ vọng sẽ làm mờ ranh giới giữa phát triển JavaScript và TypeScript

Hỗ trợ chạy trực tiếp TypeScript trong Node.js

  • Trong phiên bản gần đây v22.18.0 (LTS), Node.js đã giới thiệu tính năng có thể chạy trực tiếp các tệp TypeScript (.ts) mà không cần cấu hình hay công cụ riêng
  • Trước đây, để chạy mã TypeScript cần có transpiler bên ngoài hoặc bundler như ts-node, esbuild, Babel, nhưng nay Node.js có thể tự nhận diện và chạy mã TypeScript mà không cần các công cụ đó
  • Với tính năng này, nhà phát triển có thể chạy trực tiếp tệp .ts trên Node.js mà không cần tệp cấu hình tsconfig.json hay thư viện bổ sung
  • Năng suấtsự thuận tiện trong phát triển sẽ tăng đáng kể trong các tình huống như tạo prototype, phát triển thử nghiệm, chạy script
  • Dự kiến sẽ mang lại hiệu quả như tăng cường khả năng liên kết giữa các dự án JavaScript và TypeScript, đồng thời giảm rào cản gia nhập cho nhà phát triển mới

Các thay đổi đáng chú ý khác

  • esm: triển khai import.meta.main
  • fs: cải thiện xử lý sự kiện fs dựa trên AsyncIterator
  • permission: hỗ trợ truyền cờ mô hình quyền khi chạy tiến trình con
  • sqlite: thêm tùy chọn readBigInts
  • src/permission: hỗ trợ permission.has(addon)
  • url: thêm API fileURLToPathBuffer
  • watch: thêm cờ --watch-kill-signal
  • worker: cải tiến đối tượng Worker thành async disposable
Quảng cáo

Cập nhật liên quan đến commit và tài liệu

  • Bao gồm việc loại bỏ mã không cần thiết, chỉnh lý môi trường build và toolchain, nâng cấp lên npm 10.9.3
  • Chỉnh sửa các chỉ số ổn định chi tiết và số RFC trong tài liệu như globals.md, child_process.md, http2
  • Bổ sung nhiều bài kiểm thử và áp dụng các bản sửa lỗi

Tệp phát hành

  • Cung cấp trình cài đặt và tệp nhị phân cho Windows, macOS (Intel/Apple Silicon), Linux (x64, ARM, PPC, s390x, AIX)
  • Có thể tải mã nguồn và toàn bộ tệp phát hành từ trang phát hành chính thức của Node.js
  • Tài liệu API đã được cập nhật theo v22.18.0

7 bình luận

 
aliveornot 2025-08-19

Đúng là nhẹ cả người... Mong nó sớm phổ biến.

 
tested 2025-08-18

Có vẻ sẽ ổn cho việc chạy các script đơn giản, nhưng vì có quá nhiều hạn chế với các dự án thực tế nên chắc cũng không có mấy dịp để dùng.

Còn phải chỉnh cả phần mở rộng và đường dẫn cho khớp vì lỗi ERR_MODULE_NOT_FOUND/ERR_UNSUPPORTED_DIR_IMPORT,
và cũng không dùng được những tính năng cần hỗ trợ build TypeScript với thiết lập emitDecoratorMetadata như NestJS nên...

 
kimjeongwonn 2025-08-18

Vậy là --experimental-strip-types được áp dụng mặc định à?

 
click 2025-08-18

Dù sao thì tôi cũng không dùng enum, nên theo tiêu chí của tôi chỉ riêng việc loại bỏ kiểu cũng đã đủ để chạy rất ổn rồi.

 
crawler 2025-08-18

Sẽ tiện hơn rất nhiều!

 
honglu 2025-08-18

Không thể kìm được cú thích.

Mình đã nghĩ chỉ với cờ --no-experimental-strip-types thôi cũng đã đủ tốt rồi.

Có vẻ còn tốt hơn nữa.

 
GN⁺ 2025-08-18
Ý kiến trên Hacker News
  • Với node:test trong Node.js, giờ tôi nghĩ Node.js gần như đã trở thành lựa chọn mặc định đủ sức thuyết phục trong hầu hết các trường hợp. Việc chạy bằng tsx từng là một cải thiện rất lớn về trải nghiệm, nhưng vẫn chưa hoàn hảo. Các công cụ như zod, ts-rest và trpc đang chủ yếu giải quyết việc khẳng định kiểu lúc runtime ở biên, và dạo gần đây phát triển full-stack Typescript thực sự đã trở nên rất dễ dàng
    • Chuẩn luôn. Đến năm 2025 thì cuối cùng hệ sinh thái Node cũng đã đủ dùng chỉ với cấu hình mặc định. Module ESM hoạt động trơn tru ở cả Node lẫn Typescript, Node có thể chạy trực tiếp file .ts, và còn tích hợp sẵn một test runner mặc định khá tốt (có hỗ trợ --watch). Các package tích hợp cũng đang ngày càng tốt hơn. Ví dụ như node:fs/promises, nhờ top-level await mà làm các tác vụ vòng lặp bất đồng bộ cũng dễ hơn nhiều. Đã mất rất lâu để thuyết phục mọi người tiếp cận theo hướng thực tế, nhưng giờ thì đúng là đã rất dễ chịu
    • Tôi hoàn toàn ủng hộ việc Node hỗ trợ trực tiếp Typescript. Dạo này vitest giúp nhiều thứ trở nên tiện hơn, nhưng trước đây tôi đã tốn rất nhiều thời gian chỉ để cấu hình môi trường test cho file .ts. Còn trpc và ts-rest thì tôi nghĩ là bài toán hoàn toàn khác. Cả hai đều dùng được, nhưng trong production tôi tránh trpc vì tôi không thể thực sự sở hữu URL API của mình, cũng không thể quản lý và loại bỏ dần các URL cũ một cách tự nhiên. Với ts-rest, tôi thường vẫn thích tự chia sẻ zod và type để tự quản lý trực tiếp từng cặp request/response của API. Và mỗi lần thấy một công cụ rõ ràng là RPC như trpc mà lại có -rest trong tên là tôi thấy hơi khó chịu
    • Tôi sẽ theo dõi xem liệu Sveltr có chuyển codebase trở lại Typescript hay không
    • Tôi tò mò không biết cái này có chạy được tsx không. Dù có loại bỏ type đi thì JSX vẫn phải được chuyển thành JavaScript, nên tôi thắc mắc phần đó xử lý thế nào
    • Tôi mới chuyển sang Python cách đây không lâu. Mọi thứ đều có sẵn, nên tôi thấy hài lòng hơn nhiều vì không còn phải debug đủ kiểu vấn đề kỳ quặc của một hệ thống còn chưa hoàn chỉnh
  • Tôi rất ấn tượng với những tiến bộ mà Node đã thể hiện trong vài năm gần đây. Thật tốt khi deno và bun đã tạo áp lực để Node tập trung vào các cải tiến dày đặc và có ý nghĩa. Đã có một thời gian dài bị trì trệ
    • Tôi tò mò gần đây Node đã có những cải tiến gì. Lần cải tiến gần nhất mà tôi thấy thực sự đáng kể là hỗ trợ chính thức cho import/export (không rõ còn phải dùng kiểu lách .mjs nữa không). Tôi đã rời xa hệ sinh thái một thời gian nên muốn biết từ đó đến nay đã có gì thay đổi
    • Tôi không chắc có đúng là vậy không. Nhìn vào các dự án tôi từng tham gia thì kể cả không có deno hay bun cũng chẳng sao cả. Điều thực sự có ý nghĩa vẫn là các bản phát hành LTS của Node, và ngay cả các dự án mới nhất cũng vẫn đang dùng Node 20
  • Thật tiếc là Typescript không được chấp nhận trong node_modules (liên quan: tài liệu chính thức của node.js). Vậy thì các dependency của dự án sẽ ra sao, tôi khá thắc mắc. Tôi đã viết một thư viện cho mô hình dữ liệu bằng Typescript, và muốn import nó vào app của mình ở nguyên trạng Typescript. Tôi muốn biết quy tắc này chỉ áp dụng cho package npm hay áp dụng cho mọi dependency. Ở đây có cơ hội khá lớn. Tôi đã làm một runtime dựa trên golang để thực thi typescript (chính xác hơn là toàn bộ JS), và sobek mà đội grafana đang dùng có lẽ cũng chỉ cần thêm chức năng strip type là được. Tôi cảm thấy chỉ cần xuất hiện một runtime mặc định chấp nhận hoàn toàn Typescript thì Node.js sẽ thực sự mang tính cách mạng. Không cần transpiler, không cần typescript-go, cũng không cần rust (dù rust thì vẫn hơi cần 😉), chỉ cần một hệ thống có parser tốt theo dõi source map và type trong chế độ debug là đủ. Dù sao thì tôi cũng muốn dành sự ghi nhận và cảm ơn tới đội Node cùng tất cả những người đóng góp. Có cảm giác Node là tiêu chuẩn để tất cả chúng ta đi theo. API nhúng cũng đơn giản và dễ dùng, nên khi tạo bản standalone cũng rất tiện
    • Tôi cũng từng để lại bình luận tương tự (tham khảo). Có đoạn nói là “để khuyến khích không phát hành package viết bằng Typescript lên npm”, và tôi cũng đã thử với package private nhưng vẫn không chạy; Node hoàn toàn không quan tâm tới chính trường "private"
    • Tôi nghĩ package nên luôn được compile sang JavaScript trước khi phát hành lên npm. Tôi không thấy lý do gì phải đưa nguyên Typescript lên npm cả
  • Vấn đề liên quan Tôi thấy đáng tiếc khi không có hỗ trợ strip type trong node_modules
    • Một nửa lý do tôi mong chờ tính năng này chính là vì điều đó. Tôi muốn viết thư viện bằng Typescript, chỉ typecheck trong CI/CD, rồi import trực tiếp từ Node.js
    • Tôi nghĩ đây là quyết định đúng. Typescript có breaking change diễn ra khá thường xuyên. Chừng nào chưa được chuẩn hóa thì cách hiện tại vẫn tốt hơn
  • Tôi không phải người dùng quá nhiều JS/TS, nhưng tôi tự hỏi liệu dùng luôn Bun có tốt hơn không. Tất nhiên không phải mọi dự án đều bắt đầu mới, nhưng tôi thấy Bun nhìn chung là runtime tốt hơn. Chạy TS ngay từ đầu, phân giải dependency nhanh hơn rất nhiều, và trải nghiệm sử dụng cũng rất tốt. Cá nhân tôi đã chuyển khá nhiều dự án Node cũ sang Bun, và từ khi Bun ra mắt thì tôi gần như không còn dùng Node nữa. Nếu tôi đang hiểu sai điều gì thì mong được chỉ ra
    • Tôi đã chỉ dùng Node gần 8 năm rồi gần đây mới chuyển sang Deno. Việc chuyển này cũng không hề dễ, và điều khiến tôi sợ không phải là nó không chạy, mà là không biết lúc nào nó sẽ ngừng chạy. Node rõ ràng vẫn còn nhiều điểm chưa tốt, nhưng dù sao nó vẫn là chuẩn thực tế của ngành. Bản thân hệ sinh thái JS vốn đã hỗn loạn, nên nhiều lập trình viên đã mệt mỏi với các build tool, bundler và runtime mới. Có vẻ Bun vẫn chưa tích lũy đủ độ ổn định và mức hỗ trợ để trở nên thật sự thuyết phục. Trước đây tôi từng chỉ vì một bản cập nhật minor của TS mà mất vài ngày để xử lý vấn đề
    • Tôi không thích lắm việc cứ phải chạy theo xu hướng mới nhất. NodeJS là runtime được hỗ trợ tốt nhất trong hệ sinh thái JS. Tôi nghĩ cứ đi theo lựa chọn mặc định thì tốt hơn nhiều. Tôi thuộc kiểu chọn công nghệ “nhàm chán”
    • Từ khi Bun ra mắt tôi đã thử chuyển hẳn sang nhiều lần, nhưng lần nào cũng va phải một vấn đề không thể né được ở khoảng 90%. Ở lần thử gần nhất, một số thư viện không chạy vì một vài hàm napi chưa được triển khai, rồi còn lỗi tùy chọn recursive của opendir bị bỏ qua nữa. Tôi đang ở thế chờ Bun bắt kịp, nhưng đến giờ nó vẫn chưa có vẻ sẵn sàng cho áp dụng thực tế trong các dự án lớn. Các tính năng riêng của bun thoạt nhìn có vẻ hay nhưng vào thực chiến thì chưa đủ. Tài liệu cũng chưa đạt chất lượng như Node.js
    • Đây là các vấn đề tương thích tôi gặp phải khi thử thay Node bằng Bun.
  • localAddress bị bỏ qua trong kết nối TCP
  • Không tương thích với Node module API (ví dụ: dự án spamscanner không chạy)
  • Vấn đề race liên quan đến EventEmitter (tạm khắc phục một phần bằng eventemitter2)
  • Dev server của Svelte vites đôi khi bị treo, phải xóa node_modules rồi cài lại
    • Tôi đã thử dùng tính năng TS và test runner của chính Node, nhưng hiện vẫn chưa tốt bằng Bun. Trong thời gian tới, cứ khi nào cần những tính năng như vậy thì tôi vẫn dùng Bun. Trong hệ sinh thái Node, tôi đã học được rằng thay vì all-in vào một thứ, tốt hơn là kết hợp các công cụ chuyên cho từng việc.

      • Bun.js: dùng cho runtime Node, chạy TS và test. Tôi đã thử nhiều cách như TSX, TS-Node, chính Node, v.v.

      • NPM: dùng để chạy script tooling

      • PNPM: dùng để cài dependency. (Tôi thấy tốt nhất so với npm, yarn, bun)

      • Biome.js: dùng để lint. Tốt hơn bất kỳ công cụ lint nào tôi từng dùng

  • Điều rất hay ở cải tiến lần này là nó chỉ làm “type stripping”, nên không cần source map và gần như có chi phí bằng 0 trong production. Đội Node làm quá tốt
  • Hàm strip type (import { stripTypeScriptTypes } from 'node:module') cũng đã được expose. Khi phát triển một web app đơn giản không có dependency frontend, có thể viết toàn bộ bằng typescript rồi khi phục vụ script frontend thì chỉ cần bỏ type đi là được (dự án ví dụ)
  • Nhờ thay đổi này mà công ty chúng tôi cuối cùng cũng có thể chuyển sang Typescript. Chúng tôi đã chuyển nhiều dịch vụ sang TS cùng lúc, và một số cái vẫn đang tiếp tục. Một thành quả rất lớn
  • Có vẻ cách nó hoạt động là loại bỏ thông tin type. Nói cách khác, nó chỉ cắt bớt một bước transpile, chứ không cải thiện gì về mặt an toàn
    • Một mục tiêu thiết kế cốt lõi của Typescript là chỉ cần loại bỏ cú pháp liên quan đến type thì đầu ra sẽ là một file JavaScript hợp lệ. Trình biên dịch TS không sinh mã (ví dụ không như PureScript). Việc kiểm tra tĩnh sẽ do type checker như tsc đảm nhiệm, còn thông tin type thì bị loại bỏ. Python cũng bỏ qua type annotation ở runtime, còn Java thì một phần thông tin type như generic cũng bị xóa khỏi bytecode
    • Câu “ít nhất thì nó chỉ giảm được bước transpile chứ không cải thiện an toàn” hơi dễ gây hiểu lầm. Việc Node chạy trực tiếp TS không làm tăng độ an toàn từ type checking, nhưng type checking vốn có thể được thực hiện riêng trong editor hoặc bằng nhiều công cụ khác. Việc Node hỗ trợ chạy trực tiếp TS làm giảm mạnh rào cản dùng TS, và gián tiếp giúp tăng độ an toàn về type
    • Typescript chưa từng hứa hẹn sẽ đảm bảo tăng độ an toàn. Đây là một hiểu lầm phổ biến. TS thực chất không có runtime mode hay runtime information; nếu không chạy type checker thì kể cả có lỗi type nghiêm trọng, nó vẫn cứ chạy. Nói nghiêm ngặt thì Typescript gần với một linter hơn
    • Có thể chạy script trực tiếp mà không cần build/transpile thực sự rất tiện. Nếu cần typecheck thì tôi chạy riêng bằng tsc, cách này khá hợp với tôi
    • Chúng tôi đang dùng một thiết lập tương tự trong dự án với tsx, cũng không cần build/transpile gì mà vẫn chạy được. Khi phát triển thì cực kỳ tiện. Nhờ --watch của tsx mà có thể chạy server trực tiếp từ mã nguồn TS và tự khởi động lại khi có thay đổi. Sắp tới có lẽ chỉ với nodemon và tính năng tích hợp của Node cũng có thể tạo ra môi trường tương tự. Nếu muốn typecheck ngay trong runtime thì phải có hỗ trợ ở cấp độ v8, mà như vậy gần như là viết lại toàn bộ
  • Thực tế thì nó không chạy toàn bộ Typescript, mà chỉ hỗ trợ một tập con. Nội dung tiêu đề có thể khiến người ta cảm thấy bị phóng đại. Cũng có nguy cơ thay đổi này khiến TS bị dùng như một linter thuần túy, và nhiều tính năng mạnh của TS vốn không thể chỉ triển khai bằng strip type sẽ bị mai một
    • Tôi tò mò không biết rốt cuộc những tính năng nào của TS là không thể strip được. Ngoài enum ra thì có trường hợp thực tế nào mọi người vẫn dùng không?