From 1216a45a088e37e89bc98d9c67eb99035083330d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E9=95=87?= Date: Mon, 29 Jul 2024 10:54:20 +0800 Subject: [PATCH 1/3] fix: use the newest params to request modified in `beforeRequest` --- .changeset/spicy-moose-pull.md | 5 +++ packages/alova/src/functions/sendRequest.ts | 5 ++- .../test/browser/global/createAlova.spec.ts | 34 +++++++++++++++++++ packages/alova/typings/index.d.ts | 4 ++- 4 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 .changeset/spicy-moose-pull.md diff --git a/.changeset/spicy-moose-pull.md b/.changeset/spicy-moose-pull.md new file mode 100644 index 00000000..5cd0a47b --- /dev/null +++ b/.changeset/spicy-moose-pull.md @@ -0,0 +1,5 @@ +--- +'alova': patch +--- + +use the newest params to request modified in `beforeRequest` diff --git a/packages/alova/src/functions/sendRequest.ts b/packages/alova/src/functions/sendRequest.ts index 9da9ee3d..b794e7e1 100644 --- a/packages/alova/src/functions/sendRequest.ts +++ b/packages/alova/src/functions/sendRequest.ts @@ -95,11 +95,12 @@ export default function sendRequest(methodInstance: Me const response = async () => { const { beforeRequest = noop, responded, requestAdapter, cacheLogger } = getOptions(methodInstance); const methodKey = getMethodInternalKey(methodInstance); + const { s: toStorage, t: tag, m: cacheMode, e: expireMilliseconds } = getLocalCacheConfigParam(methodInstance); const { id, l1Cache, l2Cache, snapshots } = getContext(methodInstance); // 获取受控缓存或非受控缓存 const { cacheFor } = getConfig(methodInstance); - const { baseURL, url: newUrl, type, data, hitSource: methodHitSource } = methodInstance; + const { hitSource: methodHitSource } = methodInstance; // 如果当前method设置了受控缓存,则看是否有自定义的数据 let cachedResponse = await (isFn(cacheFor) @@ -121,11 +122,13 @@ export default function sendRequest(methodInstance: Me } // 克隆method作为参数传给beforeRequest,防止多次使用原method实例请求时产生副作用 + // 放在` let cachedResponse = await ...`之后,解决在method.send中先赋值promise给method实例的问题,否则在clonedMethod中promise为undefined const clonedMethod = cloneMethod(methodInstance); // 发送请求前调用钩子函数 // beforeRequest支持同步函数和异步函数 await beforeRequest(clonedMethod); + const { baseURL, url: newUrl, type, data } = clonedMethod; const { params = {}, headers = {}, transform = $self, shareRequest } = getConfig(clonedMethod); const namespacedAdapterReturnMap = (adapterReturnMap[id] = adapterReturnMap[id] || {}); let requestAdapterCtrls = namespacedAdapterReturnMap[methodKey]; diff --git a/packages/alova/test/browser/global/createAlova.spec.ts b/packages/alova/test/browser/global/createAlova.spec.ts index 3ff9c64a..81fc944a 100644 --- a/packages/alova/test/browser/global/createAlova.spec.ts +++ b/packages/alova/test/browser/global/createAlova.spec.ts @@ -105,6 +105,40 @@ describe('createAlova', () => { expect(mockFn).toHaveBeenCalled(); }); + test('should use the newest params to request modified in `beforeRequest` hook', async () => { + const alova = createAlova({ + requestAdapter: adapterFetch(), + beforeRequest: method => { + method.url = '/unit-test'; + method.config.params = { + a: 7, + b: 8 + }; + method.config.headers = { + newHeader: 123 + }; + method.baseURL = 'http://localhost:3000'; + }, + responded: r => r.json() + }); + const Get = alova.Get('/unknown', { + params: { a: 'a', b: 'str' }, + headers: { + 'Content-Type': 'application/json' + } + }); + const result = await Get; + expect(result).toStrictEqual({ + code: 200, + msg: '', + data: { + path: '/unit-test', + method: 'GET', + params: { a: '7', b: '8' } + } + }); + }); + test('`beforeRequest` hook support async function', async () => { const alova = createAlova({ baseURL: 'http://localhost:3000', diff --git a/packages/alova/typings/index.d.ts b/packages/alova/typings/index.d.ts index ca512913..6abdd175 100644 --- a/packages/alova/typings/index.d.ts +++ b/packages/alova/typings/index.d.ts @@ -600,9 +600,11 @@ export declare class Method { onUpload(progressHandler: ProgressHandler): () => void; } -export interface MethodSnapshotContainer { +export class MethodSnapshotContainer { records: Record>>; + capacity: number; + occupy: number; save(methodInstance: Method): void; From 51f1eb3ecd9b6f3eed1374408d3abc8cad53b59a Mon Sep 17 00:00:00 2001 From: MeetinaXD Date: Sat, 3 Aug 2024 14:54:03 +0800 Subject: [PATCH 2/3] fix: ssr in codesandbox --- packages/alova/src/defaults/cacheLogger.ts | 5 +++-- packages/alova/src/globalConfig.ts | 4 +++- packages/alova/src/index.ts | 4 ++-- packages/alova/test/browser/global/ssr.spec.ts | 17 +++++++++++++++++ packages/alova/typings/index.d.ts | 8 ++++++++ .../core/implements/createRequestState.ts | 15 +++------------ packages/client/src/hooks/useAutoRequest.ts | 6 +++--- packages/shared/src/vars.ts | 6 ++++-- packages/shared/test/isSSR.spec.ts | 18 ++++++++++++++++-- 9 files changed, 59 insertions(+), 24 deletions(-) create mode 100644 packages/alova/test/browser/global/ssr.spec.ts diff --git a/packages/alova/src/defaults/cacheLogger.ts b/packages/alova/src/defaults/cacheLogger.ts index 113b805e..8615d206 100644 --- a/packages/alova/src/defaults/cacheLogger.ts +++ b/packages/alova/src/defaults/cacheLogger.ts @@ -1,4 +1,5 @@ -import { STORAGE_RESTORE, isSSR, len } from '@alova/shared/vars'; +import { globalConfigMap } from '@/globalConfig'; +import { STORAGE_RESTORE, len } from '@alova/shared/vars'; import { CacheMode } from '~/typings'; import { Method } from '..'; @@ -16,7 +17,7 @@ export default (response: any, methodInstance: Method, cacheMode: CacheMode, tag const labelStyle = '\x1B[32m%s\x1B[39m'; const startSep = ` [HitCache]${url} `; const endSepFn = () => Array(len(startSep) + 1).join('^'); - if (isSSR) { + if (globalConfigMap.ssr) { log(hdStyle, startSep); log(labelStyle, ' Cache ', response); log(labelStyle, ' Mode ', cacheMode); diff --git a/packages/alova/src/globalConfig.ts b/packages/alova/src/globalConfig.ts index 3e310829..ead5ce97 100644 --- a/packages/alova/src/globalConfig.ts +++ b/packages/alova/src/globalConfig.ts @@ -1,7 +1,9 @@ +import { defaultIsSSR } from '@alova/shared/vars'; import { AlovaGlobalConfig } from '~/typings'; export let globalConfigMap: Required = { - autoHitCache: 'global' + autoHitCache: 'global', + ssr: defaultIsSSR }; /** diff --git a/packages/alova/src/index.ts b/packages/alova/src/index.ts index f3658ecb..52501333 100644 --- a/packages/alova/src/index.ts +++ b/packages/alova/src/index.ts @@ -1,5 +1,5 @@ -export { default as Method } from './Method'; export { createAlova } from './alova'; export * from './functions/manipulateCache'; -export { default as globalConfig } from './globalConfig'; +export { default as globalConfig, globalConfigMap } from './globalConfig'; +export { default as Method } from './Method'; export { promiseStatesHook } from './utils/helper'; diff --git a/packages/alova/test/browser/global/ssr.spec.ts b/packages/alova/test/browser/global/ssr.spec.ts new file mode 100644 index 00000000..3aeb1cc5 --- /dev/null +++ b/packages/alova/test/browser/global/ssr.spec.ts @@ -0,0 +1,17 @@ +import globalConfig, { globalConfigMap } from '@/globalConfig'; + +describe('ssr', () => { + test('default ssr option', () => { + expect(globalConfigMap.ssr).toBeFalsy(); + }); + + test('set ssr to false', () => { + globalConfig({ ssr: false }); + expect(globalConfigMap.ssr).toBeFalsy(); + }); + + test('set ssr to true', () => { + globalConfig({ ssr: true }); + expect(globalConfigMap.ssr).toBeTruthy(); + }); +}); diff --git a/packages/alova/typings/index.d.ts b/packages/alova/typings/index.d.ts index 6abdd175..7e5fe5fb 100644 --- a/packages/alova/typings/index.d.ts +++ b/packages/alova/typings/index.d.ts @@ -698,6 +698,12 @@ export interface AlovaGlobalConfig { * @default 'global' */ autoHitCache?: 'global' | 'self' | 'close'; + /** + * whether the app is running in the server + * If not set or set to `undefined`, alova determines whether it is now running in the server + * @default undefined + */ + ssr?: boolean | undefined; } // ************ exports *************** @@ -813,6 +819,8 @@ export declare function queryCache( */ export declare function hitCacheBySource(sourceMethod: Method): Promise; +export declare const globalConfigMap: Required; + /** * Set global configuration * @param config configuration diff --git a/packages/client/src/hooks/core/implements/createRequestState.ts b/packages/client/src/hooks/core/implements/createRequestState.ts index 7887259f..8d086f0c 100644 --- a/packages/client/src/hooks/core/implements/createRequestState.ts +++ b/packages/client/src/hooks/core/implements/createRequestState.ts @@ -12,18 +12,9 @@ import { sloughConfig, statesHookHelper } from '@alova/shared/function'; -import { - PromiseCls, - falseValue, - forEach, - isArray, - isSSR, - promiseCatch, - trueValue, - undefinedValue -} from '@alova/shared/vars'; +import { PromiseCls, falseValue, forEach, isArray, promiseCatch, trueValue, undefinedValue } from '@alova/shared/vars'; import type { AlovaGlobalCacheAdapter, FrontRequestState, Method, Progress } from 'alova'; -import { AlovaGenerics, promiseStatesHook } from 'alova'; +import { AlovaGenerics, globalConfigMap, promiseStatesHook } from 'alova'; import { AlovaCompleteEvent, AlovaErrorEvent, @@ -161,7 +152,7 @@ export default function createRequestState { let offVisiblity = noop; let offPolling = noop; onMounted(() => { - if (!isSSR) { + if (!globalConfigMap.ssr) { offNetwork = enableNetwork ? useAutoRequest.onNetwork(notify, config) : offNetwork; offFocus = enableFocus ? useAutoRequest.onFocus(notify, config) : offFocus; offVisiblity = enableVisibility ? useAutoRequest.onVisibility(notify, config) : offVisiblity; diff --git a/packages/shared/src/vars.ts b/packages/shared/src/vars.ts index d7f7e09f..9eee06b3 100644 --- a/packages/shared/src/vars.ts +++ b/packages/shared/src/vars.ts @@ -54,8 +54,10 @@ export const defineProperty = (o: object, key: string | symbol, value: any, isDe // 是否为服务端运行,node和bun通过process判断,deno通过Deno判断 // 部分框架(如支付宝和 uniapp)会注入 process 对象作为全局变量使用 // 因此使用服务端独有的 process.cwd 函数作为判断依据 -export const isSSR = - typeof process !== undefStr ? typeof (process as any).cwd === 'function' : typeof Deno !== undefStr; +export const defaultIsSSR = + typeof window === undefStr && + (typeof process !== undefStr ? typeof (process as any).cwd === 'function' : typeof Deno !== undefStr); +export const isSSR = defaultIsSSR; /** cache mode */ // only cache in memory, it's default option diff --git a/packages/shared/test/isSSR.spec.ts b/packages/shared/test/isSSR.spec.ts index 76084321..7d8f88d5 100644 --- a/packages/shared/test/isSSR.spec.ts +++ b/packages/shared/test/isSSR.spec.ts @@ -3,9 +3,14 @@ const undefStr = 'undefined'; const MockGlobal: any = {}; const isSSR = () => - typeof MockGlobal.process !== undefStr + typeof MockGlobal.window === undefStr && + (typeof MockGlobal.process !== undefStr ? typeof MockGlobal.process.cwd === 'function' - : typeof MockGlobal.Deno !== undefStr; + : typeof MockGlobal.Deno !== undefStr); + +const setGlobalWindow = (window: any) => { + MockGlobal.window = window; +}; const setGlobalProcess = (process: any) => { MockGlobal.process = process; @@ -16,6 +21,7 @@ const setGlobalDeno = (deno: any) => { // Mock the global process and Deno objects before each test beforeEach(() => { + delete MockGlobal.window; delete MockGlobal.process; delete MockGlobal.Deno; }); @@ -28,6 +34,14 @@ describe('isSSR', () => { expect(isSSR()).toBeFalsy(); }); + it('should return false in codesandbox environment', () => { + // Browser: process is undefined, Deno is undefined + setGlobalWindow({}); + setGlobalProcess({ cwd: () => 'test' }); + setGlobalDeno(undefined); + expect(isSSR()).toBeFalsy(); + }); + it('should return false in react-native environment', () => { // React Native: process is undefined, Deno is undefined setGlobalProcess(undefined); From 5b381b4c4cbfd802f8c80f17ad373b094e4606df Mon Sep 17 00:00:00 2001 From: MeetinaXD Date: Sat, 3 Aug 2024 14:58:51 +0800 Subject: [PATCH 3/3] chore: add changeset --- .changeset/polite-cheetahs-impress.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/polite-cheetahs-impress.md diff --git a/.changeset/polite-cheetahs-impress.md b/.changeset/polite-cheetahs-impress.md new file mode 100644 index 00000000..0f9f6333 --- /dev/null +++ b/.changeset/polite-cheetahs-impress.md @@ -0,0 +1,6 @@ +--- +'@alova/shared': patch +'alova': patch +--- + +fix: ssr in codesandbox