Reputation: 838
How do I set the baseUrl that is used in the useFetch composable globally (maybe nuxt.config.ts)?
How can I avoid defining it in every useFetch?
Upvotes: 27
Views: 46025
Reputation: 31
Can create a $fetch instance then reuse by creating a new composable. Below is an example for creating $fetch instance:
// Create a fetch object with a baseURL already setup
const apiFetch = $fetch.create({ baseURL: '/api' })
// Use it as if it was $fetch
const {data, pending, errors, refresh} = await apiFetch('/test') // Same as $fetch('/test', { baseURL: '/api' })
See: https://github.com/nuxt/nuxt/discussions/15930
Upvotes: 3
Reputation: 4934
You can define the baseURL
in your nuxt.config.js|ts
like this:
import { defineNuxtConfig } from 'nuxt'
export default defineNuxtConfig({
// ...
runtimeConfig: {
public: {
baseURL: process.env.BASE_URL || 'https://api.example.com/',
},
},
// ...
(or use a fixed value or only the environment variable - as you like)
And add this composable:
// /composables/useMyFetch.js
export const useMyFetch = (request, opts) => {
const config = useRuntimeConfig()
return useFetch(request, { baseURL: config.public.baseURL, ...opts })
}
If you want type safety, you can achieve it like this:
// /composables/useMyFetch.ts
export const useMyFetch: typeof useFetch = (request, opts?) => {
const config = useRuntimeConfig()
return useFetch(request, { baseURL: config.public.baseURL, ...opts })
}
You can then use useMyFetch
as replacement for useFetch
- but with baseURL being set :-)
Upvotes: 44
Reputation: 10805
If you are looking to do this in Typescript, you can infer the parameters from useFetch
so you don't have to update your code if things change inside Nuxt.
Make your base URL configurable from your environment
As other folks have mentioned, first set your base URL in the public part of your runtime config:
// nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'
export default defineNuxtConfig({
// ...
runtimeConfig: {
public: {
baseURL: process.env.BASE_URL || 'https://api.example.com/',
},
},
// ...
Wrap useFetch with your own composable
The definition of useFetch
uses a number of type variables, is overloaded and what is valid for the options argument actually changes depending on the request/results types that are passed to it. This makes it very difficult to re-type correctly.
To make matters worse, even if we do re-type it correctly, if the definition changes our wrapper won't be correct anymore. Luckily there is a pretty simple solution. Borrow the type of useFetch
and re-use it:
// composables/useAPIFetch.ts
import { useFetch } from "#app"
type useFetchType = typeof useFetch
// wrap useFetch with configuration needed to talk to our API
export const useAPIFetch: useFetchType = (path, options = {}) => {
const config = useRuntimeConfig()
// modify options as needed
options.baseURL = config.public.baseUrl
return useFetch(path, options)
}
Note we explicitly need to not re-declare any type variables, parameter argument types or return types, since we are borrowing all of them from useFetch
's type.
Use your new composable
Use it in your page / component and your types will flow through properly:
// components/Foo.vue
const { data, error, pending } = await useAPIFetch<ResultsType>("/my-path", {
method: "POST",
body: data,
...
})
Upvotes: 9
Reputation: 314
in your nuxt.config file add this code
runtimeConfig: {
public: {
baseURL: process.env.BASE_URL || 'https://yourBaseURL.com/',
},
}
then create a file in composables directory and use below code
export const useCustomFetch = (request , opts)=>{
const config = useRuntimeConfig()
return useFetch(request,{baseURL:config.public.baseURL,
onRequest({ request, options }) {
// Set the request headers
},
onRequestError({ request, options, error }) {
// Handle the request errors
},
onResponse({ request, response, options }) {
// Process the response data
return response._data
},
onResponseError({ request, response, options }) {
// Handle the response errors
},
...opts})
}
now you can use this composable wrapper in your components in this composable you have interceptor to
Upvotes: 1
Reputation: 1564
You can also involve .env like this
in .env
NUXT_PUBLIC_BASE_URL = https://www.someapi.com
in nuxt.config.js/ts
runtimeConfig: {
public: {
BASE_URL: 'some fallback value',
},
},
as it said in the document BASE_URL
will be replaced by NUXT_PUBLIC_BASE_URL
automatically
( no need to use process.env.NUXT_PUBLIC_BASE_URL
)
and in composable you can use
const config = useRuntimeConfig();
console.log('base url is' , config.baseUrl)
Upvotes: 7
Reputation: 29
For anyone still looking for the answer to the original question you can do this in nuxt.config
with runtimeConfig and env variables. You can of course replace the env variables with a hard-coded values if you prefer.
In your nuxt.config.js/ts
runtimeConfig: {
SOME_SECRET_KEY: process.env.SOME_SECRET_KEY,
public: {
SOME_API_KEY: process.env.SOME_API_KEY,
},
},
Then in someComposable.js
:
const config = useRuntimeConfig();
You can then access your variables as eg config.public.SOME_API_KEY
Hope that helps. More info here: https://v3.nuxtjs.org/guide/features/runtime-config
Upvotes: -1
Reputation: 46764
The following composable could be set
/composables/useJsonP.ts
export const useJsonP = async (path) => {
return await useFetch(() => `https://jsonplaceholder.typicode.com/${path}`)
}
And you could call this in your view
<script setup>
const jsonP = await useJsonP('todos/1')
</script>
<template>
<div>
<pre>{{ jsonP.data }}</pre>
</div>
</template>
That way, no need to define it somewhere and hack somehow the configuration. You do have a simple way of defining reusable pieces of code, that are directly imported into your components/views thanks to the DX of Nuxt.
Upvotes: 12