Dickson Afful
Dickson Afful

Reputation: 838

How to set global API baseUrl used in useFetch in Nuxt 3

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

Answers (7)

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

some-user
some-user

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

Matt Sanders
Matt Sanders

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

Amir
Amir

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

morteza mortezaie
morteza mortezaie

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

TimC
TimC

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

kissu
kissu

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

Related Questions