From 5d809142d307374484eeba770ddc69bc9ee4321f Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 31 Mar 2022 09:47:01 +0200 Subject: [PATCH 1/9] feat(nuxt)!: use paylod cache for initial data fetching by default --- .../nuxt3/src/app/composables/asyncData.ts | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/packages/nuxt3/src/app/composables/asyncData.ts b/packages/nuxt3/src/app/composables/asyncData.ts index ae164d346ea..655a698e57e 100644 --- a/packages/nuxt3/src/app/composables/asyncData.ts +++ b/packages/nuxt3/src/app/composables/asyncData.ts @@ -21,12 +21,17 @@ export interface AsyncDataOptions< transform?: Transform pick?: PickKeys watch?: MultiWatchSources + cache?: boolean +} + +export interface RefrashOptions { + _initial?: boolean } export interface _AsyncData { data: Ref pending: Ref - refresh: (force?: boolean) => Promise + refrash: (opts?: RefrashOptions) => Promise error?: any } @@ -58,6 +63,7 @@ export function useAsyncData< console.warn('[useAsyncData] `defer` has been renamed to `lazy`. Support for `defer` will be removed in RC.') } options.lazy = options.lazy ?? (options as any).defer ?? false + options.cache = options.cache ?? true // Setup nuxt instance payload const nuxt = useNuxtApp() @@ -81,11 +87,15 @@ export function useAsyncData< error: ref(nuxt.payload._errors[key] ?? null) } as AsyncData - asyncData.refresh = (force?: boolean) => { + asyncData.refrash = (opts = {}) => { // Avoid fetching same key more than once at a time - if (nuxt._asyncDataPromises[key] && !force) { + if (nuxt._asyncDataPromises[key]) { return nuxt._asyncDataPromises[key] } + // Avoid fetching same key that is already fetched + if (opts._initial && options.cache && nuxt.payload.data[key] !== undefined) { + return nuxt.payload.data[key] + } asyncData.pending.value = true // TODO: Cancel previous promise // TODO: Handle immediate errors @@ -115,11 +125,13 @@ export function useAsyncData< return nuxt._asyncDataPromises[key] } + const initialFetch = () => asyncData.refrash({ _initial: true }) + const fetchOnServer = options.server !== false && nuxt.payload.serverRendered // Server side if (process.server && fetchOnServer) { - const promise = asyncData.refresh() + const promise = initialFetch() onServerPrefetch(() => promise) } @@ -131,17 +143,17 @@ export function useAsyncData< } else if (instance && (nuxt.isHydrating || options.lazy)) { // 2. Initial load (server: false): fetch on mounted // 3. Navigation (lazy: true): fetch on mounted - instance._nuxtOnBeforeMountCbs.push(asyncData.refresh) + instance._nuxtOnBeforeMountCbs.push(initialFetch) } else { // 4. Navigation (lazy: false) - or plugin usage: await fetch - asyncData.refresh() + initialFetch() } if (options.watch) { - watch(options.watch, () => asyncData.refresh()) + watch(options.watch, () => initialFetch()) } const off = nuxt.hook('app:data:refresh', (keys) => { if (!keys || keys.includes(key)) { - return asyncData.refresh() + return initialFetch() } }) if (instance) { From 69f335894180bd52fa31086378678618743fa682 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 31 Mar 2022 09:47:24 +0200 Subject: [PATCH 2/9] feat: update useFetch with mapped cache --- packages/nuxt3/src/app/composables/fetch.ts | 42 ++++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/packages/nuxt3/src/app/composables/fetch.ts b/packages/nuxt3/src/app/composables/fetch.ts index 03d298e5d07..f8015f09912 100644 --- a/packages/nuxt3/src/app/composables/fetch.ts +++ b/packages/nuxt3/src/app/composables/fetch.ts @@ -7,11 +7,17 @@ import { useAsyncData } from './asyncData' export type FetchResult = TypedInternalResponse -export type UseFetchOptions< +export interface UseFetchOptions< DataT, Transform extends _Transform = _Transform, PickKeys extends KeyOfRes = KeyOfRes -> = AsyncDataOptions & FetchOptions & { key?: string } +> extends + Omit, 'cache'>, + Omit + { + cache?: boolean | RequestCache, + key?: string + } export function useFetch< ResT = void, @@ -32,19 +38,43 @@ export function useFetch< return isRef(r) ? r.value : r }) - const asyncData = useAsyncData(key, () => { - return $fetch(_request.value, opts) as Promise<_ResT> - }, { + const _fetchOptions = { + ...opts, + cache: typeof opts.cache === 'boolean' ? undefined : opts.cache + } + + const _asyncDataOptions: AsyncDataOptions = { ...opts, + cache: requestCacheToCacheOption(opts.cache), watch: [ _request, ...(opts.watch || []) ] - }) + } + + const asyncData = useAsyncData(key, () => { + return $fetch(_request.value, _fetchOptions) as Promise<_ResT> + }, _asyncDataOptions) return asyncData } +// Maps request cache option to useAsyncData cache strategy +// https://developer.mozilla.org/en-US/docs/Web/API/Request/cache +function requestCacheToCacheOption (input: undefined | boolean | RequestCache): AsyncDataOptions['cache'] { + // Async data possible options + const t = typeof input + if (t === 'boolean' || t === 'undefined') { + return input as boolean | undefined + } + // Map values + if (input === 'force-cache') { + return true + } + // Use default behavior for rest + return undefined +} + export function useLazyFetch< ResT = void, ReqT extends string = string, From 17be5751e7aaa4ac6bb2a2e2bb49f3b2564aae9c Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 31 Mar 2022 09:48:33 +0200 Subject: [PATCH 3/9] fix typo in interface --- packages/nuxt3/src/app/composables/asyncData.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nuxt3/src/app/composables/asyncData.ts b/packages/nuxt3/src/app/composables/asyncData.ts index 655a698e57e..1451feaa6be 100644 --- a/packages/nuxt3/src/app/composables/asyncData.ts +++ b/packages/nuxt3/src/app/composables/asyncData.ts @@ -24,14 +24,14 @@ export interface AsyncDataOptions< cache?: boolean } -export interface RefrashOptions { +export interface RefreshOptions { _initial?: boolean } export interface _AsyncData { data: Ref pending: Ref - refrash: (opts?: RefrashOptions) => Promise + refrash: (opts?: RefreshOptions) => Promise error?: any } From d9d38de6261569c5e9e1c3eb280e6b5b26a82212 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 31 Mar 2022 09:51:00 +0200 Subject: [PATCH 4/9] update docs --- docs/content/3.docs/1.usage/1.data-fetching.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/content/3.docs/1.usage/1.data-fetching.md b/docs/content/3.docs/1.usage/1.data-fetching.md index 75236470c0b..4fbcc8d9817 100644 --- a/docs/content/3.docs/1.usage/1.data-fetching.md +++ b/docs/content/3.docs/1.usage/1.data-fetching.md @@ -16,12 +16,12 @@ Within your pages, components and plugins you can use `useAsyncData` to get acce const { data: Ref, pending: Ref, - refresh: (force?: boolean) => Promise, + refresh: () => Promise, error?: any } = useAsyncData( key: string, handler: (ctx?: NuxtApp) => Promise, - options?: { + options?: { lazy: boolean, server: boolean, watch: WatchSource[] @@ -40,6 +40,7 @@ const { * _transform_: a function that can be used to alter `handler` function result after resolving * _pick_: only pick specified keys in this array from `handler` function result * _watch_: watch reactive sources to auto refresh + * _cache_: When set to `false`, will skip payload cache for initial fetch. (defaults to `true`) Under the hood, `lazy: false` uses `` to block the loading of the route before the data has been fetched. Consider using `lazy: true` and implementing a loading state instead for a snappier user experience. @@ -114,6 +115,7 @@ const { Available options: * `key`: Provide a custom key +* `cache`: Either a [RequestCache](https://developer.mozilla.org/en-US/docs/Web/API/Request/cache) strategy or `false` to skip initial paylod cache from asyncData. * Options from [ohmyfetch](https://github.com/unjs/ohmyfetch) * `method`: Request method * `params`: Query params From d6436a183fd4f521e662a3f56a2a3569aad6f63a Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 31 Mar 2022 10:06:05 +0200 Subject: [PATCH 5/9] refactor: use `initialCache` option to avoid future compatibility with `cache` --- .../content/3.docs/1.usage/1.data-fetching.md | 3 +-- .../nuxt3/src/app/composables/asyncData.ts | 6 ++--- packages/nuxt3/src/app/composables/fetch.ts | 22 ++----------------- playground/app.vue | 2 ++ 4 files changed, 8 insertions(+), 25 deletions(-) diff --git a/docs/content/3.docs/1.usage/1.data-fetching.md b/docs/content/3.docs/1.usage/1.data-fetching.md index 4fbcc8d9817..04c385f90e0 100644 --- a/docs/content/3.docs/1.usage/1.data-fetching.md +++ b/docs/content/3.docs/1.usage/1.data-fetching.md @@ -40,7 +40,7 @@ const { * _transform_: a function that can be used to alter `handler` function result after resolving * _pick_: only pick specified keys in this array from `handler` function result * _watch_: watch reactive sources to auto refresh - * _cache_: When set to `false`, will skip payload cache for initial fetch. (defaults to `true`) + * _initialCache_: When set to `false`, will skip payload cache for initial fetch. (defaults to `true`) Under the hood, `lazy: false` uses `` to block the loading of the route before the data has been fetched. Consider using `lazy: true` and implementing a loading state instead for a snappier user experience. @@ -115,7 +115,6 @@ const { Available options: * `key`: Provide a custom key -* `cache`: Either a [RequestCache](https://developer.mozilla.org/en-US/docs/Web/API/Request/cache) strategy or `false` to skip initial paylod cache from asyncData. * Options from [ohmyfetch](https://github.com/unjs/ohmyfetch) * `method`: Request method * `params`: Query params diff --git a/packages/nuxt3/src/app/composables/asyncData.ts b/packages/nuxt3/src/app/composables/asyncData.ts index 1451feaa6be..de4d632fa25 100644 --- a/packages/nuxt3/src/app/composables/asyncData.ts +++ b/packages/nuxt3/src/app/composables/asyncData.ts @@ -21,7 +21,7 @@ export interface AsyncDataOptions< transform?: Transform pick?: PickKeys watch?: MultiWatchSources - cache?: boolean + initialCache?: boolean } export interface RefreshOptions { @@ -63,7 +63,7 @@ export function useAsyncData< console.warn('[useAsyncData] `defer` has been renamed to `lazy`. Support for `defer` will be removed in RC.') } options.lazy = options.lazy ?? (options as any).defer ?? false - options.cache = options.cache ?? true + options.initialCache = options.initialCache ?? true // Setup nuxt instance payload const nuxt = useNuxtApp() @@ -93,7 +93,7 @@ export function useAsyncData< return nuxt._asyncDataPromises[key] } // Avoid fetching same key that is already fetched - if (opts._initial && options.cache && nuxt.payload.data[key] !== undefined) { + if (opts._initial && options.initialCache && nuxt.payload.data[key] !== undefined) { return nuxt.payload.data[key] } asyncData.pending.value = true diff --git a/packages/nuxt3/src/app/composables/fetch.ts b/packages/nuxt3/src/app/composables/fetch.ts index f8015f09912..2a055d83094 100644 --- a/packages/nuxt3/src/app/composables/fetch.ts +++ b/packages/nuxt3/src/app/composables/fetch.ts @@ -12,10 +12,9 @@ export interface UseFetchOptions< Transform extends _Transform = _Transform, PickKeys extends KeyOfRes = KeyOfRes > extends - Omit, 'cache'>, - Omit + AsyncDataOptions, + FetchOptions { - cache?: boolean | RequestCache, key?: string } @@ -45,7 +44,6 @@ export function useFetch< const _asyncDataOptions: AsyncDataOptions = { ...opts, - cache: requestCacheToCacheOption(opts.cache), watch: [ _request, ...(opts.watch || []) @@ -59,22 +57,6 @@ export function useFetch< return asyncData } -// Maps request cache option to useAsyncData cache strategy -// https://developer.mozilla.org/en-US/docs/Web/API/Request/cache -function requestCacheToCacheOption (input: undefined | boolean | RequestCache): AsyncDataOptions['cache'] { - // Async data possible options - const t = typeof input - if (t === 'boolean' || t === 'undefined') { - return input as boolean | undefined - } - // Map values - if (input === 'force-cache') { - return true - } - // Use default behavior for rest - return undefined -} - export function useLazyFetch< ResT = void, ReqT extends string = string, diff --git a/playground/app.vue b/playground/app.vue index c93a9dcaf5f..1d94b12f2c6 100644 --- a/playground/app.vue +++ b/playground/app.vue @@ -1,4 +1,6 @@