1 điểm bởi GN⁺ 2025-01-25 | 1 bình luận | Chia sẻ qua WhatsApp
  • Bun 1.2 là một bản phát hành lớn hướng tới bộ công cụ phát triển JavaScript/TypeScript full-stack, đồng thời mở rộng khả năng tương thích Node.js cùng runtime, bundler, test và package manager
  • Bun đã tăng cường việc kiểm chứng tương thích bằng cách chạy bộ kiểm thử Node.js sau mỗi thay đổi, đồng thời bổ sung hỗ trợ node:http2, node:dgram, node:cluster, node:zlib, node:v8
  • API tích hợp mới Bun.s3Bun.sql đưa truy cập tới object storage tương thích S3 và Postgres vào thẳng runtime, giảm phụ thuộc vào client bên ngoài
  • Package manager chuyển lockfile mặc định từ file nhị phân bun.lockb sang bun.lock dựa trên JSONC, đồng thời thêm .npmrc, bun publish, bun patch, bun outdated, bun run --filter
  • Thư mục làm việc của bun run, cách xử lý lỗi của Bun.build(), giá trị trả về của server.stop(), bun -p và giá trị mặc định của sourcemap đã thay đổi, nên các dự án hiện có cần kiểm tra ảnh hưởng khi migration

Tăng cường khả năng tương thích Node.js

  • Bun 1.2 thay đổi quy trình cải thiện tương thích bằng cách chạy bộ kiểm thử Node.js sau mỗi lần thay đổi của Bun
    • Trước đây, lỗi chủ yếu được sửa dựa trên GitHub issue hoặc báo cáo không chạy được package npm, nhưng cách này gần như là kiểu “đập chuột chũi”, khiến các đợt refactor lớn trở nên khó khăn
    • Bun đã port hàng nghìn file test từ kho mã Node.js sang Bun và chạy các test này ở mỗi commit để xác nhận tính tương thích
  • Trong các bài test của Node.js có những trường hợp kiểm tra chi tiết triển khai nội bộ và thông điệp lỗi chính xác, nên Bun đã thay binding nội bộ bằng stub riêng trong một số test, hoặc điều chỉnh sang xác minh dựa trên namecode
    • Bun cố gắng khớp thông điệp lỗi của Node.js nhiều nhất có thể, nhưng trong một số trường hợp vẫn cung cấp thông điệp hữu ích hơn nếu namecode giống nhau
  • Các module và tính năng Node.js mới được hỗ trợ
    • node:http2: hỗ trợ tạo máy chủ HTTP/2, cũng cần cho máy chủ gRPC
    • node:dgram: hỗ trợ bind/connect cho socket UDP
    • node:cluster: có thể chạy nhiều instance Bun để phân phối công việc trên nhiều lõi CPU
    • node:zlib: phần triển khai JavaScript đã được viết lại bằng mã native và nhanh gấp 2 lần so với Bun 1.1
    • node:v8: có thể kiểm tra heap của Bun trong Chrome DevTools bằng getHeapSnapshot, writeHeapSnapshot
  • Máy chủ node:http2 trong Bun 1.2 nhanh gấp 2 lần Node.js
  • express xử lý request HTTP nhanh hơn tối đa 3 lần so với Node.js nhờ cải thiện tương thích node:http và tối ưu hóa máy chủ HTTP của Bun
  • Cũng đã bổ sung hỗ trợ cho C++ addon sử dụng V8 C++ API
    • Node.js dùng V8, còn Bun dùng JavaScriptCore, nên độ khó triển khai rất cao
    • Bun triển khai public C++ API của V8 trên nền JavaScriptCore để các package như cpu-features có thể hoạt động
    • Hỗ trợ V8 C++ API rất phức tạp nên nhiều package có thể vẫn còn thiếu tính năng; Bun đang tiếp tục cải thiện hỗ trợ cho các package như node-canvas@v2node-sqlite3

API S3 tích hợp Bun.s3

  • Bun 1.2 bổ sung API tích hợp Bun.s3 để làm việc với object storage tương thích S3
    • Có thể dùng với các dịch vụ triển khai S3 API như Amazon S3, Google Cloud Storage, Cloudflare R2
    • Việc đọc, ghi, xóa file được xử lý bằng API tương thích với Blob theo tiêu chuẩn Web
  • s3.file() trả về một tham chiếu trì hoãn tới file S3, có thể dùng theo cùng cách với Bun File API như text(), json(), arrayBuffer(), stream()
  • Client S3 của Bun được viết bằng mã native chứ không phải JavaScript
    • So với cách dùng @aws-sdk/client-s3 trên Node.js, việc tải file từ bucket S3 nhanh hơn 5 lần
  • Tính năng ghi cung cấp write()writer()
    • write() có thể upload chuỗi, Uint8Array, Blob, Response...
    • writer() thực hiện multipart upload cho file lớn
  • presign() tạo presigned URL cho phép upload một file cụ thể
    • Có thể để người dùng upload trực tiếp lên S3 mà không lộ credential hoặc cấp quyền truy cập bucket không cần thiết
  • Khi dùng cùng Bun.serve(), new Response(s3.file(...)) sẽ chuyển hướng bằng presigned URL thay vì để máy chủ tải file S3 rồi gửi lại
    • Giảm bộ nhớ, thời gian và chi phí băng thông khi máy chủ phải tải file
  • URL s3:// cũng có thể dùng trong Bun.file()fetch()
    • Có thể upload, download, xóa bằng fetch("s3://...")
    • S3Client mặc định được cấu hình bằng các biến môi trường như AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY

