alova 3.3.0 发布:开发体验提升的重大更新

经过几个月的精心打磨,很高兴向大家宣布 alova 3.3.0 正式发布!

在过去半年时间里,我们也深入听取了社区开发者的反馈,针对实际开发中的痛点,在业务逻辑方面加强了不少。从 SSR 支持到 AI 应用,服务端场景下的业务逻辑,从分布式缓存到文件上传等等。

什么是alova

alova是一个请求工具集,帮助开发者极致高效地集成你的APIs,它完美兼容你最喜欢的HTTP client和UI框架,快速开发客户端和服务的应用的业务逻辑,同时让API信息与代码进行交互,像虫洞一样拉近后端协作距离。

如果觉得alova还不错,真诚希望你可以尝试体验一下,也可以给我们来一个免费的github stars

访问alovajs的官网查看更多详细信息:alovajs官网

更新亮点预览

功能增强

  • nuxt3 优化:完美适配 Nuxt3,支持客户端和服务端的状态同步,以及await useRequest 语法
  • usePagination 重构:告别繁琐的额外请求,一键实现增删改操作
  • useSSE 升级:支持 POST 请求和自定义 headers

全新策略

  • 验证码策略:分布式验证码发送和验证解决方案
  • 上传策略:万能文件上传,支持多种数据格式

核心特性

  • alova.Request:更好的 TypeScript 类型支持
  • baseURL优化:带协议 URL 自动忽略 baseURL 拼接
  • querystring 支持:params 参数支持字符串格式

存储适配器

  • Redis 适配器:分布式集群存储场景
  • File 适配器:单机多进程原子化场景

接下来具体了解下吧。

一、useHook 功能增强

完美适配 Nuxt3

alova 3.3.0 借鉴了 Nuxt3 的优秀设计,实现了比useFetch更好的体验,在使用useRequest、useWatcher等几乎所有的hooks时不仅可以同步两端的数据,避免在客户端重复请求,还可以在服务端和客户端同步例如DateError等以及自定义类型的数据。

Nuxt3 的写法:

javascript 复制代码
<script setup>
const { data: count } = await useFetch('/api/count');
</script>

现在 alova 中可以这样写:

javascript 复制代码
<script setup>
const { data, loading } = await useRequest(...);
</script>

在实际中表现如下:

  • 在服务端会进行一次真实的请求
  • 在客户端不会重复请求
  • data、loading 等状态在客户端依然可以正常使用

这需要配合本次新增的nuxtHook:

javascript 复制代码
import { createAlova } from 'alova';
import nuxtHook from 'alova/nuxt';

export const alovaInstance = createAlova({
  // ...
  statesHook: nuxtHook({
    nuxtApp: useNuxtApp // 必须指定useNuxtApp
  })
});

usePagination 优化

在之前的版本中,如果要对列表项进行增删改操作,需要先定义额外的 useRequest,然后再调用 usePagination 的操作函数,代码显得相当繁琐:

3.2.x 的写法中,操作列表数据需要额外定义useRequest

javascript 复制代码
const { data, loading, page, pageSize, remove } = usePagination(getList);
const { send: removeItem, loading: removing } = useRequest(id => removeItem(id), {
  immediate: false
}).onSuccess(({ args: [id] }) => {
  remove(id);
});
const handleRemove = id => {
  removeItem(id);
};

3.3.0 中定义actions即可:

javascript 复制代码
// 简洁的新写法
const { 
  ...
  remove,
  removing
} = usePagination(getList, {
  actions: {
    remove: id => removeItem(id),
    replace: item => replaceItem(item)
  }
});

const handleRemove = id => {
  remove(id); // 直接调用即可,内部会自动触发请求
};

新增的状态管理让UI控制更精确,以下是一个vue3的示例:

html 复制代码
<template>
<table>
  <tr v-for="(item, index) in list" :key="item.id">
    <td>{{ item.id }}</td>
    <td>{{ item.name }}</td>
    <td>
      <button 
        :loading="removing.includes(index)" 
        @click="remove(item.id)"
      >
        删除
      </button>
    </td>
  </tr>
