Bun竟然能这么快?搭配HonoJS的入门指南

1-img-20240908220980.png

最近我用bun+hono搭建了一个web服务,并尝试用docker打包部署。

在没有缓存的情况下,docker build 打包仅用了30s,如果是项目修改后再重新打包,更是连5s都用不了

而这个小服务虽然只是刚起步,但已经具备了日志、响应和错误标准化返回、数据库连接(sqlite)、路由分组、环境变量配置、jwt鉴权这几项,可以说当成个人的小玩具已经够格了。

Bun和Node到底是什么关系

Bun is an all-in-one JavaScript runtime & toolkit designed for speed, complete with a
bundler, test runner, and Node.js-compatible package manager.

Bun 是一款专为提高速度而设计的一体化 JavaScript 运行时工具包,配有捆绑器、测试运行器和与 Node.js 兼容的包管理器。

Node.js 是一个免费、开源、跨平台的 JavaScript 运行时环境。

通过他们官方的一句话介绍,可以清晰的看到,他们都是为了让JavaScript脱离浏览器环境而创造的一个运行时环境。只不过Node使用C艹编写,而Bun使用Zig。Node基于V8引擎(Goggle Chrome),而Bun使用JavaScriptCore(Apple Safari)

以前我们用JavaScript都是和html配合写前端代码,写完后需要打开浏览器才能看到效果,而有了其他的运行时环境后,就可以像其他Python/Go语言一样直接在命令行执行JavaScript脚本,所以其功能也从操作Dom变为了操作系统级Api,如:文件IO、数据库等等。