Client Postgres tích hợp Bun.sql

  • Bun 1.2 bổ sung client SQL tích hợp Bun.sql hỗ trợ Postgres
    • Trước đó Bun đã cung cấp client SQLite tích hợp, và ở bản phát hành này phạm vi hỗ trợ cơ sở dữ liệu SQL được mở rộng
    • Cũng đã có pull request bổ sung hỗ trợ MySQL
  • Bun.sql thực thi SQL bằng tagged-template literal
    • Có thể truyền giá trị JavaScript làm tham số SQL
    • Tự động dùng escape chuỗi và prepared statement để ngăn SQL injection
  • Kết quả được trả về dưới dạng mảng object với tên cột làm key
  • Sử dụng triển khai native và nhiều tối ưu hóa
    • prepared statement tự động
    • query pipelining
    • binary wire protocol
    • connection pooling
    • cache cấu trúc
  • Tốc độ đọc hàng nhanh hơn tối đa 50% so với cách dùng các client Postgres phổ biến trên Node.js
  • API được lấy cảm hứng từ postgres.js, nhằm giúp việc chuyển từ mã hiện có sang client SQL tích hợp của Bun trở nên dễ dàng

Thay đổi ở trình quản lý gói

  • Bun 1.2 chuyển lockfile mặc định từ bun.lockb dạng nhị phân sang bun.lock dạng văn bản
    • bun.lockb từng giúp bun install nhanh hơn gần 30 lần so với npm, nhưng khó xem nội dung trên GitHub, khó review pull request và khó xử lý merge conflict
    • Các công cụ như Dependabot cũng gặp khó khi đọc lockfile
  • bun.lock là tệp JSONC
    • Hỗ trợ comment và trailing comma
    • Giúp dễ xem diff trong pull request hơn, và trailing comma làm giảm khả năng xảy ra merge conflict
  • Dự án mới sẽ tạo bun.lock
    • Các dự án hiện có dùng bun.lockb vẫn tiếp tục được hỗ trợ lockfile nhị phân mà không tự động migrate
    • bun.lockb sẽ được hỗ trợ lâu dài, và bun add, bun update cũng sẽ tiếp tục cập nhật nó
    • Có thể migrate sang lockfile văn bản mới bằng bun install --save-text-lockfile
  • bun install vẫn nhanh hơn 30% so với Bun 1.1 ngay cả sau khi chuyển sang lockfile văn bản
  • Có thể dùng comment và trailing comma trong package.json
    • require()import() cũng có thể đọc package.json kiểu này
    • Tuy nhiên đây không phải tính năng được hỗ trợ rộng rãi trong toàn bộ hệ sinh thái JavaScript, nên được khuyến nghị dùng theo kiểu “at your own risk”
  • Đã bổ sung hỗ trợ .npmrc
    • Đọc .npmrc ở thư mục gốc dự án và thư mục home
    • Có thể dùng để cấu hình registry, scoped package và xác thực private registry
  • Lệnh và tùy chọn mới cho trình quản lý gói
    • bun run --filter: chạy đồng thời cùng một script trên nhiều workspace
    • bun outdated: kiểm tra dependency đã cũ
    • bun publish: thay thế npm publish, hỗ trợ xác thực .npmrc, đóng gói tarball, OTP và xử lý các edge case của package.json
    • bun patch: lưu thay đổi sửa dependency thành tệp .patch trong patches/ và tự động áp dụng khi bun install
    • --omit=dev|optional|peer: loại trừ dependency dev, optional, peer khỏi quá trình cài đặt
    • Có thể cấu hình chứng chỉ CA trong bunfig.toml, cờ CLI và .npmrc
    • Cũng hỗ trợ bundleDependencies và giữ nguyên thụt lề của package.json khi dùng bun add

Cải tiến test runner

  • bun test hỗ trợ JUnit XML reporter
    • Với bun test --reporter=junit --reporter-outfile=junit.xml, có thể gửi kết quả test tới các công cụ CI/CD như Jenkins, CircleCI và GitLab CI
    • Cũng có thể cấu hình báo cáo JUnit trong bunfig.toml
  • Đã thêm reporter LCOV cho code coverage
    • bun test --coverage --coverage-reporter=lcov sẽ tạo coverage/lcov.info
    • Có thể đổi thư mục output bằng --coverage-dir
  • Hỗ trợ inline snapshot với expect().toMatchInlineSnapshot()
    • Dùng bun test -u hoặc --update-snapshots để cập nhật snapshot ngay trong tệp test
    • Cũng có thể dùng toThrowErrorMatchingSnapshot()toThrowErrorMatchingInlineSnapshot()
  • test.only() giờ hoạt động cả khi không có cờ --only
  • API expect() được bổ sung các matcher như trong Jest, Vitest và jest-extended
    • toContainValue(), toContainKey(), các hàm nhóm toHaveReturned()
    • Có thể truyền thông báo lỗi tùy chỉnh ở đối số thứ hai
  • Có thể thay đổi timeout test mặc định của scope hoặc module hiện tại bằng jest.setTimeout()setDefaultTimeout()