</table>
</template>

<script setup>
const { data: list, remove, removing } = usePagination(getList, {
  actions: {
    remove: id => removeUser(id)
  }
});
</script>

usePagination优化小结:

  1. actions 配置项:可配置 insert、remove、replace 对应的请求函数
  2. status 状态:包含空字符串(正常)、loading(加载中)、removing(删除中)、inserting(插入中)、replacing(替换中)
  3. 精确的行级状态:removing 是数组,replacing 是数字,可以精确控制每一行的状态

useSSE 优化

随着AI应用的兴起,Server-Sent Events (SSE) 变得越来越重要。我们团队深入研究了 AI 应用的实际需求,对 useSSE 进行了重大升级:

核心改进:

  1. 使用 fetch 替代 EventSource:支持 POST 请求、数据传输和 headers 传递
  2. 新增 responseType 参数:自动转换为 JSON 数据

实际使用示例:

javascript 复制代码
// 支持 POST 请求和自定义 headers
const streamMethod = () => alova.Post('/api/chat-stream', {
    prompt: '请告诉我关于人工智能的发展历史',
    temperature: 0.7
  }, {
  headers: {
    'Authorization': 'Bearer your-token',
    'Content-Type': 'application/json'
  },
})

const { data, readyState, onMessage, onError } = useSSE(, {
  responseType: 'json', // 自动转换为 JSON
  immediate: true
});

// 监听流式数据
onMessage(event => {
  console.log('收到AI回复:', event.data);
});

// 处理错误
onError(error => {
  console.error('连接错误:', error);
});

二、全新请求策略

服务端验证码策略:分布式验证码解决方案

对于需要验证码功能的应用,alova 3.3.0 提供了完整的服务端验证码解决方案:

javascript 复制代码
const { validateCaptcha, sendCaptcha } = createCaptchaProvider({
  // 可再次发送验证码的间隔时间
  resetTime: 60 * 1000,
  
  // 验证码过期时间
  expireTime: 60 * 1000 * 5,
  
  // 命名空间,防止命名冲突
  keyPrefix: 'alova-captcha',
  
  // 验证码存储适配器,使用redis适配器实现分布式验证码处理
  store: redisAdapter,
  
  // 重发时是否使用存储中的验证码
  resendFormStore: true,
  
  // 验证码生成规则
  codeSet: {
    chars: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
    length: 4
  }
});

// 发送验证码
await sendCaptcha((code, key) => alova.Post('/api/captcha', { 
  code, 
  mobile: key 
}), {
  key: mobile
});

// 验证验证码
const isValid = await verifyCaptcha(submitedCaptcha, mobile);

这个策略特别适合分布式环境,支持多种存储适配器,并且提供了完善的过期和重发机制。

客户端上传策略:万能的文件上传

新的上传策略支持多种数据格式直接上传,支持获得总上传进度和单个文件的上传进度,还支持批量上传:

  • base64 字符串
  • File 对象
  • Blob 对象
  • ArrayBuffer 对象
  • Canvas 对象
javascript 复制代码
// 支持各种格式的上传
const { upload, uploading, progress, appendFiles } = useUploader(uploadAPI);

// 添加文件
await appendFiles({ file: fileObject });

// 添加canvas图片
await appendFiles({ file: canvasElement });

// 添加base64
await appendFiles({ file: base64String });

// 触发上传
await upload();

这个策略解决了三个常见场景:

  1. 上传组件样式不符合需求时的自定义上传
  2. 无法使用上传组件时的编程式上传(如Canvas图片)
  3. 多种数据格式混合上传的场景

三、核心特性增强

新增 alova.Request:更好的类型支持

之前使用 new Method 时,响应数据类型不好指定。新的 alova.Request 提供了类似 axios 的使用体验:

javascript 复制代码
// 直接指定响应类型
interface User {
  id: number;
  name: string;
  age: number;
}

