Bun 1.2 发布
Bun 是一个用于构建和测试全栈 JavaScript 和 TypeScript 应用的完整工具包。如果你还不熟悉 Bun,可以通过 Bun 1.0 的博客文章了解更多。
Bun 1.2 更新亮点
Bun 1.2 是一个重大更新,我们非常兴奋地与大家分享。以下是 Bun 1.2 的主要变化:
- Node.js 兼容性:Bun 在 Node.js 兼容性方面取得了重大进展。
- 内置 S3 对象存储 API:新增了
Bun.s3,支持与 S3 存储的交互。 - 内置 Postgres 客户端:新增了
Bun.sql,支持 Postgres 数据库操作(MySQL 支持即将推出)。 bun install使用基于文本的锁文件:bun.lock取代了之前的二进制锁文件。
此外,Bun 1.2 还让 Express 框架的性能提升了 3 倍。
Node.js 兼容性
Bun 旨在成为 Node.js 的直接替代品。在 Bun 1.2 中,我们开始为每次 Bun 的更改运行 Node.js 测试套件。自那时起,我们已经修复了数千个错误,以下 Node.js 模块在 Bun 中的测试通过率超过了 90%。
如何衡量兼容性?
在 Bun 1.2 中,我们改变了测试和改进 Bun 与 Node.js 兼容性的方式。以前,我们根据用户报告的 GitHub 问题来优先修复 Node.js 的 bug。虽然这解决了用户遇到的实际问题,但这种方式过于被动,难以实现 100% 的 Node.js 兼容性。
于是我们想到:为什么不直接运行 Node.js 的测试套件呢?
在 Bun 中运行 Node.js 测试
Node.js 的测试套件包含数千个测试文件,大部分位于 test/parallel 目录中。虽然“直接运行”这些测试听起来很简单,但实际上比想象中复杂得多。
内部 API
许多测试依赖于 Node.js 的内部实现细节。例如,以下测试中,getnameinfo 被模拟为总是出错,以测试 dns.lookupService() 的错误处理。
const { internalBinding } = require("internal/test/binding");
const cares = internalBinding("cares_wrap");
const { UV_ENOENT } = internalBinding("uv");
cares.getnameinfo = () => UV_ENOENT;
为了在 Bun 中运行这个测试,我们不得不用自己的模拟替换内部绑定。
Bun.dns.lookupService = (addr, port) => {
const error = new Error(`getnameinfo ENOENT ${addr}`);
error.code = "ENOENT";
error.syscall = "getnameinfo";
throw error;
};
错误信息
还有一些 Node.js 测试会检查错误信息的精确字符串。虽然 Node.js 通常不会更改错误信息,但它们并不保证在版本之间不会发生变化。
const common = require("../common");
const assert = require("assert");
const cp = require("child_process");
assert.throws(
() => {
cp.spawnSync(process.execPath, [__filename, "child"], { argv0: [] });
},
{
code: "ERR_INVALID_ARG_TYPE",
name: "TypeError",
message: 'The "options.argv0" property must be of type string.' + common.invalidArgTypeHelper([]),
}
);
为了解决这个问题,我们不得不修改一些测试的断言逻辑,改为检查 name 和 code,而不是 message。
{
code: "ERR_INVALID_ARG_TYPE",
name: "TypeError",
message: 'The "options.argv0" property must be of type string.' + common.invalidArgTypeHelper([]),
}
虽然我们尽量匹配 Node.js 的错误信息,但有时我们也会提供更有帮助的错误信息,只要 name 和 code 相同即可。
目前的进展
我们已经将数千个 Node.js 测试文件移植到 Bun 中。这意味着每次我们对 Bun 进行更改时,都会运行 Node.js 测试套件以确保兼容性。
每天,我们都在为 Bun 添加越来越多的 Node.js 测试通过率,我们很快会分享更多关于 Node.js 兼容性的进展。
除了修复现有的 Node.js API,我们还添加了对以下 Node.js 模块的支持。
node:http2 服务器
你现在可以使用 node:http2 来创建 HTTP/2 服务器。HTTP/2 也是 gRPC 服务器的必要条件,Bun 现在也支持 gRPC 服务器。之前,Bun 只支持 HTTP/2 客户端。
import { createSecureServer } from "node:http2";
import { readFileSync } from "node:fs";
const server = createSecureServer({
key: readFileSync("key.pem"),
cert: readFileSync("cert.pem"),
});
server.on("stream", (stream, headers) => {
stream.respond({
":status": 200,
"content-type": "text/html; charset=utf-8",
});
stream.end("<h1>Hello from Bun!</h1>");
});
server.listen(3000);
在 Bun 1.2 中,HTTP/2 服务器的性能比 Node.js 快 2 倍。当我们为 Bun 添加新 API 时,我们会花很多时间优化性能,确保它不仅能用,而且更快。
node:dgram
你现在可以使用 node:dgram 绑定和连接到 UDP 套接字。UDP 是一种低级别的不可靠消息协议,通常用于遥测提供商和游戏引擎。
import { createSocket } from "node:dgram";
const server = createSocket("udp4");
const client = createSocket("udp4");
server.on("listening", () => {
const { port, address } = server.address();
for (let i = 0; i < 10; i++) {
client.send(`data ${i}`, port, address);
}
server.unref();
});
server.on("message", (data, { address, port }) => {
console.log(`Received: data=${data} source=${address}:${port}`);
client.unref();
});
server.bind();
这使得像 DataDog 的 dd-trace 和 @clickhouse/client 这样的包可以在 Bun 1.2 中正常工作。
node:cluster
你可以使用 node:cluster 来生成多个 Bun 实例。这通常用于通过跨多个 CPU 核心运行任务来提高吞吐量。
以下是一个使用 cluster 创建多线程 HTTP 服务器的示例:
- 主工作进程生成
n个子工作进程(通常等于 CPU 核心数)。 - 每个子工作进程监听相同的端口(使用
reusePort)。 - 传入的 HTTP 请求在子工作进程之间进行负载均衡。
import cluster from "node:cluster";
import { createServer } from "node:http";
import { cpus } from "node:os";
if (cluster.isPrimary) {
console.log(`Primary ${process.pid} is running`);
// 启动与 CPU 数量相等的工作进程
for (let i = 0; i < cpus().length; i++) {
cluster.fork();
}
cluster.on("exit", (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} exited`);
});
} else {
// 传入的请求由工作进程池处理,而不是主工作进程
createServer((req, res) => {
res.writeHead(200);
res.end(`Hello from worker ${process.pid}`);
}).listen(3000);
console.log(`Worker ${process.pid} started`);
}
注意,reusePort 仅在 Linux 上有效。在 Windows 和 macOS 上,操作系统不会像预期的那样对 HTTP 连接进行负载均衡。
node:zlib
在 Bun 1.2 中,我们重写了整个 node:zlib 模块,从 JavaScript 改为原生代码。这不仅修复了许多 bug,还使其性能比 Bun 1.1 快 2 倍。
我们还为 node:zlib 添加了对 Brotli 的支持,这在 Bun 1.1 中是缺失的。
import { brotliCompressSync, brotliDecompressSync } from "node:zlib";
const compressed = brotliCompressSync("Hello, world!");
compressed.toString("hex"); // "0b068048656c6c6f2c20776f726c642103"
const decompressed = brotliDecompressSync(compressed);
decompressed.toString("utf8"); // "Hello, world!"
使用 V8 API 的 C++ 插件
如果你想在 JavaScript 代码中使用 C++ 插件,最简单的方法是使用 N-API。
然而,在 N-API 出现之前,一些包使用了 Node.js 内部的 V8 C++ API。这使得事情变得复杂,因为 Node.js 和 Bun 使用不同的 JavaScript 引擎:Node.js 使用 V8(Chrome 使用的引擎),而 Bun 使用 JavaScriptCore(Safari 使用的引擎)。
以前,像 cpu-features 这样依赖这些 V8 API 的 npm 包在 Bun 中无法工作。
require("cpu-features")();
dyld[94465]: missing symbol called
fish: Job 1, 'bun index.ts' terminated by signal SIGABRT (Abort)
为了解决这个问题,我们进行了前所未有的工程努力,在 JavaScriptCore 中实现了 V8 的公共 C++ API,使得这些包可以在 Bun 中“直接运行”。这个实现非常复杂,我们甚至写了一篇 三部分的博客 来解释我们是如何在不使用 V8 的情况下支持 V8 API 的。
在 Bun 1.2 中,像 cpu-features 这样的包可以直接导入并运行。
$ bun index.ts
{
arch: "aarch64",
flags: {
fp: true,
asimd: true,
// ...
},
}
V8 C++ API 的支持非常复杂,因此大多数包仍然会有一些缺失的功能。我们将继续改进支持,以便像 node-canvas@v2 和 node-sqlite3 这样的包在未来能够正常工作。
node:v8
除了 V8 C++ API,我们还添加了对使用 node:v8 进行堆快照的支持。
import { writeHeapSnapshot } from "node:v8";
// 将堆快照写入当前工作目录,文件名为 `Heap-{date}-{pid}.heapsnapshot`
writeHeapSnapshot();
在 Bun 1.2 中,你可以使用 getHeapSnapshot 和 writeHeapSnapshot 来读取和写入 V8 堆快照。这使得你可以使用 Chrome DevTools 来检查 Bun 的堆。
Express 性能提升 3 倍
虽然兼容性对于修复 bug 很重要,但它也帮助我们修复了 Bun 中的性能问题。
在 Bun 1.2 中,流行的 express 框架处理 HTTP 请求的速度比 Node.js 快 3 倍。这是通过改进与 node:http 的兼容性以及优化 Bun 的 HTTP 服务器实现的。
S3 支持与 Bun.s3
Bun 旨在成为一个面向云的 JavaScript 运行时。这意味着它支持你在云中运行生产应用所需的所有工具和服务。
现代应用通常将文件存储在对象存储中,而不是本地的 POSIX 文件系统。当终端用户将文件附件上传到网站时,文件不会存储在服务器的本地磁盘上,而是存储在 S3 存储桶中。将存储与计算解耦可以避免一系列可靠性问题:磁盘空间不足、繁忙的 I/O 导致的高 p95 响应时间,以及共享文件存储的安全问题。
S3 是云中对象存储的事实标准。S3 API 由多种云服务实现,包括 Amazon S3、Google Cloud Storage、Cloudflare R2 等。
这就是为什么 Bun 1.2 添加了对 S3 的内置支持。你可以使用与 Web 标准兼容的 API(如 Blob)从 S3 存储桶中读取、写入和删除文件。
从 S3 读取文件
你可以使用新的 Bun.s3 API 来访问默认的 S3Client。客户端提供了一个 file() 方法,返回对 S3 文件的懒引用,这与 Bun 的 File API 相同。
import { s3 } from "bun";
const file = s3.file("folder/my-file.txt");
// file instanceof Blob
const content = await file.text();
// 或者:
// file.json()
// file.arrayBuffer()
// file.stream()
比 Node.js 快 5 倍
Bun 的 S3 客户端是用原生代码编写的,而不是 JavaScript。与使用 @aws-sdk/client-s3 的 Node.js 相比,Bun 从 S3 存储桶下载文件的速度快 5 倍。
将文件写入 S3
你可以使用 write() 方法将文件上传到 S3。非常简单:
import { s3 } from "bun";
const file = s3.file("folder/my-file.txt");
await file.write("hello s3!");
// 或者:
// file.write(new Uint8Array([1, 2, 3]));
// file.write(new Blob(["hello s3!"]));
// file.write(new Response("hello s3!"));
对于较大的文件,你可以使用 writer() 方法获取一个文件写入器,进行多部分上传,这样你就不必担心细节。
import { s3 } from "bun";
const file = s3.file("folder/my-file.txt");
const writer = file.writer();
for (let i = 0; i < 1000; i++) {
writer.write(String(i).repeat(1024));
}
await writer.end();
预签名 URL
当你的生产服务需要让用户上传文件到服务器时,通常更可靠的做法是让用户直接上传到 S3,而不是通过服务器作为中介。
为了实现这一点,你可以使用 presign() 方法生成文件的预签名 URL。这会生成一个带有签名的 URL,允许用户安全地上传特定文件到 S3,而不会暴露你的凭证或授予他们不必要的访问权限。
import { s3 } from "bun";
const url = s3.presign("folder/my-file.txt", {
expiresIn: 3600, // 1 小时
acl: "public-read",
});
使用 Bun.serve()
由于 Bun 的 S3 API 扩展了 File API,你可以使用 Bun.serve() 通过 HTTP 提供 S3 文件。
import { serve, s3 } from "bun";
serve({
port: 3000,
async fetch(request) {
const { url } = request;
const { pathname } = new URL(url);
// ...
if (pathname === "/favicon.ico") {
const file = s3.file("assets/favicon.ico");
return new Response(file);
}
// ...
},
});
当你使用 new Response(s3.file(...)) 时,Bun 不会将 S3 文件下载到服务器并发送给用户,而是将用户重定向到 S3 文件的预签名 URL。
Response (0 KB) {
status: 302,
headers: Headers {
"location": "https://s3.amazonaws.com/my-bucket/assets/favicon.ico?...",
},
redirected: true,
}
这节省了内存、时间和下载文件到服务器的带宽成本。
使用 Bun.file()
如果你想使用与本地文件系统相同的代码访问 S3 文件,可以使用 s3:// URL 协议引用它们。这与使用 file:// 引用本地文件的概念相同。
import { file } from "bun";
async function createFile(url, content) {
const fileObject = file(url);
if (await fileObject.exists()) {
return;
}
await fileObject.write(content);
}
await createFile("s3://folder/my-file.txt", "hello s3!");
await createFile("file://folder/my-file.txt", "hello posix!");
使用 fetch()
你甚至可以使用 fetch() 从 S3 读取、写入和删除文件。
// 上传到 S3
await fetch("s3://folder/my-file.txt", {
method: "PUT",
body: "hello s3!",
});
// 从 S3 下载
const response = await fetch("s3://folder/my-file.txt");
const content = await response.text(); // "hello s3!"
// 从 S3 删除
await fetch("s3://folder/my-file.txt", {
method: "DELETE",
});
使用 S3Client
当你导入 Bun.s3 时,它会返回一个默认客户端,该客户端使用已知的环境变量(如 AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY)进行配置。
import { s3, S3Client } from "bun";
// s3 instanceof S3Client
你也可以创建自己的 S3Client,然后将其设置为默认客户端。
import { S3Client } from "bun";
const client = new S3Client({
accessKeyId: "my-access-key-id",
secretAccessKey: "my-secret-access-key",
region: "auto",
endpoint: "https://<account-id>.r2.cloudflarestorage.com",
bucket: "my-bucket",
});
// 将默认客户端设置为你的自定义客户端
Bun.s3 = client;
Postgres 支持与 Bun.sql
与对象存储一样,生产应用通常需要的另一个数据存储是 SQL 数据库。
从一开始,Bun 就内置了 SQLite 客户端。SQLite 非常适合小型应用和快速脚本,你不需要担心设置生产数据库的麻烦。
在 Bun 1.2 中,我们通过引入 Bun.sql 扩展了 Bun 对 SQL 数据库的支持,这是一个内置的 SQL 客户端,支持 Postgres。我们还有一个 pull request 即将添加 MySQL 支持。
使用 Bun.sql
你可以使用 Bun.sql 通过标签模板字面量运行 SQL 查询。这允许你将 JavaScript 值作为参数传递给 SQL 查询。
最重要的是,它会自动转义字符串并使用预处理语句,以防止 SQL 注入。
import { sql } from "bun";
const users = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 65 },
];
await sql`
INSERT INTO users (name, age)
VALUES ${sql(users)}
`;
读取行同样简单。结果以对象数组的形式返回,键为列名。
import { sql } from "bun";
const seniorAge = 65;
const seniorUsers = await sql`
SELECT name, age FROM users
WHERE age >= ${seniorAge}
`;
console.log(seniorUsers); // [{ name: "Bob", age: 65 }]
比其他客户端快 50%
Bun.sql 是用原生代码编写的,具有以下优化:
- 自动预处理语句
- 查询流水线
- 二进制协议支持
- 连接池
- 结构缓存
这些优化就像《魔兽世界》中的增益效果一样叠加在一起。结果是,Bun.sql 在读取行时比使用 Node.js 中最流行的 Postgres 客户端快 50%。
从 postgres.js 迁移到 Bun.sql
Bun.sql 的 API 灵感来自于流行的 postgres.js 包。这使得你可以轻松地将现有代码迁移到使用 Bun 的内置 SQL 客户端。
import { postgres } from "postgres";
import { postgres } from "bun";
const sql = postgres({
host: "localhost",
port: 5432,
database: "mydb",
user: "...",
password: "...",
});
const users = await sql`SELECT name, age FROM users LIMIT 1`;
console.log(users); // [{ name: "Alice", age: 25 }]
Bun 是一个包管理器
Bun 是一个与 npm 兼容的包管理器,可以轻松安装和更新你的 node 模块。你可以使用 bun install 来安装依赖项,即使你使用的是 Node.js 作为运行时。
用 bun install 替换 npm install
$ npm install
$ bun install
在 Bun 1.2 中,我们对包管理器进行了最大的更改。
bun.lockb 的问题
从一开始,Bun 就使用了二进制锁文件:bun.lockb。
与其他使用基于文本的锁文件(如 JSON 或 YAML)的包管理器不同,二进制锁文件使得 bun install 比 npm 快近 30 倍。
然而,我们发现使用二进制锁文件有很多小问题。首先,你无法在 GitHub 和其他平台上查看锁文件的内容。这很糟糕。
如果你收到一个外部贡献者的拉取请求,更改了 bun.lockb 文件,你会信任它吗?可能不会。
这也使得工具难以读取锁文件。例如,像 Dependabot 这样的依赖管理工具需要一个 API 来解析锁文件,而我们没有提供。
Bun 将继续支持 bun.lockb 很长时间。然而,出于这些原因,我们决定在 Bun 1.2 中切换到基于文本的锁文件作为默认选项。
引入 bun.lock
在 Bun 1.2 中,我们引入了一个新的基于文本的锁文件:bun.lock。
你可以使用 --save-text-lockfile 标志迁移到新的锁文件。
bun install --save-text-lockfile
bun.lock 是一个 JSONC 文件,支持注释和尾随逗号。
// bun.lock
{
"lockfileVersion": 0,
"packages": [
["express@4.21.2", /* ... */, "sha512-..."],
["body-parser@1.20.3", /* ... */],
/* ... and more */
],
"workspaces": { /* ... */ },
}
这使得在拉取请求中查看差异变得更加容易,尾随逗号也减少了合并冲突的可能性。
对于没有锁文件的新项目,Bun 将生成一个新的 bun.lock 文件。
对于已有 bun.lockb 文件的项目,Bun 将继续支持二进制锁文件,无需迁移到新的锁文件。我们将继续支持二进制锁文件很长时间,因此你可以继续使用像 bun add 和 bun update 这样的命令,它们将更新你的 bun.lockb 文件。
bun install 速度提升 30%
你可能会认为,在我们迁移到基于文本的锁文件后,bun install 会变慢。错了!
大多数软件项目随着功能的增加而变慢,但 Bun 不是这样的项目。我们花了很多时间调整和优化 Bun,使得 bun install 甚至更快。
这就是为什么在 Bun 1.2 中,bun install 比 Bun 1.1 快 30%。
package.json 支持 JSONC
你是否曾经在 package.json 中添加了某些内容,几个月后却忘记了为什么?或者想向你的团队成员解释为什么某个依赖需要特定版本?或者因为逗号导致 package.json 文件出现合并冲突?
通常这些问题是因为 package.json 是一个 JSON 文件,这意味着你不能在其中使用注释或尾随逗号。
{
"dependencies": {
// 这会导致语法错误
"express": "4.21.2"
}
}
这是一个糟糕的体验。现代工具如 TypeScript 允许在它们的配置文件中使用注释和尾随逗号,例如 tsconfig.json,这很棒。我们还询问了社区的意见,似乎现状需要改变。
在 Bun 1.2 中,你可以在 package.json 中使用注释和尾随逗号。它直接生效。
{
"name": "app",
"dependencies": {
// 我们需要 0.30.8,因为 0.30.9 有一个 bug
"drizzle-orm": "0.30.8", /* <- 尾随逗号 */
},
}
由于有许多工具读取 package.json 文件,我们添加了对 require() 或 import() 这些带有注释和尾随逗号的文件的支持。你不需要更改代码。
const pkg = require("./package.json");
const {
default: { name },
} = await import("./package.json");
由于这在 JavaScript 生态系统中并不广泛支持,我们建议你“自担风险”使用此功能。然而,我们认为这是正确的方向:让事情对你来说更容易。
.npmrc 支持
在 Bun 1.2 中,我们添加了对读取 npm 配置文件 .npmrc 的支持。
你可以使用 .npmrc 来配置 npm 注册表和范围包。这在企业环境中通常是必要的,因为你可能需要认证到私有注册表。
@my-company:registry=https://packages.my-company.com
@my-org:registry=https://packages.my-company.com/my-org
Bun 会在项目的根目录和你的主目录中查找 .npmrc 文件。
bun run --filter
你现在可以使用 bun run --filter 同时在多个工作区中运行脚本。
bun run --filter='*' dev
这将在所有匹配通配符模式的工作区中并发运行 dev 脚本。它还会交错每个脚本的输出,因此你可以看到每个工作区的输出。
你也可以传递多个过滤器给 --filter,并且你可以直接使用 bun 而不是 bun run。
bun --filter 'api/*' --filter 'frontend/*' dev
bun outdated
你现在可以使用 bun outdated 查看哪些依赖项已过时。
它会显示你的 package.json 依赖项列表,以及哪些版本已过时。“更新”列显示下一个符合 semver 的版本,“最新”列显示最新版本。
如果你注意到有特定的依赖项需要更新,可以使用 bun update。
bun update @typescript-eslint/parser # 更新到 "7.18.0"
bun update @typescript-eslint/parser --latest # 更新到 "8.2.0"
你也可以过滤你想检查更新的依赖项。只需确保引用模式,以免你的 shell 将其扩展为通配符模式!
bun outdated "is-*" # 检查 is-even, is-odd 等
bun outdated "@discordjs/*" # 检查 @discordjs/voice, @discordjs/rest 等
bun outdated jquery --filter="foo" # 在 `foo` 工作区中检查 jquery
bun publish
你现在可以使用 bun publish 发布 npm 包。
它是 npm publish 的直接替代品,支持许多相同的功能,例如:
- 读取
.npmrc文件进行认证。 - 打包 tarball,考虑多个目录中的
.gitignore和.npmignore文件。 - OTP / 双因素认证。
- 处理
package.json字段的边缘情况,如bin、files等。 - 小心处理缺失的
README文件。
我们还添加了对发布有用的命令,例如:
bun pm whoami,打印你的 npm 用户名。bun pm pack,创建一个 npm 包 tarball 以便发布或本地安装。
bun patch
有时,你的依赖项有 bug 或缺少功能。虽然你可以 fork 该包,进行更改并发布它,但这需要很多工作。如果你不想维护一个 fork 呢?
在 Bun 1.2 中,我们添加了对依赖项打补丁的支持。以下是它的工作原理:
- 运行
bun patch <package>来打补丁。 - 编辑
node_modules/<package>目录中的文件。 - 运行
bun patch --commit <package>来保存你的更改。就这样!
Bun 会在 patches/ 目录中生成一个 .patch 文件,其中包含你的更改,该文件会在 bun install 时自动应用。然后你可以将补丁文件提交到你的仓库,并与你的团队分享。
例如,你可以创建一个补丁来用你自己的代码替换依赖项。
diff --git a/index.js b/index.js
index 832d92223a9ec491364ee10dcbe3ad495446ab80..2a61f0dd2f476a4a30631c570e6c8d2d148d419a 100644
--- a/index.js
+++ b/index.js
@@ -1,14 +1 @@
- 'use strict';
-
- var isOdd = require('is-odd');
-
- module.exports = function isEven(i) {
- return !isOdd(i);
- };
+ module.exports = (i) => (i % 2 === 0)
Bun 从 node_modules 目录中克隆该包,并使用其自身的副本。这允许你安全地编辑包目录中的文件,而不会影响共享文件缓存。
更易用
我们还对 bun install 进行了许多小的改进,使其更易用。
CA 证书
你现在可以为 bun install 配置 CA 证书。这在需要从公司的私有注册表安装包或使用自签名证书时非常有用。
[install]
# CA 证书作为字符串
ca="-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
# CA 证书文件的路径。该文件可以包含多个证书。
cafile="path/to/cafile"
如果你不想更改 bunfig.toml 文件,你也可以使用 --ca 和 --cafile 标志。
bun install --cafile=/path/to/cafile
bun install --ca="..."
如果你使用的是现有的 .npmrc 文件,你也可以在那里配置 CA 证书。
cafile=/path/to/cafile
ca="..."
bundleDependencies 支持
你现在可以在 package.json 中使用 bundleDependencies。
{
"bundleDependencies": ["is-even"]
}
这些是你期望已经存在于 node_modules 文件夹中的依赖项,它们不会像其他依赖项一样被安装。
bun add 尊重 package.json 缩进
我们修复了一个 bug,即 bun add 不会尊重 package.json 中的缩进。Bun 现在会保留 package.json 的缩进,无论它有多奇怪。
bun add is-odd
// 一个故意奇怪的 package.json
{
"dependencies": {
"is-even": "1.0.0",
"is-odd": "1.0.0"
}
}
--omit=dev|optional|peer 支持
Bun 现在支持 bun install 的 --omit 标志,允许你省略开发、可选或对等依赖项。
bun install --omit=dev # 省略开发依赖项
bun install --omit=optional # 省略可选依赖项
bun install --omit=peer # 省略对等依赖项
bun install --omit=dev --omit=optional # 省略开发
