Overview
ofetch.create() allows you to create new fetch instances with pre-configured options that are shared across all requests. This is useful for setting up API clients with common settings like base URLs, headers, and interceptors.
Basic Usage
const apiFetch = ofetch.create({ baseURL: '/api' })
apiFetch('/test') // Same as ofetch('/test', { baseURL: '/api' })
Common Use Cases
API Client with Base URL
Create a dedicated fetch instance for your API:
const apiFetch = ofetch.create({
baseURL: 'https://api.example.com',
headers: {
'Authorization': 'Bearer token123',
'Content-Type': 'application/json'
}
})
// All requests use the base URL and headers
const users = await apiFetch('/users')
const posts = await apiFetch('/posts')
Authenticated Requests
Set up authentication headers globally:
const authenticatedFetch = ofetch.create({
baseURL: '/api',
async onRequest({ options }) {
const token = await getAuthToken()
options.headers.set('Authorization', `Bearer ${token}`)
}
})
await authenticatedFetch('/protected/resource')
Multiple API Clients
Create separate instances for different services:
const githubAPI = ofetch.create({
baseURL: 'https://api.github.com',
headers: {
'Accept': 'application/vnd.github.v3+json'
}
})
const internalAPI = ofetch.create({
baseURL: 'https://internal.company.com/api',
retry: 3,
timeout: 5000
})
const repos = await githubAPI('/users/unjs/repos')
const data = await internalAPI('/internal/data')
How It Works
From src/fetch.ts:268-277:
$fetch.create = (defaultOptions = {}, customGlobalOptions = {}) =>
createFetch({
...globalOptions,
...customGlobalOptions,
defaults: {
...globalOptions.defaults,
...customGlobalOptions.defaults,
...defaultOptions,
},
});
The create method:
- Merges global options with custom global options
- Combines all default options into a single defaults object
- Returns a new
$Fetch instance with the merged configuration
Options Inheritance
Defaults will be cloned at one level and inherited. Be careful about nested options like headers.
Options are merged shallowly. For nested options like headers, the entire object is replaced:
const base = ofetch.create({
headers: { 'X-Custom': 'base' }
})
// This replaces headers entirely, not merges
const response = await base('/endpoint', {
headers: { 'Authorization': 'Bearer token' }
})
// Only Authorization header is sent, X-Custom is lost
To preserve base headers, use interceptors:
const base = ofetch.create({
headers: { 'X-Custom': 'base' },
async onRequest({ options }) {
// Add additional headers without replacing
options.headers.set('Authorization', 'Bearer token')
}
})
Advanced Example: Retry Configuration
const resilientFetch = ofetch.create({
retry: 3,
retryDelay: 1000,
retryStatusCodes: [408, 429, 500, 502, 503, 504],
async onRequestError({ error }) {
console.error('Request failed:', error)
},
async onResponseError({ response }) {
console.error('Response error:', response.status)
}
})
await resilientFetch('/flaky-endpoint')
Custom Global Options
You can pass custom global options as the second parameter:
const customFetch = ofetch.create(
{ baseURL: '/api' },
{ fetch: customFetchImplementation }
)
This allows you to:
- Provide a custom fetch implementation
- Override the global fetch function
- Configure fetch-level defaults
TypeScript Support
The created instance maintains full type safety:
interface User {
id: number
name: string
}
const api = ofetch.create({ baseURL: '/api' })
const user = await api<User>('/users/1')
// user is typed as User
console.log(user.name)