Bundler và tính năng build

  • Bun 1.2 hỗ trợ HTML import
    • Khi truyền tệp HTML vào tùy chọn static của Bun.serve, Bun sẽ tự động bundle các thẻ <script><link> trong HTML rồi public chúng thành static route
  • bun build --compile hỗ trợ cross-compilation
    • Có thể tạo binary Windows hoặc macOS từ Linux, và cũng hỗ trợ chiều ngược lại
    • Bản build cho Windows có thể đặt icon và dùng tùy chọn ẩn cửa sổ console
  • bun build --bytecode tạo bytecode cache
    • Có thể giúp thời gian khởi động của các ứng dụng như eslint nhanh gấp 2 lần
    • Tệp .jsc chứa bytecode cache của tệp .js tương ứng, và cần cả hai tệp để chạy
    • Bytecode cache có thể lớn gấp 8 lần mã nguồn, nên đổi lại việc cải thiện thời gian khởi động là dùng nhiều dung lượng đĩa hơn
  • Có thể chỉ định định dạng output CommonJS bằng bun build --format=cjs
    • Trước đây chỉ hỗ trợ ESM
    • Giúp dễ tạo thư viện hoặc ứng dụng nhắm tới các phiên bản Node.js cũ hơn
  • Cải thiện khả năng phát hiện CommonJS
    • Khi tệp mơ hồ, chỉ thị "use strict" ở đầu tệp sẽ được dùng như heuristic cuối cùng để xác định CommonJS
    • require.main === module được viết lại thành import.meta.main để có thể dùng cùng câu lệnh import
  • Plugin API được bổ sung hook onBeforeParse()
    • Phải được triển khai bằng N-API addon, không phải JavaScript
    • Có thể xử lý mã nguồn ngay trước khi parse với gần như không có overhead trong các ngôn ngữ biên dịch như Rust, C/C++ và Zig
    • Đây là API nâng cao dành cho tác giả plugin và framework
  • Các tùy chọn build cũng được mở rộng
    • Tiêm biến môi trường vào bundle bằng --env="PUBLIC_*"
    • Loại bỏ function call theo kiểu --drop=console
    • Thêm banner/footer
    • Kiểm tra danh sách tệp được nhúng trong standalone executable bằng Bun.embeddedFiles()
    • Bỏ qua annotation dead-code elimination sai bằng --ignore-dce-annotations
    • Cấu hình để không đưa dependency gói vào bundle bằng --packages=external

Bundling CSS

  • Bun 1.2 triển khai CSS parser và bundler mới
    • Được phát triển từ công trình của LightningCSS, rồi được viết lại từ Rust sang Zig và tích hợp với parser, bundler và runtime JavaScript/TypeScript của Bun
  • Với bun build ./index.css, có thể gộp nhiều tệp CSS cùng các tham chiếu @import, url, @font-face thành một tệp CSS duy nhất
  • Có thể import tệp .css từ mã JavaScript và TypeScript
    • CSS được import trong JavaScript module graph cùng các quy tắc @import sẽ được làm phẳng thành một tệp CSS theo từng entrypoint
  • API Bun.build() cũng có thể bundle CSS và JavaScript bằng cùng một API

Thêm API runtime Bun

  • Bun.serve() hỗ trợ static route thông qua thuộc tính static
    • Truyền đường dẫn làm key và đối tượng Response làm value
    • Static route nhanh hơn tối đa 40% so với xử lý trực tiếp trong handler fetch()
    • Phần body, header và status code của response được cache trong bộ nhớ nên không có JavaScript allocation hay garbage collection
    • Có thể tải lại static route bằng server.reload()
  • Bun.udpSocket() cung cấp UDP socket theo kiểu API của Bun
    • Cũng hỗ trợ node:dgram, nhưng Bun.udpSocket() là API hiện đại tương tự Bun.listen() hiện có
    • Có thể gửi nhiều UDP datagram bằng một syscall và xử lý OS backpressure
  • Bun.file() hỗ trợ delete(), unlink(), stat()
    • stat() trả về metadata có cùng dạng với đối tượng Stats của Node.js fs.stat()
    • Có thể dùng cùng API này cho cả file trên S3
  • Bun.color() cung cấp khả năng phân tích, chuẩn hóa và chuyển đổi màu sắc
    • Hỗ trợ CSS, ANSI color code, RGB, HSL v.v.
  • dns.prefetch() có thể lấy trước DNS record để làm nóng DNS cache khi khởi động
  • Các tiện ích khác
    • Bun.inspect.table(): trả về chuỗi dạng bảng như console.table
    • Bun.randomUUIDv7(): tạo monotonic UUID v7 phù hợp cho sắp xếp và cơ sở dữ liệu

