Tại sao không nên sử dụng Bun trong sản xuất?
Bun xứng đáng nhận được sự công nhận. Nó nhanh chóng, tham vọng và đã làm thay đổi hệ sinh thái JavaScript vốn đã trì trệ. Tốc độ đổi mới thú vị đã tăng lên đáng kể sau khi Bun cho thấy một trải nghiệm tích hợp có thể như thế nào. Node.js, từng bảo thủ một cách nghiêm ngặt, bỗng chốc đã có những cập nhật lớn: hỗ trợ TypeScript gốc, fetch trong lõi, chế độ theo dõi tích hợp, một công cụ kiểm thử chính thức, hỗ trợ .env. Bun đã thắp lên ngọn lửa, và toàn bộ hệ sinh thái đã trở nên nóng hơn.
Đó là một thắng lợi cho tất cả mọi người. Nhưng sản xuất là nơi mà sự lạc quan gặp phải hỗn loạn.
“Trở thành tất cả” hay “trở thành bền vững”?
Khi Bun 1.0 ra mắt, mục tiêu không chỉ là “một runtime khác”. Nó hướng đến việc thay thế Node và hàng tá công cụ xung quanh: npx, dotenv, cross-env, nodemon, pm2, ws, node-fetch/isomorphic-fetch, tsc, Babel, ts-node, tsx. Vào thời điểm đó, câu chuyện tích hợp mọi thứ nghe có vẻ như là tương lai.
Hai năm sau, nhiều tính năng nổi bật đó đã xuất hiện trong Node. Những phần mà Node không hấp thụ (như bundling, quản lý gói,...) có thể được coi là tốt hơn khi để trong tay người dùng, nơi mà sự chuyên môn hóa và cải tiến nhanh chóng phát triển (ví dụ: Rolldown hay LightningCSS). Không phải mọi thứ đều nên được tích hợp vào một runtime, vì một cách tôn trọng, không một đội ngũ nào có thể xuất sắc trong mọi thứ cùng một lúc.
Hiệu suất: nhanh nhưng…
Hào quang ra mắt của Bun là tốc độ. Một số biểu đồ họ quảng cáo về Bun từ đầu đã gây tranh cãi - chẳng hạn như so sánh với Yarn v1 khi Yarn v3 đã có mặt - và mặc dù những biểu đồ đó vẫn được nổi bật hai năm sau, nhưng chúng thường thiếu ngữ cảnh. Hãy xem “Bun nhanh hơn Vitest 5 lần”. Nghe có vẻ ấn tượng, cho đến khi bạn lưu ý rằng Vitest và Jest cố tình thêm overhead cho tính cách ly của bài kiểm tra, giúp các bài kiểm tra trở nên đáng tin cậy và dễ gỡ lỗi hơn. Đó là một phần lý do tại sao Jest đã giành được vị trí hàng đầu vào thời điểm đó.
Bỏ qua những đánh đổi đó không chỉ không cung cấp thông tin mà còn gây hiểu lầm. Tại mức tốt nhất, đó là không đầy đủ. Tại mức tệ nhất, là tiếp thị không trung thực.
Trong khi đó, phần còn lại của hệ sinh thái không ngừng cải tiến. Node, npm, pnpm, Vitest, và những công cụ khác vẫn tiếp tục phát triển. Thêm vào đó, các sáng kiến cộng đồng (ví dụ: e18e) đang thúc đẩy các chiến thắng về hiệu suất trên toàn bộ hệ sinh thái, không chỉ riêng Bun.
Tính di động & khóa chặt: dễ bắt đầu, khó dừng lại
Bun cung cấp các API không tiêu chuẩn mà có thể cảm thấy tuyệt vời trong ngày đầu tiên - nhưng lại âm thầm ràng buộc bạn với chính Bun. Thật dễ dàng để bun init, bun test, và dựa vào các trợ giúp như Bun.file, Bun.serve, và Bun.write. Việc di chuyển sang môi trường khác sau này? Chúc bạn may mắn.
Hãy xem yêu cầu lâu dài “Hỗ trợ Vitest”. Nó đã được mở trước khi Bun 1.0 ra mắt và vẫn còn mở cho đến ngày hôm nay. Nếu bạn muốn thử nghiệm Bun một cách nghiêm túc, bạn sẽ bị đẩy vào việc sử dụng công cụ kiểm thử của Bun. Điều đó tiện lợi, cho đến khi bạn muốn quay trở lại Node hoặc một runtime khác và phải đối mặt với việc di chuyển khó khăn.
Phiên bản & độ ổn định: số phiên bản là một hợp đồng
Sau khi thông báo 1.0, Bun đã phát hành hàng chục phiên bản 1.0.x bao gồm tính năng mới - không chỉ là sửa lỗi. Điều đó thực sự không phải là cách mà phiên bản semver hoạt động; nó gần giống với trò đùa nổi tiếng trên internet về “phiên bản tự hào”:
PROUD.DEFAULT.SHAME
PROUD cho những thay đổi mà bạn tự hào, DEFAULT cho các bản phát hành thường lệ, SHAME cho những sửa lỗi mà bạn hy vọng không ai chú ý.
Nếu các bản phát hành “sửa lỗi” bao gồm các tính năng mới, thì điều gì ngăn cản một bản phát hành “nhỏ” bao gồm các thay đổi phá vỡ? Thực tế, đó chính xác là những gì đã xảy ra - ví dụ, Bun 1.1 đã thay đổi giá trị mặc định của NODE_ENV, thay đổi cách mà các xuất khẩu có điều kiện được giải quyết, và 1.1.26 đã thay đổi idleTimeout trong node:http.
Đối với các đội ngũ sản xuất, số phiên bản là một hợp đồng. Chúng báo hiệu khi nào an toàn để nâng cấp và khi nào cần chuẩn bị cho tác động. Nếu những tín hiệu đó không thể được tin tưởng, việc nâng cấp trở thành một trò chơi may rủi.
So sánh với Node: hiện tại, Node phát hành nhanh chóng trên các phiên bản hiện tại, vì vậy bạn có thể thử nghiệm các tính năng mới một cách nhanh chóng. Nhưng cũng có dòng LTS đã được kiểm chứng và siêu ổn định (vẫn nhận được những thứ thú vị từ thời gian này!), và mô hình kép đó là rất quan trọng. Bạn có thể thử nghiệm ở rìa, nhưng khi bạn cần độ tin cậy, nhịp điệu LTS mang lại cho bạn chính xác điều đó. Sự cân bằng đó chính là điều làm cho Node sẵn sàng cho sản xuất.
Lựa chọn thiết kế đáng nghi
-
Lifecycle scripts: Bun không chạy chúng theo mặc định (điều này một phần giải thích cho “cài đặt nhanh hơn” - ít công việc hơn được thực hiện). Bỏ qua các script theo mặc định là một ý tưởng tuyệt vời giúp cải thiện an toàn cho hệ sinh thái, và vì lý do này, các trình quản lý gói khác cũng nhanh chóng áp dụng nó. Vấn đề: Bun duy trì một danh sách cho phép tùy ý các “gói phổ biến” mà script của chúng được chạy. Nếu bạn có trong danh sách,
postinstallcủa bạn sẽ được thực hiện - tuyệt vời cho bạn (hoặc… cho ai đó đã xâm nhập tài khoản npm của bạn). Nếu bạn không có, người dùng Bun cần phải thực hiện các bước thêm. Đó là một sự kết hợp hoàn hảo giữa an ninh bị xâm phạm và sự thuận tiện. -
JSONC trong
package.json: các bình luận là rất hữu ích, nhưng việc làm chopackage.jsonkhông phải là JSON sẽ phá vỡ tính tương thích với mọi công cụ khác. Đó là sự phân mảnh, không phải là sự tiến bộ. -
Lockfile nhị phân: Bun ban đầu phát hành một lockfile nhị phân khiến việc xem xét PR trở nên mờ mịt - một kịch bản lý tưởng cho bất kỳ ai cố gắng lén lút mã độc qua. Nó sau đó đã chuyển sang định dạng văn bản, nhưng định dạng vẫn kém dễ đọc hơn pnpm hoặc Yarn. Các lockfile khó kiểm tra làm suy yếu văn hóa an ninh.
Lộ trình điều khiển bởi YOLO và thiếu tôn trọng lẫn nhau
Bun thường cảm thấy như nó phát hành bất cứ điều gì đã thắng trong cuộc khảo sát trên Twitter tuần trước - nhanh chóng.
Tốc độ mà Bun phát hành tính năng có thể gây nghiện, nhưng nó cũng dẫn đến sự vượt quá: một cờ tsconfig.json tự chế, jsxSideEffects, đã được thêm vào Bun 1.2.22. Hãy nghĩ về điều đó: cờ này đã được đưa vào không gian tên của TypeScript bởi một dự án khác ngoài TypeScript. Nếu nhóm TS muốn cờ đó sau này, sự nhầm lẫn và các thay đổi phá vỡ là không thể tránh khỏi.
Điều này cũng khiến tôi nhớ đến cuộc tranh cãi về LightningCSS khi thay vì hợp tác với dự án Rust hiện tại, tác giả của nó thậm chí đã cung cấp các binding C và hỗ trợ, Bun đã chuyển nó sang Zig và giữ một bản sao riêng (tôi đã đề cập đến điều gì về người dùng và sự bền vững? Tôi nghĩ vậy…).
Đó không phải là sự hợp tác - đó là sự sao chép mà không có sự hồi đáp. Dù giấy phép cho phép điều gì, đạo đức và sự tin tưởng trong hệ sinh thái rất quan trọng.
Nó vẽ nên một bức tranh về một dự án quan tâm đến việc đi theo con đường riêng của nó hơn là xây dựng cùng với cộng đồng rộng lớn hơn, và đó không phải là nền tảng mà tôi sẽ khuyên bạn dựa vào để xây dựng hệ thống sản xuất.
Tín hiệu bảo trì: các trình theo dõi vấn đề không nói dối
Tính đến thời điểm hiện tại, Node - môi trường thực thi hỗ trợ hầu hết toàn cầu, bao gồm cả bàn chải đánh răng của bạn, có khoảng 1.7k vấn đề mở. Bun, còn trẻ và mặc dù phổ biến, nhưng ít được áp dụng hơn, có khoảng 4.7k vấn đề. Số liệu thô không bao giờ cho chúng ta toàn bộ câu chuyện, nhưng sự mất cân bằng là rất rõ ràng. Node gánh vác một khối lượng công việc toàn cầu nhưng vẫn quản lý được một lượng backlog ít hơn. Bun, vẫn còn trong giai đoạn đầu phát triển, đã bị quá tải. Điều này không chính xác truyền cảm hứng cho sự tự tin cho các khối lượng công việc sản xuất.
Khi nào tôi sẽ sử dụng Bun?
Điều này không phải là “không bao giờ sử dụng Bun.” Nó là “sử dụng nó một cách khôn ngoan.”
Những ứng dụng tốt:
- Các nguyên mẫu và sân chơi nơi mà DX tích hợp giúp bạn nhanh hơn.
- Các CLIs hoặc script đơn mục đích nơi tính di động không quan trọng.
Những điều cần lưu ý nếu bạn áp dụng nó:
- Tuân thủ các tiêu chuẩn; tách biệt các chi tiết của Bun.
- Ưu tiên công cụ di động.
- Ghi phiên bản, đọc kỹ changelog và thử nghiệm nâng cấp như bạn làm với việc di chuyển cơ sở dữ liệu.
Những gì Bun có thể làm để xứng đáng với ghế sản xuất
- Đối xử với semver như một hợp đồng; tính năng trong các bản phát hành nhỏ, thay đổi phá vỡ trong các bản phát hành lớn.
- Thiết lập một lịch trình LTS và phát hành rõ ràng để các đội biết khi nào là an toàn để áp dụng.
- Làm cho các thông số kiểm tra trung thực: so sánh như với như, giải thích các đánh đổi.
- Ưu tiên hợp tác hơn là sao chép: đóng góp upstream, phối hợp công khai.
- Phát hành các tính năng mới với một quy trình cẩn thận, chú ý đến hệ sinh thái.
Kết luận
Sản xuất phụ thuộc vào sự bền vững, khả năng dự đoán và sự tin tưởng. Hiện tại, những lựa chọn thiết kế, phiên bản và tiếp thị của Bun đã làm suy yếu những nền tảng đó. Nếu những điều này quan trọng với bạn, hãy suy nghĩ kỹ trước khi xây dựng trên Bun ngày hôm nay.
Đừng hiểu lầm tôi: Bun đã làm cho hệ sinh thái tốt hơn chỉ bằng cách tồn tại. Nó đã nhắc nhở mọi người cảm giác tuyệt vời của DX, và đã khơi dậy Node để phát hành các tính năng đã được chờ đợi từ lâu. Và nó vẫn đang tiếp tục làm như vậy! Tôi thực sự biết ơn vì điều đó.