
Research
Shai-Hulud Descends to Hades: Miasma Worm Campaign Spreads with New PyPI Wave
Socket found 37 malicious PyPI wheels that abuse Python startup hooks to launch a Bun-powered credential stealer tied to Mini Shai-Hulud/Miasma.
react-native-cross-fetch
Advanced tools
一个极致精简、高性能的跨平台 HTTP 请求库,专为 React Native (iOS/Android) 和 Web 环境设计。
单文件 ~300 行 TypeScript,ESM ~23 KB / gzip ~9 KB,零运行时依赖。
它提供了一套统一的 API(与主流 HTTP 客户端一致),在支持 fetch 的环境中优先使用 fetch,在不支持的环境或特殊场景下自动降级为 XMLHttpRequest。
| 库 | min 体积 | gzip 体积 | 运行时依赖 |
|---|---|---|---|
| react-native-cross-fetch | ~23 KB | ~9 KB | 0 |
| axios | ~55 KB | ~14 KB | 0(但含 Node 适配器) |
| ky | ~22 KB | ~8 KB | 0(仅 fetch,无 XHR 降级) |
与 axios 功能覆盖度接近(拦截器、取消、超时、FormData、参数序列化),但不含 Node.js 专属代码,体积更小,且针对 RN + Web 场景做了专项优化。
fetch,必要时自动切换到 XMLHttpRequest.d.ts 类型定义baseURL + params 自动拼接与序列化paramsSerializer 自定义参数序列化timeout 超时设置AbortSignal / CancelToken 双重取消机制FormData 文件上传application/x-www-form-urlencoded 自动编码fetchOptions 透传到底层 fetchparseReviver 自定义 JSON 解析HttpStatusCode 双向状态码映射CrossFetchError 带标准化错误码(ERR_NETWORK / ERR_CANCELED / ECONNABORTED 等)| 需求 | react-native-cross-fetch | axios | ky |
|---|---|---|---|
| RN iOS/Android + Web 三端统一 | ✅ | ⚠️ 含 Node 冗余代码 | ⚠️ 仅 fetch |
| fetch 优先 + XHR 降级 | ✅ | ✅ | ❌ 仅 fetch |
| 拦截器 | ✅ | ✅ | ✅ hooks |
| 取消请求 (AbortSignal + CancelToken) | ✅ | ✅ | ✅ 仅 AbortSignal |
| 零运行时依赖 | ✅ | ✅ | ✅ |
| gzip < 15KB | ✅ ~9KB | ❌ ~14KB | ✅ ~8KB |
| 完整 TypeScript 类型 | ✅ | ✅ | ✅ |
核心优势:
create/request/get/post/interceptors/defaults),轻松迁移onUploadProgress / onDownloadProgress)http/https adapter、agent、代理、cookie jar 等)npm install react-native-cross-fetch
yarn add react-native-cross-fetch
import crossFetch from 'react-native-cross-fetch';
// GET
const res = await crossFetch.get('https://api.example.com/user', {
params: { id: 12345 }
});
console.log(res.data);
// POST
await crossFetch.post('https://api.example.com/user', {
firstName: 'Fred',
lastName: 'Flintstone'
});
const api = crossFetch.create({
baseURL: 'https://api.example.com/v1',
timeout: 10000,
headers: { 'X-Custom-Header': 'foobar' }
});
await api.get('/users');
await crossFetch.request('https://api.example.com/user', { method: 'get' });
// 请求拦截器 — 注入 Token
api.interceptors.request.use((config) => {
config.headers = {
...config.headers,
Authorization: `Bearer ${getToken()}`
};
return config;
});
// 响应拦截器 — 统一处理 401
api.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
console.log('未授权,请登录');
}
return Promise.reject(error);
}
);
interface User {
id: number;
name: string;
email: string;
}
const res = await api.get<User>('/user/1');
console.log(res.data.name); // 类型安全
import { isCrossFetchError } from 'react-native-cross-fetch';
try {
await api.get('/user/12345');
} catch (error) {
if (isCrossFetchError(error)) {
if (error.code === 'ECONNABORTED') console.log('请求超时');
else if (error.code === 'ERR_NETWORK') console.log('网络错误');
else if (error.response) {
console.log('状态码:', error.response.status);
console.log('响应数据:', error.response.data);
}
}
}
// 方式一:AbortController(推荐)
const controller = new AbortController();
api.get('/data', { signal: controller.signal });
controller.abort();
// 方式二:CancelToken
const { token, cancel } = crossFetch.CancelToken.source();
api.get('/data', { cancelToken: token });
cancel('不再需要');
const formData = new FormData();
formData.append('file', fileObject);
formData.append('userId', '123');
// Content-Type 会自动处理,无需手动设置
await api.post('/upload', formData);
{
data, // 响应数据(自动 JSON 解析)
status, // HTTP 状态码
statusText, // 状态文本
headers, // CrossFetchHeaders 实例
config, // 请求配置
request // fetch: Request | xhr: XMLHttpRequest
}
{
url: '/user', // 请求路径(必填)
method: 'get', // 请求方法,默认 'get'
baseURL: 'https://api.example.com/', // 基础 URL,自动拼接
headers: {}, // 请求头
params: { ID: 12345 }, // URL 查询参数
paramsSerializer: { serialize(p) {} }, // 自定义参数序列化
data: { key: 'value' }, // 请求体(POST/PUT/PATCH/DELETE)
timeout: 10000, // 超时时间(ms),默认 0(无超时)
adapter: 'fetch', // 强制指定适配器:'fetch' | 'xhr'
responseType: 'json', // 响应类型:json | text | blob | arraybuffer | stream | formdata
withCredentials: false, // 跨域携带凭证
signal: controller.signal, // AbortSignal 取消
cancelToken: token, // CancelToken 取消
validateStatus: (s) => s < 400, // 自定义状态码校验
fetchOptions: {}, // 透传到底层 fetch(redirect/mode/cache 等)
transitional: { // 过渡选项
silentJSONParsing: true,
forcedJSONParsing: true,
clarifyTimeoutError: false,
},
parseReviver: (key, val) => val, // JSON.parse reviver
env: { fetch, XMLHttpRequest }, // 自定义环境注入
}
import crossFetch, {
CrossFetchError,
CrossFetchHeaders,
CanceledError,
CancelToken,
isCrossFetchError,
isCancel,
mergeConfig,
getAdapter,
toFormData,
formToJSON,
HttpStatusCode,
VERSION,
all,
spread,
} from 'react-native-cross-fetch';
ISC
FAQs
轻量请求库:三端可用(RN iOS/Android + Web),fetch 优先,必要时自动降级 XHR。
We found that react-native-cross-fetch demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
Socket found 37 malicious PyPI wheels that abuse Python startup hooks to launch a Bun-powered credential stealer tied to Mini Shai-Hulud/Miasma.

Security News
RubyGems and Bundler 4.0.13 introduced an opt-in cooldown feature that delays newly published gems during dependency resolution.

Security News
pnpm 11.5 now recognizes npm staged publish approvals in release metadata, preventing those releases from being mistaken for lower-trust package publishes.