Cải tiến client SQLite

  • Client SQLite tích hợp sẵn của Bun có thể ánh xạ kết quả truy vấn thành instance của class bằng query.as(Class)
    • Có thể gắn getter, setter và method
    • Vì lý do hiệu năng nên không hỗ trợ class constructor, default initializer và private field
    • Không quản lý quan hệ hay sinh SQL nên không phải ORM
  • query.iterate() xử lý bằng iterator thay vì nạp toàn bộ các hàng vào bộ nhớ cùng lúc
    • Bản thân đối tượng truy vấn cũng có thể duyệt bằng vòng lặp for
  • Khi bật tùy chọn strict, có thể bỏ qua tiền tố $, @, : trong tham số truy vấn
    • Nếu thiếu tham số sẽ ném lỗi
  • Có thể kiểm tra số hàng đã thay đổi và row ID được chèn cuối cùng từ kết quả db.run()
    • changes
    • lastInsertRowid
  • Tùy chọn safeIntegers sẽ trả về số nguyên 64 bit dưới dạng BigInt thay vì number bị cắt bớt
    • Có thể thiết lập ở cấp cơ sở dữ liệu hoặc cấp truy vấn
  • Có thể dùng cú pháp JavaScript using để tự động đóng statement và database khi scope kết thúc

Biên dịch và chạy C từ JavaScript

  • Bun 1.2 bổ sung hỗ trợ thử nghiệm để biên dịch và chạy C từ JavaScript
    • Sử dụng API cc() của bun:ffi
    • Đây là cách dùng system library của C từ JavaScript mà không cần build step riêng
  • Bun tích hợp sẵn tinycc
    • Không giống gcc hay clang, nó có thể biên dịch mã C đơn giản trong vài mili giây
    • Có thể biên dịch và chạy mã C khi cần
  • Cũng cung cấp mã C dùng N-API
    • Hoạt động chỉ với Bun mà không cần bước build node-gyp

Hỗ trợ musl và Alpine Linux

  • Bun 1.2 bổ sung bản build Bun cho các bản phân phối Linux dùng musl libc thay vì glibc
    • Có thể dùng trong các môi trường như Alpine Linux
    • Hỗ trợ Linux x64 và aarch64
  • Trong Docker có thể dùng image oven/bun:alpine
  • musl cho phép tạo image container nhỏ hơn, nhưng có xu hướng chậm hơn đôi chút so với bản glibc của Bun
    • Nếu không có lý do cụ thể thì nên dùng glibc

Tính năng ngôn ngữ JavaScript

  • Đã thêm hỗ trợ import attributes
    • Có thể import và chỉ rõ JSON, text, TOML v.v. như import json from "./package.json" with { type: "json" }
    • Cũng có thể dùng trong import() động
  • Hỗ trợ usingawait using
    • Khi ra khỏi scope, [Symbol.dispose] hoặc [Symbol.asyncDispose] sẽ được gọi để tự động dọn dẹp tài nguyên
    • Được hỗ trợ trong nhiều API của Bun như Bun.spawn(), Bun.serve(), Bun.connect(), Bun.listen(), bun:sqlite v.v.
  • API mới liên quan đến Promise
    • Promise.withResolvers(): tạo promise, resolve, reject cùng lúc
    • Promise.try(): bọc hàm đồng bộ hoặc bất đồng bộ thành promise
  • API về lỗi và mảng byte
    • Error.isError(): kiểm tra chính xác hơn một giá trị có phải Error hay không, kể cả khi prototype chain bị thao tác hoặc trong tình huống cross-realm của node:vm
    • Uint8Array.toBase64() / Uint8Array.fromBase64()
    • Uint8Array.toHex() / Uint8Array.fromHex()
  • Đã thêm iterator helper
    • map, flatMap, filter, take, drop, reduce, toArray, forEach, find
  • Hỗ trợ Float16Array
    • Mảng số thực dấu chấm động 16 bit có độ chính xác thấp hơn 32 bit nhưng hiệu quả bộ nhớ cao hơn

Thêm Web API

  • Hỗ trợ TextDecoderStreamTextEncoderStream
    • Đây là phiên bản streaming của TextDecoderTextEncoder
    • Trong Bun, TextEncoderStream nhanh hơn Node.js tối đa 30 lần
  • Hỗ trợ tùy chọn stream của TextDecoder
    • Có thể xử lý chunk như một phần của luồng lớn hơn ngay cả khi đó chưa phải UTF-8 code point hoàn chỉnh
  • Đã thêm phương thức bytes()
    • Trong Response, Blob, Bun.file() v.v., dữ liệu stream được trả về dưới dạng Uint8Array
    • Giảm bớt quy trình gọi arrayBuffer() rồi tạo Uint8Array như trước
  • Hỗ trợ upload fetch() dạng streaming
    • Hữu ích khi tải lên file lớn hoặc luồng dữ liệu chưa biết trước content length
  • Đã triển khai console.group()console.groupEnd()
  • Hỗ trợ URL.createObjectURL()
    • Có thể tạo URL từ Blob và dùng cho fetch(), Worker, import()
    • Worker script cũng đi qua Bun transpiler nên có thể dùng cú pháp TypeScript
  • AbortSignal.any() kết hợp nhiều AbortSignal, để khi một signal bị abort thì signal cha cũng bị abort