const method = alova.Request<User>({
  url: '/xxx',
  method: 'post',
  data: { name: 'John' },
  headers: { 'Content-Type': 'application/json' }
});

const response = await method;
// response 现在有完整的 User 类型支持

// 或者通过 transform 指定类型
const method2 = alova.Request({
  url: '/xxx',
  method: 'post',
  data: { name: 'John' },
  transform(data: User) {
    return { ...data, fullName: `${data.name}(${data.age})` };
  }
});

baseURL 自动忽略机制

当请求URL包含协议时,会自动忽略 baseURL 的拼接:

javascript 复制代码
const alova = createAlova({
  baseURL: 'http://localhost:3000',
  // ...
});

// 这个请求会直接访问指定URL,不会拼接baseURL
alova.Get('http://localhost:8080/data');

这个特性在处理跨域请求或多个API服务时特别有用。

params 支持 querystring 格式

现在可以直接传入 querystring 格式的参数:

javascript 复制代码
// 直接传入querystring
const method = alova.Get('/xxx', {
  params: 'a=1&b=2&c[]=3&c[]=4'
});

// 全局处理复杂参数
import qs from 'qs';

createAlova({
  beforeRequest(method) {
    method.config.params = qs.stringify(method.config.params, { 
      arrayFormat: "brackets" 
    });
  }
});

四、新增存储适配器

Redis 存储适配器:分布式缓存

为了支持服务端分布式集群下的缓存共享,新增了 Redis 存储适配器:

javascript 复制代码
import { RedisStorageAdapter } from '@alova/storage-redis';

const alovaInstance = createAlova({
  // ...
  l2Cache: new RedisStorageAdapter({
    host: 'localhost',
    port: 6379,
    // 其他Redis配置...
  })
});

内部使用 ioredis 实现,提供了完整的 Redis 功能支持,在请求速率限制、验证码发送场景都可以直接使用。

File 存储适配器:单机集群缓存

对于单机多进程的场景,提供了文件存储适配器:

javascript 复制代码
import { FileStorageAdapter } from '@alova/storage-file';

const alovaInstance = createAlova({
  // ...
  l2Cache: new FileStorageAdapter({
    directory: './cache'
  })
});

通过 rename + queue 实现多进程的原子化操作,确保数据一致性。

最后

此时我还想说的是,无论你是在开发传统的 Web 应用,还是在构建现代的 AI 应用,alova 3.3.0 都能给你提供强大而优雅的解决方案。

如果觉得alova还不错,真诚希望你可以尝试体验一下,也可以给我们来一个免费的github stars

访问alovajs的官网查看更多详细信息:alovajs官网

有兴趣可以加入我们的交流社区,在第一时间获取到最新进展,也能直接和开发团队交流,提出你的想法和建议。

有任何问题,你可以加入以下群聊咨询,也可以在github 仓库中发布 Discussions,如果遇到问题,也请在github 的 issues中提交,我们会在最快的时间解决。

相关推荐
HarryHY1 小时前
检查项目中的依赖是否有更新——npm outdated
前端·npm·node.js
树獭叔叔3 小时前
从零开始Node之旅——Nest.js 模块系统(Modules)
后端·node.js
non_hana4 小时前
Vite Dev Server 构建原理
node.js·vite
non_hana4 小时前
一些 linter & formatter 配置最佳实践
typescript·node.js·eslint
漂流瓶jz16 小时前
让数据"流动"起来!Node.js实现流式渲染/流式传输与背后的HTTP原理
前端·javascript·node.js
陪我一起学编程18 小时前
关于nvm与node.js
vue.js·后端·npm·node.js
程序猿小D18 小时前
第22节 Node.js JXcore 打包
开发语言·人工智能·vscode·node.js·c#
2401_8784545318 小时前
node.js的初步学习
学习·node.js
不想说话的麋鹿1 天前
《NestJS 实战:RBAC 系统管理模块开发 (一)》
前端·node.js·全栈