Overview
ofetch.native() provides a shortcut to the native fetch API, allowing you to use standard fetch when you don’t need ofetch’s additional features.
Basic Usage
const response = await ofetch.native('/api/users')
const data = await response.json()
When to Use
Use ofetch.native() when you:
- Need standard fetch behavior without ofetch enhancements
- Want to process the response manually
- Need compatibility with code expecting native fetch
- Want to avoid automatic JSON parsing or error handling
How It Works
From src/fetch.ts:266:
$fetch.native = (...args) => fetch(...args);
This is a direct passthrough to the underlying fetch implementation configured for the ofetch instance.
Comparison
ofetch (default)
// Automatic JSON parsing
const users = await ofetch('/api/users')
// users is already parsed JSON
// Automatic error throwing
try {
await ofetch('/api/404')
} catch (error) {
console.error(error.status) // 404
}
ofetch.native()
// Manual response handling
const response = await ofetch.native('/api/users')
const users = await response.json()
// Manual error checking
const response = await ofetch.native('/api/404')
if (!response.ok) {
console.error(response.status) // 404
}
ofetch.raw()
// Automatic parsing + access to response
const response = await ofetch.raw('/api/users')
const users = response._data // Already parsed
const headers = response.headers
Common Use Cases
Manual Response Processing
const response = await ofetch.native('/api/data')
// Check status before parsing
if (response.status === 304) {
// Use cached data
return getCachedData()
}
if (response.ok) {
const data = await response.json()
return data
}
Streaming Response
const response = await ofetch.native('/api/large-file')
const reader = response.body?.getReader()
if (reader) {
while (true) {
const { done, value } = await reader.read()
if (done) break
// Process chunk
processChunk(value)
}
}
Custom Content Type Handling
const response = await ofetch.native('/api/image')
const blob = await response.blob()
const imageUrl = URL.createObjectURL(blob)
// Display image
document.querySelector('img').src = imageUrl
Progressive Enhancement
async function fetchData(url: string) {
const response = await ofetch.native(url)
// Custom error handling
if (!response.ok) {
if (response.status === 401) {
redirectToLogin()
return
}
throw new Error(`HTTP ${response.status}`)
}
// Check content type
const contentType = response.headers.get('Content-Type')
if (contentType?.includes('application/json')) {
return await response.json()
} else if (contentType?.includes('text/')) {
return await response.text()
} else {
return await response.blob()
}
}
With Custom Instances
const apiFetch = ofetch.create({
baseURL: '/api',
headers: { 'X-Custom': 'header' }
})
// native() still uses baseURL and default headers
const response = await apiFetch.native('/users')
// Fetches from /api/users with X-Custom header
ofetch.native() bypasses ofetch’s automatic JSON parsing, error handling, and retry logic. You’ll need to handle these manually.
Implementation Details
From src/index.ts:9-11:
export const fetch: typeof globalThis.fetch = globalThis.fetch
? (...args: Parameters<typeof globalThis.fetch>) => globalThis.fetch(...args)
: () => Promise.reject(new Error("[ofetch] global.fetch is not supported!"));
The fetch wrapper:
- Uses
globalThis.fetch if available (browser, modern Node.js)
- Forwards all arguments to the native fetch
- Throws an error if fetch is not supported
Standard Fetch API
ofetch.native() supports all standard fetch options:
await ofetch.native('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'John' }),
credentials: 'include',
cache: 'no-cache',
redirect: 'follow',
referrerPolicy: 'no-referrer'
})
TypeScript
From src/types.ts:14:
export interface $Fetch {
// ...
native: Fetch;
// ...
}
native is typed as the standard Fetch type:
const response: Response = await ofetch.native('/api/users')