Thay đổi hành vi và lưu ý khi di chuyển

  • Thư mục làm việc của bun run đã thay đổi
    • Trước đây sử dụng thư mục làm việc hiện tại của shell
    • Trong Bun 1.2, thư mục cha của package.json được dùng làm thư mục làm việc của script
    • Đây là thay đổi nhằm đồng bộ với cách hoạt động của npmyarn
  • bun test giờ sẽ coi uncaught error hoặc rejection giữa các bài kiểm thử là lỗi thất bại
    • Trước đây những lỗi như vậy có thể không được xử lý là kiểm thử thất bại
  • server.stop() giờ trả về Promise<void>
    • Có thể chờ cho đến khi các kết nối HTTP đang xử lý được đóng lại
  • Bun.build() giờ sẽ reject khi thất bại, thay vì đưa lỗi vào logs của kết quả đã resolve
    • Nếu cần hành vi cũ, có thể đặt throw: false
  • bun -p nay trở thành alias của bun --print để tương thích với Node.js
    • Trước đây đây là alias của bun --port
  • Giá trị mặc định của bun build --sourcemap đã đổi từ inline source map sang linked source map
    • Nếu cần hành vi cũ, hãy dùng --sourcemap=inline

Cải thiện hiệu năng

  • Bun 1.2 bao gồm cải thiện hiệu năng trên nhiều đường chạy khác nhau
    • node:http2: nhanh gấp 2 lần
    • Tải lên S3 qua node:http: nhanh gấp 5 lần
    • path.resolve(): nhanh gấp 30 lần
    • Phân giải DNS của fetch(): nhanh gấp 2 lần
    • bun --hot: giảm một nửa mức sử dụng bộ nhớ
    • macOS fs.readdirSync(): đọc thư mục nhỏ nhanh hơn 5%
    • String.at(): nhanh hơn 44%
    • atob() với đầu vào chuỗi lớn: nhanh hơn tối đa 8 lần
    • Giải nén dữ liệu gzip của fetch(): nhanh hơn 30%
    • Buffer.from(string, "base64") với đầu vào lớn: nhanh hơn từ 6 đến 30 lần
    • JSON.parse() với đầu vào chuỗi lớn: nhanh hơn từ 2 đến 4 lần, với đầu vào object: nhanh hơn 6%
    • Thông lượng của một số ứng dụng Bun.serve(): tăng tối đa 2 lần
    • Error.captureStackTrace(): nhanh gấp 9 lần
    • fs.readFile() với tệp nhỏ: nhanh hơn tối đa 10%
    • console.log() với đối số chuỗi: nhanh hơn 50%
  • Trên Windows, JIT của JavaScriptCore được kích hoạt
    • Trước đây JIT chỉ khả dụng trên macOS và Linux
    • JavaScript trên Windows nhìn chung chạy nhanh hơn
    • Ví dụ, Object.entries() nhanh hơn 20%, Array.map() nhanh hơn 50%

Cài đặt và nâng cấp

  • Lệnh cài đặt mới
    • curl -fsSL https://bun.sh/install | bash
    • powershell -c "irm bun.sh/install.ps1 | iex"
    • npm install -g bun
    • brew tap oven-sh/bun rồi brew install bun
    • docker pull oven/bun
  • Với Bun đã được cài đặt, hãy nâng cấp bằng bun upgrade

