简介Bun v1.3 全栈 JavaScript 运行时发布配套代码包面向全栈开发团队、追求高性能的企业级应用开发者及希望从 Node.js 迁移的工程师。该版本将前端热重载、生产构建、MySQL/PostgreSQL/SQLite 数据库客户端与 Redis 客户端整合进单一运行时Redis 吞吐量达 250 万次/秒约为 ioredis 的 7.9 倍并优化了 WebSocket、包管理与测试调试能力可减少多工具切换成本。资源包共 5 个文件以 3 个 html 页面为主辅以 .inscode 与 .gitignore 配置压缩后约 11KB结构轻量便于快速查看示例页面与项目配置。目前已有 124 人学习下载。读者可借助其中的演示页面理解 Bun 全栈能力的前端呈现方式结合配置项了解项目初始化与忽略规则为搭建高性能全栈应用或评估迁移方案提供参考。1. Bun v1.3 全栈 JS 运行时一个二进制文件把开发服务器、打包器和测试跑通如果你之前对 Bun 的印象还停留在「一个更快的 npm 替代品」那 v1.3 这个版本值得重新看一眼。它把运行时、包管理器、打包器、测试运行器、开发服务器全部塞进同一个二进制文件里你不需要再维护tsconfigjest.configwebpack.confignodemon.json这一整套配置文件。装完 Bunbun run dev就能起一个带热更新的全栈服务bun test直接跑测试bun build出产物。对独立开发者和中小团队来说这意味着从零到能跑的原型时间从半天压缩到十几分钟。这篇笔记不讲发布会通稿只讲我实际把 Bun v1.3 用在一个全栈项目里的路径怎么装、怎么配、哪些参数必须调、哪些地方会翻车。适合已经会写 JS/TS、想减少工具链维护成本的从业者。2. 从零跑通 Bun v1.3安装、初始化与第一个全栈服务2.1 安装 Bun 与验证运行时版本Bun 的安装方式在不同系统上略有差异但核心逻辑都是把单个二进制放到 PATH 里。Linux 和 macOS 用官方脚本Windows 目前推荐用 WSL 或原生安装包。我一般先确认版本因为 v1.3 的很多 API 在早期版本里不存在版本不对后面全是玄学报错。# Linux / macOS 安装 curl -fsSL https://bun.sh/install | bash # 验证版本必须确认是 1.3.x bun --version # 输出示例1.3.0 # 查看内置工具链是否齐全 bun --help安装脚本会把bun放到~/.bun/bin如果终端提示找不到命令检查~/.bashrc或~/.zshrc里有没有把该目录加进 PATH。这一步看起来简单但我在 CI 环境里踩过坑容器镜像里预装的 Bun 是 1.0 版本bun run能跑但Bun.serve的某些选项不生效排查了半小时才发现是版本问题。所以任何环境里第一步永远是bun --version。2.2 用 bun init 生成项目骨架Bun 自带初始化命令不需要npm init再手动改。它会根据当前目录情况生成package.json、tsconfig.json和入口文件。我一般会加--yes跳过交互在脚本化场景里更稳。# 创建项目目录并初始化 mkdir bun-fullstack-demo cd bun-fullstack-demo bun init --yes # 查看生成的文件 ls -la # package.json tsconfig.json index.ts README.md生成的tsconfig.json默认已经针对 Bun 运行时做了优化比如moduleResolution设为bundlertypes里包含bun-types。如果你从 Node 项目迁移过来不要直接复制原来的tsconfig否则类型解析会出问题。package.json里默认的module字段是index.ts这意味着 Bun 直接跑 TS 文件不需要先编译成 JS。这是 Bun 和 Node 最本质的区别之一它内置了 TS 转译器用的是 Zig 写的原生解析器速度比ts-node快一个数量级。2.3 写一个带 API 和静态页面的最小全栈服务Bun v1.3 的Bun.serve支持直接返回 HTML、JSON 和文件不需要额外装 Express 或 Fastify。下面这个例子同时提供 API 路由和静态页面能直接跑起来。// index.ts const server Bun.serve({ port: 3000, // 开发模式下开启热更新 development: true, async fetch(req) { const url new URL(req.url); // API 路由返回 JSON if (url.pathname /api/health) { return Response.json({ status: ok, runtime: Bun ${Bun.version}, timestamp: Date.now(), }); } // 静态页面直接返回 HTML if (url.pathname /) { return new Response( !DOCTYPE html html headtitleBun v1.3 Demo/title/head body h1Bun v1.3 全栈服务已启动/h1 p idstatus检查 API 中.../p script fetch(/api/health) .then(r r.json()) .then(d document.getElementById(status).textContent JSON.stringify(d)); /script /body /html, { headers: { Content-Type: text/html; charsetutf-8 } } ); } return new Response(Not Found, { status: 404 }); }, }); console.log(服务运行在 http://localhost:${server.port});启动命令是bun run index.ts或者直接在package.json里配dev: bun run index.ts然后bun run dev。development: true这个参数很关键开启后 Bun 会启用热重载修改文件后浏览器自动刷新同时错误页面会显示源码位置。生产环境要把它设为false否则会暴露堆栈信息。port默认是 3000如果被占用会报EADDRINUSE改成 3001 或让 Bun 自动选端口传port: 0即可。2.4 用 bun test 跑第一个测试用例Bun 内置的测试运行器兼容 Jest 的 API但不需要装jest、ts-jest、types/jest这一堆东西。测试文件命名规则是*.test.ts或*_test.ts放在项目任意位置都行。// health.test.ts import { describe, expect, test, beforeAll, afterAll } from bun:test; let server: ReturnTypetypeof Bun.serve; beforeAll(() { // 启动一个测试用的服务实例 server Bun.serve({ port: 0, // 让系统分配空闲端口 fetch(req) { const url new URL(req.url); if (url.pathname /api/health) { return Response.json({ status: ok }); } return new Response(Not Found, { status: 404 }); }, }); }); afterAll(() { server.stop(); }); describe(健康检查接口, () { test(返回 200 和 ok 状态, async () { const res await fetch(http://localhost:${server.port}/api/health); expect(res.status).toBe(200); const data await res.json(); expect(data.status).toBe(ok); }); test(未知路径返回 404, async () { const res await fetch(http://localhost:${server.port}/unknown); expect(res.status).toBe(404); }); });运行bun test即可输出格式和 Jest 类似但启动时间通常在 100ms 以内。port: 0是测试里的常用技巧避免和开发服务器抢端口。beforeAll和afterAll的用法和 Jest 一致但 Bun 的测试运行器是原生实现的不支持 Jest 的全部插件生态比如jest.mock的某些高级用法需要改用mock.module。如果你的项目重度依赖 Jest 插件迁移前先跑一遍测试看兼容性。3. Bun v1.3 的打包器与包管理bun build 和 bun install 的参数怎么调3.1 bun install 的缓存机制与 lockfile 策略Bun 的包管理器是它最早出圈的功能v1.3 里安装速度依然是最快的但真正影响团队协作的是 lockfile 策略。Bun 默认生成bun.lockb二进制格式v1.3 开始也支持bun.lock文本格式后者在 code review 时更友好。# 安装依赖使用文本 lockfile bun install --save-text-lockfile # 从零安装忽略缓存 bun install --no-cache # 只安装生产依赖 bun install --production # 强制重新解析所有依赖版本 bun install --force--save-text-lockfile这个参数我建议在团队项目里默认开启因为二进制 lockfile 在 Git diff 里看不出变化合并冲突时基本没法手动解决。文本 lockfile 虽然体积大一点但可读性和可维护性好得多。--no-cache在 CI 里偶尔需要比如缓存损坏导致安装出诡异错误时清掉重来比排查快。--production用于构建镜像阶段能减少最终产物体积。注意 Bun 的缓存目录默认在~/.bun/install/cache如果磁盘空间紧张可以用BUN_INSTALL_CACHE_DIR环境变量改到其他位置。3.2 bun build 打包全栈项目的三个关键参数bun build是 v1.3 里被低估的功能。它不只是打包前端代码还能把服务端代码打包成单个可执行文件。下面是一个典型的前端打包命令。# 打包前端入口输出到 dist 目录 bun build ./src/index.tsx \ --outdir ./dist \ --target browser \ --minify \ --sourcemapexternal \ --splitting \ --format esm--target browser告诉 Bun 按浏览器环境解析依赖会自动 polyfill 或排除 Node 内置模块。--minify开启压缩生产环境必加。--sourcemapexternal生成独立的 sourcemap 文件方便线上排查但不会增大主包体积。--splitting开启代码分割对多页面应用很重要否则所有路由的代码会打成一个巨大文件。--format esm输出 ES 模块格式现代浏览器都支持。如果你要打包服务端代码成可执行文件用--target bun和--compile# 打包成单个可执行文件 bun build ./index.ts --compile --outfile ./my-server # 运行产物 ./my-server--compile会把 Bun 运行时和你的代码一起打包生成的文件可以直接在没装 Bun 的机器上运行。这个特性在部署时非常省事不需要目标机器有 Node 或 Bun 环境。但要注意如果代码里用了动态import()或读取外部文件打包后路径会变需要用import.meta.dir来定位资源。3.3 用 bun run 管理脚本与并行任务bun run不只是npm run的替代品它支持并行执行和依赖声明。在package.json里可以这样配{ scripts: { dev: bun run --watch index.ts, build: bun build ./src/index.tsx --outdir ./dist --minify, test: bun test, check: bun run typecheck bun run test, typecheck: bunx tsc --noEmit } }--watch参数让 Bun 监听文件变化并自动重启比nodemon轻量得多。bunx是 Bun 版的npx可以直接跑 npm 包里的命令不需要先全局安装。bun run check会按顺序执行typecheck和test如果typecheck失败就不会跑测试这在 CI 里能省时间。注意bun run执行脚本时用的是 Bun 运行时不是 Node所以脚本里可以直接用Bun.file、Bun.write这些 API。4. 避坑与排查Bun v1.3 迁移中容易翻车的五个地方4.1 现象bun install 后 node_modules 里缺少某些包原因Bun 默认使用硬链接和全局缓存来加速安装某些包如果缓存损坏或权限不对硬链接会失败但安装命令不报错。解决先bun install --no-cache强制重新下载如果还不行删掉node_modules和bun.lockb再装。检查~/.bun/install/cache的磁盘权限确保当前用户有写权限。4.2 现象Bun.serve 的 development 模式在 Docker 里不生效原因development: true依赖文件系统监听Docker 容器里 inotify 的默认限制可能不够。解决在docker run时加--ulimit nofile65536:65536或者在宿主机上调整fs.inotify.max_user_watches。如果还不行改用轮询模式在Bun.serve里传watch: { mode: poll }代价是 CPU 占用略高。4.3 现象bun test 报错 “Cannot find module bun:test”原因测试文件被其他工具比如 VS Code 的 TS 插件用 Node 的类型定义解析了找不到 Bun 特有的模块。解决在tsconfig.json的compilerOptions.types里加上bun-types并确保moduleResolution是bundler。如果用的是 monorepo每个子包的tsconfig都要加不能只加根目录的。4.4 现象bun build --compile 生成的二进制文件运行时报 “ENOENT”原因代码里用了相对路径读取文件比如fs.readFileSync(./config.json)打包后工作目录变了。解决改用import.meta.dir拼接绝对路径或者把配置文件通过--define注入成常量。如果必须读外部文件用Bun.file(import.meta.dir /config.json)。4.5 现象从 Node 迁移后 process.env 读不到变量原因Bun 默认不自动加载.env文件需要显式指定或使用--env-file参数。解决启动时加bun run --env-file.env index.ts或者在代码里用Bun.env代替process.envBun 会自动读取.env。注意.env.local和.env.production的加载顺序和 Node 生态的dotenv不同迁移时要把环境变量文件整理清楚。5. 进阶技巧用 Bun v1.3 的 SQLite 和 S3 API 做全栈数据层Bun v1.3 内置了bun:sqlite和Bun.s3这两个 API 让全栈项目不需要额外装数据库驱动和对象存储 SDK。下面是一个用 SQLite 做数据持久化、用 S3 兼容接口存文件的例子。// db.ts import { Database } from bun:sqlite; const db new Database(app.db, { create: true }); // 建表IF NOT EXISTS 保证幂等 db.run( CREATE TABLE IF NOT EXISTS posts ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, content TEXT, created_at INTEGER DEFAULT (unixepoch()) ) ); // 预编译语句避免 SQL 注入 const insertPost db.prepare( INSERT INTO posts (title, content) VALUES (?, ?) RETURNING id, title, created_at ); const listPosts db.prepare( SELECT id, title, created_at FROM posts ORDER BY created_at DESC LIMIT ? ); export function createPost(title: string, content: string) { return insertPost.get(title, content); } export function getPosts(limit 20) { return listPosts.all(limit); }bun:sqlite的 API 和better-sqlite3很像但不需要编译原生模块安装即用。db.prepare返回的语句对象可以重复执行性能比每次拼 SQL 好。RETURNING子句在 SQLite 3.35 支持Bun 内置的版本足够新。注意unixepoch()是 SQLite 的函数返回秒级时间戳前端展示时要乘 1000。// storage.ts const s3 new Bun.S3Client({ accessKeyId: Bun.env.S3_ACCESS_KEY!, secretAccessKey: Bun.env.S3_SECRET_KEY!, bucket: my-app-bucket, endpoint: Bun.env.S3_ENDPOINT, // 兼容 MinIO 等自建服务 }); export async function uploadFile(key: string, file: File) { await s3.write(key, file.stream(), { type: file.type, // 设置缓存头减少重复请求 cacheControl: public, max-age31536000, }); return s3.presign(key, { expiresIn: 3600 }); } export async function getFileUrl(key: string) { return s3.presign(key, { expiresIn: 3600 }); }Bun.S3Client兼容 AWS S3 协议所以 MinIO、Cloudflare R2 这些都能用。presign生成带签名的临时 URL适合前端直接上传或下载。expiresIn单位是秒默认 86400我一般设 3600 避免链接被滥用。注意Bun.env读取环境变量时如果变量不存在会返回undefined加!是告诉 TS 这里一定有值但运行时如果真没有会报错所以.env文件要配好。验证这套数据层是否正常可以写一个集成测试// db.test.ts import { test, expect, beforeEach } from bun:test; import { Database } from bun:sqlite; let db: Database; beforeEach(() { // 每个测试用独立的内存数据库互不干扰 db new Database(:memory:); db.run(CREATE TABLE posts (id INTEGER PRIMARY KEY, title TEXT)); }); test(插入并查询帖子, () { db.run(INSERT INTO posts (title) VALUES (?), [测试标题]); const row db.query(SELECT title FROM posts WHERE id 1).get(); expect(row).toEqual({ title: 测试标题 }); });用:memory:做测试数据库是 SQLite 的经典用法速度快且不留痕迹。db.query和db.prepare的区别是前者每次返回新语句后者可复用。测试里用哪个都行但生产代码里预编译语句更合适。我自己的习惯是任何新项目先用 Bun 跑通最小闭环再逐步把 Node 生态的依赖替换成 Bun 内置 API。替换过程中遇到不兼容的包不要硬改先用bunx跑原工具等 Bun 生态跟上再换。这套路径帮我省掉了大量配置时间但前提是版本必须锁在 1.3.x并且每次升级前跑一遍完整测试。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
腾讯开源WeKnora:企业级RAG知识库与自进化机制实战解析 1. 先把话说清楚:WeKnora 到底是个什么项目 老实说,这两年 RAG 相关的开源项目我看了不下几十个,大部分都是“套壳 LangChain 向量库 前端问答”三件套,做到后面你会发现,Demo 跑得通,一上生产就各种别扭… · 2026/9/26 17:48:51
XTUOJ 1757 wave2题解:正弦波图形输出的坐标映射与调试技巧 1. 先搞懂XTUOJ 1757的题意再动手XTUOJ这段时间因为“世界杯”主题的刷题活动热闹了不少,我是顺着榜单往下刷的,结果卡在1757这道题上。题目名字就叫wave2,一眼看过去像是某个系列的第二版,但真正打开编辑器准备动笔的时候才发现&… · 2026/9/26 17:48:45
MyBatis TypeHandler从入门到实战:搞定JSON、枚举与自定义类型映射 1. TypeHandler到底解决了什么麻烦先说个我踩过的真实场景。有一年做电商项目,订单表里有个ext_info字段,存的是商品快照的JSON字符串。Java实体类里想直接用一个Map<String, Object>去接,结果查询出来一直是String,还得手动… · 2026/9/26 17:48:45
递归自我提升(RSP):AGI内生演化的工程实践指南 1. 这不是科幻小说里的桥段,而是正在实验室里跑通的工程现实“递归自我提升”这六个字听起来像哲学课上的思辨命题,或者科幻电影里反派AI启动终极协议时的倒计时音效。但如果你最近翻过arXiv上几篇来自DeepMind、Anthropic或OpenAI内部团队的预印本&… · 2026/9/26 18:17:19
Codex JS逆向工业化:一键部署签名Skill实战 1. 这不是“魔法”,是 JS 逆向工程的工业化落地Codex 这个词最近在爬虫圈和前端安全圈反复刷屏,但很多人一看到“Codex 逆向”四个字,第一反应是——这又是个玄学黑盒?是不是得先啃完 V8 引擎源码、手写 AST 解析器、再把 WebAsse… · 2026/9/26 18:17:19
WEEE电子废弃物符号识别:从数据集构建到YOLOv8训练全流程 简介:一套面向电子设计、PCB Layout与产品认证人员的WEEE回收标识矢量资源包,内含符合欧盟WEEE指令要求的带交叉线垃圾桶图标,可用于产品包装、用户手册、设备外壳标记以及电路板丝印等合规场景。压缩包共3个文件,包含EPS、PNG与H… · 2026/9/26 18:17:10
Substrate实战:从零构建自定义区块链应用链 第一次在区块链技术讨论里看到Substrate这个词时,我还以为误入了哪篇生物化学论文。等到自己动手把它跑起来,我才意识到它和“基质”“底物”还真有点神似——你给出一堆可插拔的模块,它帮你把整条链的骨架撑起来。Substrate是由Parity开发的… · 2026/9/26 18:17:10
业务系统接入AI助手:独立会话服务架构与实践 不需要不假思索地冲去新开一个仓库,但要说“直接加个聊天模块就完事”,同样会踩大坑。这个问题的答案取决于你系统的规模、团队配置、AI 功能未来的迭代频率,以及你敢不敢让模型的 3 秒延迟拖住你核心接口的线程池。我先把结论放在前面&#… · 2026/9/26 18:17:10
GitHub 热榜项目周榜(2026-06-06):用 TaoToken 统一 Key 接入热门 AI 工具 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 18:17:10
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46