在只有Node一家独大的时候,我们甚至可以在(某些)面试官问:「你会什么后端语言」的时候,说:「我会NodeJS」,而现在有了DenoBun,我岂不是会了三门后端语言?(🤫bushi

截止到当前,Node已经发布到了22.8.0,庞大的开源module支撑起了整个社群的,而他的官方包管理器npm有点让人一言难尽

1-img-20240908210948.png

于是又出现了yarnpnpm老外写这些东西可能真的是在解决需求,到了咱这边真的也就是给面试官多提供了一些出题思路。 而Bun本身就自带包管理器。

另外,现在要想写一个“时髦的”前端项目,还必须有一个打包器,因为在不同的运行环境中,不同的浏览器中,对JavaScript的支持标准大不相同,所以需要把新版本的JavaScript降级,或者把TypeScript转换为JavaScript。或者是把JavaScript文件大小进行压缩。

而Node生态下光打包器就有:Webpack、Rollup、Vite等等,更不要说Rust开始被大厂卷起来之后,又用Rust对以前打包速度、运行速度有上限的打包器进行重构。面试官的出题角度还在增加
而Bun本身也是一个打包器。

另外还有测试运行器.. Vitest/Jest

所以现在可以明白,在2022年才发布的Bun究竟是想要做什么了

Hono简介

Hono🔥是一个基于 Web 标准构建的小型、简单且超快的 Web 框架。可以运行在所有JavaScript运行时,当然也包括了Bun,所以作为尝鲜,就图个鲜上加鲜。

在使用任何框架前,我都习惯先通读一遍官方文档,这大概会花费我2-4小时的时候。

在读完一遍官方文档后,如果使用过其他框架完成过类似的项目,就会大概知道这个框架哪些是自带的,哪些需要借助第三方。

如果框架本身过于精简(比如Koa),你就不得不去研究一些官方插件或是第三方插件,或者说去拜读一些开源项目,或者去找一些快速启动模板,以便自己快速上手。

Hono则是在文档里提供了很多官方的插件(Helper),无需翻看其他文档就能实现功能

搭建项目

按照官方文档开始搭建,因为我这里使用的是Bun,所以需要先下载好Bun

Macos/Linux

curl -fsSL https:

然后创建项目

bun create hono@latest my-app

创建项目后会有一个入口index.ts,在Bun中TS是一等公民,无需进行编译就能直接运行,所以速度非常快。

然后我们需要添加一些常用的中间件,如corscsrf,然后给自己配置一下喜欢的端口号

import { Hono } from 'hono'
import { showRoutes } from 'hono/dev'
import { cors } from 'hono/cors'
import { csrf } from 'hono/csrf'

const app = new Hono()

const api = app.basePath('/api')


api.use(csrf())

api.use('*', cors())

app.get('/', (c) => { return c.text('Hello Hono!') })
app.post('/', (c) => c.text('POST /')) 
app.put('/', (c) => c.text('PUT /')) 
app.delete('/', (c) => c.text('DELETE /'))







export default {
  port: Bun.env.PORT,
  fetch: app.fetch,
}

这样就完成了一个简单的服务,可以打开localhost:port,看一下是否返回了Hello Hono!

设置统一的前缀可以用basePath,设置环境变量可以在.env.env.development.env.production 中配置(在bun的官方文档中),并使用Bun.env.XXXX读取。

User模块路由

只有一个接口,我们可以写在index.ts里,那如果有一堆接口呢,肯定要进行分组的

Hono中路由分组也比较简单,只要再用一次new Hono()



const user = new Hono()

user.get('/list', (c) => c.text('List users')) 
user.get('/:id', (c) => {
  
  const id = c.req.param('id')
  return c.text('Get user: ' + id)
})
user.post('/', (c) => c.text('Create user')) 


const app = new Hono()


app.route('/user', user)

所以,要想给路由分组,只需要在src下再新建一个user文件夹,里面实现user的路由,在从index.ts里使用app.route('/user', user)就可以了。

由于我们使用了basePath,所以此时的user接口为/api/user/list/api/user/:id

我们在使用公司后端接口或者其他网站的开放接口接口时,经常会看到这样的结构/api/v1/user/a/b/c

在Hono中可以这样实现

user.get('/list', (c) => c.text('我是 user/list'))
v1.route('/user', user)
app.route('/v1', v1)

export default app

它会这样响应

GET /api/v1/user/list ---> `我是 user/list`

注意,如果上述代码中,route注册的顺序出错,则不会正常响应

错误捕捉

当发生一些致命错误时,为了不让服务挂掉,我们需要catch住,并且返回给前端一些友好的提示。不然我们那些年骂过的xx后端就变成了自己。

在Hono中使用也很简单,不需要自己单独写个中间件

import { HTTPException } from 'hono/http-exception'



app.onError((err, c) => {
  
  const status = 200;
  
  
  const errorCode = 40001
  const errorMsg = '不是我的错,想想前端的问题!'
  if (err instanceof HTTPException) {
    errorCode = ErrorCode.UNAUTHORIZED
  }

  const response = {
    code: errorCode,
    data: null,
    message: errorMsg,
  };
  return c.json(response, status)
})

这样,在后端有任何错误的时候,我们都会以http status 200的状态码返回,并且可以在返回体中定义好固定的结果,并且返回出一个自定义的errorCode,外加一个友好的前端能看得懂的errorMsg

随着项目的复杂度增加,可以把这个handler单独拆分出去,已达到精简入口文件的目的。

比如新建一个common 文件夹,里面写一个errorHandler.ts,在index.ts中或者在user模块src/user/index.ts中,都可以分别使用app.onError()user.onError()具体处理通用的或者是自定义的错误处理逻辑!

总结

这篇文章是一个入门篇,主要目的是讲述一下Node和Bun的区别,以及使用Bun+Hono的一个入门项目。

路由分组、错误捕捉这些功能很简单的就可以实现了,因为篇幅原因,我就把其他功能拆分成多篇教程了。

后续教程会涉及:数据库、响应标准化、日志、jwt鉴权、docker/docker-compose打包部署等等,是一个完整闭环的小项目。

代码也会开源分享出来,感兴趣的可以关注起来~

欢迎点赞催更👍

阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.shuli.cc/?p=21454,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?