1 bình luận

 
GN⁺ 2025-01-25
Các ý kiến trên Hacker News
  • Không hiểu vì sao lại đưa cơ sở dữ liệu bên thứ bathư viện S3 bên ngoài vào core/thư viện chuẩn
    Những thứ như vậy có lẽ hợp làm thư viện tùy chọn hơn; các runtime kiểu này cần chọn rất thận trọng những gì đưa vào thư viện chuẩn
    Ngay từ bây giờ đã có cảm giác đây là một dự án nhồi nhét mọi thứ như “bồn rửa nhà bếp”

    • Tôi nghĩ chính lập trường như vậy là một trong những lý do Bun được chú ý
      Cách tiếp cận kèm sẵn pin phổ biến ở nhiều nơi và là con đường được lựa chọn
      Cấu hình TypeScript cũng khó, Webpack, S3, Postgres, Jest, v.v. cũng vậy, nên cách tiếp cận file/stream được đơn giản hóa cũng khá thú vị
      Có lẽ chỉ cần chờ xem các nhà cung cấp triển khai phân tán sẽ xuất hiện thế nào
    • Theo tôi biết Bun đã nhận đầu tư VC, nên một lúc nào đó sẽ phải kiếm tiền; vì vậy tôi đoán có thể họ đang biến nó thành một trình chạy all-in-one để tạo ra một dạng khóa chặt vào nhà cung cấp nào đó
      Tất nhiên có thể tôi sai, nhưng việc đưa các phụ thuộc như vậy vào core/thư viện chuẩn thật sự không hợp lý lắm
    • Nhiều người đã nói điều tương tự với Jared, tác giả của Bun, nhưng quan điểm của Jared là Bun nên có sẵn mọi thứ mà một dự án mặc định cần
      Có vẻ anh ấy cho rằng nếu đưa vào core thì có thể tối ưu tốt hơn so với thư viện bên thứ ba
      Cá nhân tôi nghĩ đó là cách tiếp cận sai và cảm giác Jared đang quá tham vọng, nhưng rốt cuộc đây vẫn là dự án đam mê của anh ấy
    • Hoàn toàn đồng ý rằng thư viện tùy chọn sẽ tốt hơn
      Theo cách Bun diễn đạt thì “Bun hướng tới một runtime JavaScript ưu tiên cloud. Nghĩa là nó hỗ trợ tất cả công cụ và dịch vụ cần thiết để chạy ứng dụng production trên cloud”, nhưng câu này không tạo nhiều niềm tin cho tôi
      Lựa chọn thiết kế cụ thể này trông còn tệ hơn cả Node
    • Cái này là để phục vụ dịch vụ được quản lý của Bun
      Vấn đề của phần mềm được VC hậu thuẫn luôn là các tính năng tích hợp kiểu này cố gắng cung cấp một thứ gì đó độc quyền, nói cách khác là tạo ra sự phụ thuộc
  • Trải nghiệm dùng Bun của tôi đến giờ rất tốt
    Mỗi khi cấu hình TypeScript/Jest/React/Webpack cho dự án mới, tôi luôn ngại vì các breaking change chỗ này chỗ kia; còn với Bun thì nó tự xử lý và với nhu cầu của tôi thì cứ chạy được một cách không đau đớn
    Khó nói gì về việc tích hợp các thư viện bên thứ ba như S3, SQL, nhưng ít nhất có vẻ họ đang tập trung vào những thứ phổ biến nhất và được yêu cầu nhiều nhất
    Tôi thích vì nó mang lại sự hợp lý mà hệ sinh thái công cụ Node.js từng cần

    • Tôi tò mò Bun tạo ra khác biệt gì trong stack công nghệ frontend nói ở trên
    • Các dự án React/TypeScript cũng đã được cấu hình tốt bằng Vite hoặc Next.js rồi
      Có vẻ bạn đang đánh giá thấp việc các công cụ khác cũng đã tiến bộ rất nhiều trong thời gian qua
    • Bun rất tuyệt
      Với tôi nó giống như mã gian lận năng suất
      Vì ChatGPT chưa hiểu Bun tốt nên có hơi mất năng suất một chút, nhưng tôi vẫn thích Bun
  • Có nhiều điểm hay, nhưng tôi lo rằng một số hành vi mặc định có đang đi quá xa theo hướng hành vi ẩn như phép thuật hay không
    Khi dùng new Response(s3.file(...)), thay vì tải file S3 xuống server rồi gửi cho người dùng, Bun chuyển hướng người dùng tới URL được ký sẵn của file S3
    Với thiết lập mặc định thì đây là lựa chọn khá bất ngờ, và hoàn toàn không rõ phải tắt thế nào khi không muốn trực tiếp phơi bày bucket S3

    • Tôi tôn trọng lĩnh vực Bun đang cố khai phá, nhưng nếu theo dõi tác giả trên Twitter thì sẽ thấy các quyết định khá thiên về kết quả ngắn hạn và sự tiện lợi, còn tác động sâu xa của các hành vi ma thuật đó thì thường bị xem nhẹ
      Ban đầu tôi rất kỳ vọng vào dự án này, nhưng nhìn vào các quyết định thiết kế rời rạc được công khai trên mạng xã hội, mà cá nhân tôi thấy nhiều cái không tốt, thì tôi không còn tin vào định hướng dài hạn
      Nếu vẫn giữ ở v0.x thì ổn, nhưng một khi đã phát hành 1.0, tiêu chuẩn để mở rộng bề mặt API lẽ ra phải cao hơn nhiều
    • Chỉ cần truyền stream vào response là được
      Response(file.stream())
    • Tôi hiểu vì sao họ làm vậy, nhưng tôi không thích thiết kế này
      Cá nhân tôi thấy nó giống một hành vi có tác dụng phụ mạnh, và khi đọc thì trông như nó trả về nội dung file chứ không phải URL
      Dù vậy tôi cũng tò mò việc lộ bucket thì có gì khó chịu
      Vì là URL được ký sẵn nên nó đâu cấp quyền truy cập rộng rãi
      Một API tường minh hơn như Response((file(...).getPresignedURL())) sẽ tốt hơn, hoặc có tùy chọn bật hành vi này bằng biến môi trường hay cấu hình Bun thì có lẽ ổn hơn
  • Kèm sẵn pin tạo ra khác biệt lớn
    Đó cũng là lý do tôi thích việc các Web API như Fetch API, Service Workers, Web Components, ES6+, WebRTC giờ đã trở thành native trên cả hai runtime V8 và WebKit
    Tuy nhiên cũng phải có giới hạn
    S3 có thể là đi hơi xa, nhưng SQL driver thì hợp lý
    Dù vậy, vấn đề là nên đưa vào đến đâu
    Có rất nhiều cơ sở dữ liệu, vậy có phải đưa driver của một nửa trong số đó vào không?
    Chỉ đến mức đó thôi cũng đã thêm nhiều mã, có thể làm file thực thi chậm đi
    Ngoài ra, đưa những API nhạy cảm như vậy vào Bun cũng có thể khiến bảo mật bị bỏ sót
    Hãy tưởng tượng một script nào đó hoặc một vấn đề về đường dẫn khiến eval được chạy, rồi Bun upload toàn bộ file nguồn lên S3 cá nhân; đến lúc đó là coi như xong

    • Tôi tò mò không biết câu “nhiều mã hơn làm file thực thi chậm đi” có thật sự đúng không
      Tôi từng nghĩ tùy vào cách mã được load lúc runtime, mức này có thể gần như bỏ qua được
      Nếu chỉ khi thấy câu lệnh import thì việc load mã mới được kích hoạt, thì thực tế chẳng có overhead tốc độ nào phải không?
      Ngay cả khi được link tĩnh, tôi cũng không rõ vì sao chỉ vì mã tồn tại mà file thực thi lại chậm đi đến mức đáng quan tâm
      Chắc có chuyện file thực thi cần load vào bộ nhớ lớn hơn theo đúng nghĩa đen, nhưng có lẽ không phải kiểu chậm đi có thể cảm nhận được
    • Trước đây trên HN từng có thảo luận về lý do trình duyệt không hỗ trợ SQLite như một công dân hạng nhất, và lập luận đó cũng có thể áp dụng cho Bun
      Cốt lõi là ai chịu trách nhiệm bảo trì thư viện, và khi SQLite thay đổi thì thư viện đó sẽ được thay đổi như thế nào
      Nếu SQLite có lỗi thì trong Bun sẽ sửa ra sao?
      Những phiên bản nào cần được đưa bản sửa vào?
      Bản vá của runtime có thể thay đổi hành vi của mã chạy bên trên nó; vậy xử lý thế nào nếu người dùng đã workaround theo hành vi cũ?
      Ở một mức độ nào đó đây là các vấn đề có thể giải quyết, nhưng cũng đi kèm nhược điểm
      Đến một lúc nào đó, nó không còn là runtime nữa mà trở thành nền tảng, kéo theo những trách nhiệm và vấn đề khác
    • Tôi nghĩ lập luận ủng hộ việc đưa S3 vào là có nhiều dịch vụ lưu trữ đối tượng triển khai API tương thích S3
      Nó không phải chuẩn web thực sự, nhưng cũng là thứ nhiều người trên thực tế coi như chuẩn để tương thích theo
    • Dù nói “nhiều mã hơn làm file thực thi chậm đi”, bài viết có benchmark đúng nghĩa, và nói Bun nhanh gấp đôi giải pháp Node.js nhanh nhất
  • Gần đây một khách hàng của tôi dùng Bun trong production
    Tôi nghe nói trải nghiệm phát triển với Bun tốt đến mức khó tin nhờ tốc độ và sự đơn giản
    Trải nghiệm nhà phát triển về lâu dài đóng vai trò rất lớn
    Nếu codebase hoặc quy trình lộn xộn, bạn sẽ mất người giỏi trừ khi trả mức đãi ngộ cỡ FAANG

  • Tôi vẫn chưa dùng thử Bun, nhưng danh sách tính năng dài đến mức khiến tôi hoài nghi liệu tất cả có vững chắc và không lỗi hay không
    Tôi hy vọng mình sai, và dự định sẽ thử chạy trong một dự án sau này
    Từ góc nhìn quản lý dự án, tôi hơi bối rối vì sao lại dành thời gian cho hỗ trợ S3 khi nó còn chưa tương thích 100% với Node.js
    Next.js là một hệ sinh thái rất lớn, nên nếu kéo được khách hàng Next.js sang thì có thể tăng trưởng lớn hơn nhiều so với hỗ trợ S3

    • Tương thích 100% là một chiến thắng tốt về mặt marketing, nhưng phần đuôi dài của khả năng tương thích có thể không tạo khác biệt mấy với người dùng trung bình
      Hằng ngày bạn thực sự dùng bao nhiêu trong toàn bộ bề mặt API của Node.js?
      Bạn thực sự phụ thuộc bao nhiêu vào các edge case kỳ quặc trong đó?
    • Cụm “từ góc nhìn quản lý dự án” giả định rằng ta biết dự án là gì
      Những người làm việc trên đó cũng không phải robot
      Có việc cần thời gian để nắm bắt, và trong lúc đó họ cũng có thể làm việc khác
      Cũng không phải một người làm tất cả mọi thứ
      Nói “kéo khách hàng Next.js sang thì sẽ tăng trưởng hơn”, nhưng tăng trưởng hướng tới điều gì?
      Điều đó không kiếm ra tiền
      Đây là một dự án được VC hậu thuẫn, và mục tiêu không phải là cung cấp Bun miễn phí để có được mọi người dùng trên thế giới
    • Điều khiến tôi đặc biệt lăn tăn khi nghi ngờ liệu danh sách tính năng dài có vững chắc và không lỗi hay không là việc nó được viết bằng Zig
      Zig có mức an toàn bộ nhớ rất thấp
      Nếu tham chiếu một biến không còn sống, thay vì lỗi segmentation, nó truy cập vào một vùng bộ nhớ tùy ý không liên quan
      Nghe nói ngay cả trong chế độ debug và safe cũng vậy[0]
      Việc đặt lên trên một hệ thống lifetime bộ nhớ đánh dấu tên biến là đã chết và chặn truy cập nếu nó đã chết khó đến vậy sao?
      Cuối cùng lại thành “đừng dùng hành vi không xác định”[1]
      Vì vậy tôi không muốn đặt bất cứ thứ gì làm bằng Zig ở những nơi như web server phơi ra Internet
      [0] : https://news.ycombinator.com/item?id=41720995
      [1] : https://github.com/ziglang/zig/issues/16467#issuecomment-164...
    • Nó không quá vững chắc, cũng không phải không có lỗi
      Năm ngoái tôi đã thử dùng và nó liên tục crash
    • Mục nói rằng họ đã sửa lỗi bun add không giữ nguyên khoảng trắng và thụt lề trong package.json, và giờ giữ nguyên được cả kiểu thụt lề kỳ quặc đến đâu, khá buồn cười
      Không biết ai yêu cầu chuyện này, và vì sao họ nghĩ đáng để viết mã cho nó
  • Import HTML thật ấn tượng và hay ho
    Trong Bun 1.2, họ hỗ trợ import HTML, và nói rằng có thể thay thế toàn bộ toolchain frontend bằng một câu lệnh import duy nhất
    Bạn có thể bắt đầu bằng cách truyền import HTML vào tùy chọn static của Bun.serve

    import homepage from "./index.html";
    
    Bun.serve({  
      static: {  
        "/": homepage,  
      },
    
      async fetch(req) {  
        // ... api requests  
      },  
    });  
    
    • Tôi tò mò ví dụ điều này giúp thay thế Vite như thế nào
      Có thể load các plugin theo từng framework như hot module replacement, tiền xử lý CSS, trình biên dịch Vue SFC không?
      Việc phục vụ file tĩnh thì không hẳn là mới, nên có vẻ tôi đang bỏ sót điều gì đó
  • Tôi từng nghĩ không có dự án nào được định sẵn sẽ thất bại nhiều như một lựa chọn cạnh tranh thay thế cho Node.js, nhưng dùng thử một lần hóa ra lại là quyết định đúng
    Tôi phải viết nhiều script độc lập để xử lý việc cập nhật file văn bản và SQLite DB, và có thể dùng ngay TypeScript, bun:sqlite [1], bun $ Shell [2] mà không cần file cấu hình hay quản lý dependency npm cục bộ
    Sau đó tôi cũng thử dùng cho các dự án JS/TypeScript mới, và cả bundler tích hợp sẵn [3] lẫn hỗ trợ test [4] đều hữu ích, cài dependency cũng xong ngay tức thì
    Mọi thứ chạy nhanh và dùng được ngay thực sự là một cải thiện chất lượng cuộc sống, và giờ Bun đã trở thành lựa chọn đầu tiên của tôi cho dự án JS mới
    [1] https://bun.sh/docs/runtime/shell
    [2] https://bun.sh/docs/api/sqlite
    [3] https://bun.sh/docs/bundler
    [4] https://bun.sh/docs/cli/test

    • Tôi cũng vậy
      Trước đây tôi nghiêng về kiểu “mấy thứ này sang năm npm cũng sẽ có hết, vậy thì có ý nghĩa gì”
      Cuối cùng tôi đã thử Bun và thật sự bất ngờ
      Khi những yếu tố nhỏ trong trải nghiệm lập trình viên tích lại, khác biệt trở nên rất lớn
      Trong dự án của tôi, Bun thật sự mang cảm giác như thế hệ tiếp theo
  • Cách đây không lâu tôi lần đầu dùng thử Bun và trải nghiệm rất tuyệt
    Tất cả dự án của tôi đều cấu hình Webpack hoặc Vite để dùng TypeScript; một khi đã cấu hình thì gần như chạy hoàn hảo, nhưng bản thân việc cấu hình khá phiền và không đáng cho các script nhỏ
    Trái lại, Bun chạy được ngay
    Tôi đã loay hoay 10–30 phút với một công cụ nào đó tên là node-ts hay gì đó để cố chạy TS “trực tiếp” từ CLI, rồi phải đối mặt với những thông báo kinh khủng như “không phải là module”, “không thể dùng import/require”, “ESM/CJS”, và đã thử hết các cách sửa phổ biến như đổi loại module trong package.json, đổi tsconfig, đổi cách dùng import/require
    Khi đang cố chạy một script khoảng 200 dòng, đến nước cuối cùng tôi chuyển sang Bun thì nó chạy rất tuyệt

    • Node.js mới nhất giờ cũng hỗ trợ “chạy TS luôn” trong các trường hợp như vậy
      node --experimental-strip-types index.ts
      Nếu không dùng Node mới nhất thì gói tsx hoạt động tốt với tôi
      Tốt hơn ts-node
      Tuy nhiên cả hai lựa chọn đều chỉ bỏ qua thông tin kiểu, và Bun cũng vậy
  • Tôi thích hướng đi này
    Đặc biệt, việc đưa vào hỗ trợ native cho S3 và Postgres là rất hợp lý, vì nó có thể tồn tại như một phương án thay thế cho tình trạng hiện nay là “tự lắp ghép framework”
    Trong mọi web framework như Rails và Laravel, đây là tiêu chuẩn, và hệ sinh thái JS cũng có thể hưởng lợi lớn từ điều này
    Tôi nghĩ bước tiếp theo là trải nghiệm test mặc định tốt hơn, có thể làm tốt migration và quản lý schema, cũng như thiết lập factory