mirror of https://github.com/alibaba/ice.git
refactor: app data loader (#689)
* refactor: getAppData to dataLoader * refactor: merge data loader logic in one file * fix: comments
This commit is contained in:
parent
e21fb48509
commit
6ce0835d9b
|
|
@ -1,6 +1,5 @@
|
||||||
import { defineAppConfig } from 'ice';
|
import { defineAppConfig, defineDataLoader } from 'ice';
|
||||||
import { isWeb, isNode } from '@uni/env';
|
import { isWeb, isNode } from '@uni/env';
|
||||||
import type { GetAppData } from 'ice';
|
|
||||||
|
|
||||||
if (process.env.ICE_CORE_ERROR_BOUNDARY === 'true') {
|
if (process.env.ICE_CORE_ERROR_BOUNDARY === 'true') {
|
||||||
console.error('__REMOVED__');
|
console.error('__REMOVED__');
|
||||||
|
|
@ -26,10 +25,10 @@ export default defineAppConfig(() => ({
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const getAppData: GetAppData = () => {
|
export const dataLoader = defineDataLoader(() => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
resolve({
|
resolve({
|
||||||
title: 'gogogogo',
|
title: 'gogogogo',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { defineAppConfig } from 'ice';
|
import { defineAppConfig, defineDataLoader } from 'ice';
|
||||||
import type { GetAppData } from 'ice';
|
|
||||||
|
|
||||||
export default defineAppConfig(() => ({
|
export default defineAppConfig(() => ({
|
||||||
app: {
|
app: {
|
||||||
|
|
@ -7,7 +6,7 @@ export default defineAppConfig(() => ({
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const getAppData: GetAppData = () => {
|
export const dataLoader = defineDataLoader(() => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
resolve({
|
resolve({
|
||||||
title: 'gogogogo',
|
title: 'gogogogo',
|
||||||
|
|
@ -16,4 +15,4 @@ export const getAppData: GetAppData = () => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
import { defineAppConfig, type GetAppData } from 'ice';
|
import { defineAppConfig, defineDataLoader } from 'ice';
|
||||||
|
|
||||||
export const getAppData: GetAppData = () => {
|
export const dataLoader = defineDataLoader(() => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
resolve({
|
resolve({
|
||||||
success: true,
|
success: true,
|
||||||
id: 34293,
|
id: 34293,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
|
|
||||||
export const miniappManifest = {
|
export const miniappManifest = {
|
||||||
title: 'miniapp test',
|
title: 'miniapp test',
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { defineAppConfig, Link } from 'ice';
|
import { defineAppConfig, defineDataLoader, Link } from 'ice';
|
||||||
import type { GetAppData } from 'ice';
|
|
||||||
import { defineAuthConfig } from '@ice/plugin-auth/esm/types';
|
import { defineAuthConfig } from '@ice/plugin-auth/esm/types';
|
||||||
|
|
||||||
export default defineAppConfig(() => ({}));
|
export default defineAppConfig(() => ({}));
|
||||||
|
|
@ -21,7 +20,7 @@ export const authConfig = defineAuthConfig((data) => {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
export const getAppData: GetAppData = () => {
|
export const dataLoader = defineDataLoader(() => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
resolve({
|
resolve({
|
||||||
auth: {
|
auth: {
|
||||||
|
|
@ -29,4 +28,4 @@ export const getAppData: GetAppData = () => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
import { request as requestAPI } from 'ice';
|
import { request as requestAPI, defineDataLoader } from 'ice';
|
||||||
import { defineRequestConfig } from '@ice/plugin-request/esm/types';
|
import { defineRequestConfig } from '@ice/plugin-request/esm/types';
|
||||||
|
|
||||||
export async function getAppData() {
|
export const dataLader = defineDataLoader(async () => {
|
||||||
try {
|
try {
|
||||||
return await requestAPI('/user');
|
return await requestAPI('/user');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('request error', err);
|
console.log('request error', err);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
app: {
|
app: {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import type { GetAppData } from 'ice';
|
import { defineAppConfig, defineDataLoader } from 'ice';
|
||||||
import { defineAppConfig } from 'ice';
|
|
||||||
import { defineStoreConfig } from '@ice/plugin-store/esm/types';
|
import { defineStoreConfig } from '@ice/plugin-store/esm/types';
|
||||||
|
|
||||||
export const store = defineStoreConfig(async (appData) => {
|
export const store = defineStoreConfig(async (appData) => {
|
||||||
|
|
@ -10,7 +9,7 @@ export const store = defineStoreConfig(async (appData) => {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
export const getAppData: GetAppData = () => {
|
export const dataLoader = defineDataLoader(() => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
resolve({
|
resolve({
|
||||||
user: {
|
user: {
|
||||||
|
|
@ -18,6 +17,6 @@ export const getAppData: GetAppData = () => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
|
|
||||||
export default defineAppConfig(() => ({}));
|
export default defineAppConfig(() => ({}));
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
import { defineAppConfig } from '../disable-data-loader/.ice';
|
|
||||||
import type { GetAppData } from '../disable-data-loader/.ice';
|
|
||||||
|
|
||||||
export default defineAppConfig(() => ({
|
|
||||||
app: {
|
|
||||||
rootId: 'app',
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const getAppData: GetAppData = () => {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
resolve({
|
|
||||||
title: 'gogogogo',
|
|
||||||
auth: {
|
|
||||||
admin: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
{
|
|
||||||
"compileOnSave": false,
|
|
||||||
"buildOnSave": false,
|
|
||||||
"compilerOptions": {
|
|
||||||
"baseUrl": "../disable-data-loader",
|
|
||||||
"outDir": "../disable-data-loader/build",
|
|
||||||
"module": "esnext",
|
|
||||||
"target": "es6",
|
|
||||||
"jsx": "react-jsx",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"allowSyntheticDefaultImports": true,
|
|
||||||
"lib": ["es6", "dom"],
|
|
||||||
"sourceMap": true,
|
|
||||||
"allowJs": true,
|
|
||||||
"rootDir": "../disable-data-loader",
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"noImplicitReturns": true,
|
|
||||||
"noImplicitThis": true,
|
|
||||||
"noImplicitAny": false,
|
|
||||||
"importHelpers": true,
|
|
||||||
"strictNullChecks": true,
|
|
||||||
"suppressImplicitAnyIndexErrors": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"paths": {
|
|
||||||
"@/*": ["../disable-data-loader/src/*"],
|
|
||||||
"ice": ["../disable-data-loader/.ice"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"include": ["../disable-data-loader/src", "../disable-data-loader/.ice", "../disable-data-loader/ice.config.*"],
|
|
||||||
"exclude": ["../disable-data-loader/node_modules", "../disable-data-loader/build", "../disable-data-loader/public"]
|
|
||||||
}
|
|
||||||
|
|
@ -141,7 +141,7 @@ async function createService({ rootDir, command, commandArgs }: CreateServiceOpt
|
||||||
const coreEnvKeys = getCoreEnvKeys();
|
const coreEnvKeys = getCoreEnvKeys();
|
||||||
|
|
||||||
const routesInfo = await generateRoutesInfo(rootDir, routesConfig);
|
const routesInfo = await generateRoutesInfo(rootDir, routesConfig);
|
||||||
const hasExportAppData = (await getFileExports({ rootDir, file: 'src/app' })).includes('getAppData');
|
const hasExportAppData = (await getFileExports({ rootDir, file: 'src/app' })).includes('dataLoader');
|
||||||
const csr = !userConfig.ssr && !userConfig.ssg;
|
const csr = !userConfig.ssr && !userConfig.ssg;
|
||||||
|
|
||||||
const disableRouter = userConfig?.optimization?.router && routesInfo.routesCount <= 1;
|
const disableRouter = userConfig?.optimization?.router && routesInfo.routesCount <= 1;
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ const getWatchEvents = (options: Options): WatchEvent[] => {
|
||||||
/src\/app.(js|jsx|ts|tsx)/,
|
/src\/app.(js|jsx|ts|tsx)/,
|
||||||
async (event: string) => {
|
async (event: string) => {
|
||||||
if (event === 'change') {
|
if (event === 'change') {
|
||||||
const hasExportAppData = (await getFileExports({ rootDir, file: 'src/app' })).includes('getAppData');
|
const hasExportAppData = (await getFileExports({ rootDir, file: 'src/app' })).includes('dataLoader');
|
||||||
if (hasExportAppData !== !!cache.get('hasExportAppData')) {
|
if (hasExportAppData !== !!cache.get('hasExportAppData')) {
|
||||||
cache.set('hasExportAppData', hasExportAppData ? 'true' : '');
|
cache.set('hasExportAppData', hasExportAppData ? 'true' : '');
|
||||||
renderExportsTemplate({
|
renderExportsTemplate({
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ export default class DataLoaderPlugin {
|
||||||
public apply(compiler: Compiler) {
|
public apply(compiler: Compiler) {
|
||||||
const plugins = this.getAllPlugin(['keepExports']) as PluginData[];
|
const plugins = this.getAllPlugin(['keepExports']) as PluginData[];
|
||||||
|
|
||||||
let keepExports = ['dataLoader', 'getAppData'];
|
let keepExports = ['dataLoader'];
|
||||||
plugins.forEach(plugin => {
|
plugins.forEach(plugin => {
|
||||||
if (plugin.keepExports) {
|
if (plugin.keepExports) {
|
||||||
keepExports = keepExports.concat(plugin.keepExports);
|
keepExports = keepExports.concat(plugin.keepExports);
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ import * as app from '@/app';
|
||||||
const loaders = {};
|
const loaders = {};
|
||||||
<% } -%>
|
<% } -%>
|
||||||
|
|
||||||
<% if(hasExportAppData) {-%>loaders['__app'] = app.getAppData;<% } -%>
|
<% if(hasExportAppData) {-%>loaders['__app'] = app.dataLoader;<% } -%>
|
||||||
|
|
||||||
<% if(!dataLoaderImport.imports) {-%>
|
<% if(!dataLoaderImport.imports) {-%>
|
||||||
let fetcher = (options) => {
|
let fetcher = (options) => {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import type { AppExport, AppData, RequestContext } from './types.js';
|
import type { AppExport, AppData, RequestContext } from './types.js';
|
||||||
|
import { callDataLoader } from './dataLoader.js';
|
||||||
|
|
||||||
const Context = React.createContext<AppData | undefined>(undefined);
|
const Context = React.createContext<AppData | undefined>(undefined);
|
||||||
|
|
||||||
|
|
@ -23,9 +24,15 @@ async function getAppData(appExport: AppExport, requestContext?: RequestContext)
|
||||||
return await globalLoader.getData('__app');
|
return await globalLoader.getData('__app');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (appExport?.getAppData) {
|
if (appExport?.dataLoader) {
|
||||||
return await appExport.getAppData(requestContext);
|
return await appExport.dataLoader(requestContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loader = appExport?.dataLoader;
|
||||||
|
|
||||||
|
if (!loader) return null;
|
||||||
|
|
||||||
|
await callDataLoader(loader, requestContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,21 @@
|
||||||
import type { DataLoaderConfig, RuntimeModules, AppExport, RuntimePlugin, CommonJsRuntime } from './types.js';
|
import type { DataLoaderConfig, DataLoaderResult, RuntimeModules, AppExport, RuntimePlugin, CommonJsRuntime } from './types.js';
|
||||||
import getRequestContext from './requestContext.js';
|
import getRequestContext from './requestContext.js';
|
||||||
import { setFetcher, loadDataByCustomFetcher } from './dataLoaderFetcher.js';
|
|
||||||
|
|
||||||
interface Loaders {
|
interface Loaders {
|
||||||
[routeId: string]: DataLoaderConfig;
|
[routeId: string]: DataLoaderConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Result {
|
interface CachedResult {
|
||||||
value: any;
|
value: any;
|
||||||
status: string;
|
status: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface LoaderOptions {
|
||||||
|
fetcher: Function;
|
||||||
|
runtimeModules: RuntimeModules['statics'];
|
||||||
|
appExport: AppExport;
|
||||||
|
}
|
||||||
|
|
||||||
export function defineDataLoader(dataLoaderConfig: DataLoaderConfig): DataLoaderConfig {
|
export function defineDataLoader(dataLoaderConfig: DataLoaderConfig): DataLoaderConfig {
|
||||||
return dataLoaderConfig;
|
return dataLoaderConfig;
|
||||||
}
|
}
|
||||||
|
|
@ -23,12 +28,43 @@ export function defineStaticDataLoader(dataLoaderConfig: DataLoaderConfig): Data
|
||||||
return dataLoaderConfig;
|
return dataLoaderConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cache = new Map<string, Result>();
|
/**
|
||||||
|
* Custom fetcher for load static data loader config.
|
||||||
|
* Set globally to avoid passing this fetcher too deep.
|
||||||
|
*/
|
||||||
|
let dataLoaderFetcher;
|
||||||
|
|
||||||
|
export function setFetcher(customFetcher) {
|
||||||
|
dataLoaderFetcher = customFetcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loadDataByCustomFetcher(config) {
|
||||||
|
return dataLoaderFetcher(config);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start getData once loader is ready, and set to cache.
|
* Handle for different dataLoader.
|
||||||
*/
|
*/
|
||||||
function loadInitialData(loaders: Loaders) {
|
export function callDataLoader(dataLoader: DataLoaderConfig, requestContext): DataLoaderResult {
|
||||||
|
if (Array.isArray(dataLoader)) {
|
||||||
|
return dataLoader.map(loader => {
|
||||||
|
return typeof loader === 'object' ? loadDataByCustomFetcher(loader) : loader(requestContext);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof dataLoader === 'object') {
|
||||||
|
return loadDataByCustomFetcher(dataLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataLoader(requestContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
const cache = new Map<string, CachedResult>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start getData once data-loader.js is ready in client, and set to cache.
|
||||||
|
*/
|
||||||
|
function loadInitialDataInClient(loaders: Loaders) {
|
||||||
const context = (window as any).__ICE_APP_CONTEXT__ || {};
|
const context = (window as any).__ICE_APP_CONTEXT__ || {};
|
||||||
const matchedIds = context.matchedIds || [];
|
const matchedIds = context.matchedIds || [];
|
||||||
const routesData = context.routesData || {};
|
const routesData = context.routesData || {};
|
||||||
|
|
@ -48,22 +84,7 @@ function loadInitialData(loaders: Loaders) {
|
||||||
|
|
||||||
if (dataLoader) {
|
if (dataLoader) {
|
||||||
const requestContext = getRequestContext(window.location);
|
const requestContext = getRequestContext(window.location);
|
||||||
|
const loader = callDataLoader(dataLoader, requestContext);
|
||||||
let loader;
|
|
||||||
|
|
||||||
if (Array.isArray(dataLoader)) {
|
|
||||||
loader = dataLoader.map(loader => {
|
|
||||||
if (typeof loader === 'object') {
|
|
||||||
return loadDataByCustomFetcher(loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
return loader(requestContext);
|
|
||||||
});
|
|
||||||
} else if (typeof dataLoader === 'object') {
|
|
||||||
return loadDataByCustomFetcher(loader);
|
|
||||||
} else {
|
|
||||||
loader = dataLoader(requestContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
cache.set(id, {
|
cache.set(id, {
|
||||||
value: loader,
|
value: loader,
|
||||||
|
|
@ -73,17 +94,12 @@ function loadInitialData(loaders: Loaders) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Options {
|
|
||||||
fetcher: Function;
|
|
||||||
runtimeModules: RuntimeModules['statics'];
|
|
||||||
appExport: AppExport;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Init data loader in client side.
|
||||||
* Load initial data and register global loader.
|
* Load initial data and register global loader.
|
||||||
* In order to load data, JavaScript modules, CSS and other assets in parallel.
|
* In order to load data, JavaScript modules, CSS and other assets in parallel.
|
||||||
*/
|
*/
|
||||||
async function init(loadersConfig: Loaders, options: Options) {
|
async function init(loadersConfig: Loaders, options: LoaderOptions) {
|
||||||
const {
|
const {
|
||||||
fetcher,
|
fetcher,
|
||||||
runtimeModules,
|
runtimeModules,
|
||||||
|
|
@ -108,7 +124,7 @@ async function init(loadersConfig: Loaders, options: Options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
loadInitialData(loadersConfig);
|
loadInitialDataInClient(loadersConfig);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Load initial data error: ', error);
|
console.error('Load initial data error: ', error);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
/**
|
|
||||||
* custom fetcher for load static data loader config
|
|
||||||
* set globally to avoid passing this fetcher too deep
|
|
||||||
*/
|
|
||||||
|
|
||||||
let fetcher;
|
|
||||||
|
|
||||||
export function setFetcher(customFetcher) {
|
|
||||||
fetcher = customFetcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function loadDataByCustomFetcher(config) {
|
|
||||||
return fetcher(config);
|
|
||||||
}
|
|
||||||
|
|
@ -15,7 +15,6 @@ import type {
|
||||||
AppProvider,
|
AppProvider,
|
||||||
RouteWrapper,
|
RouteWrapper,
|
||||||
RenderMode,
|
RenderMode,
|
||||||
GetAppData,
|
|
||||||
DataLoaderConfig,
|
DataLoaderConfig,
|
||||||
RouteWrapperConfig,
|
RouteWrapperConfig,
|
||||||
} from './types.js';
|
} from './types.js';
|
||||||
|
|
@ -94,7 +93,6 @@ export type {
|
||||||
AppProvider,
|
AppProvider,
|
||||||
RouteWrapper,
|
RouteWrapper,
|
||||||
RenderMode,
|
RenderMode,
|
||||||
GetAppData,
|
|
||||||
DataLoaderConfig,
|
DataLoaderConfig,
|
||||||
RunClientAppOptions,
|
RunClientAppOptions,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { RouteComponent } from './types.js';
|
||||||
import type { RouteItem, RouteModules, RouteWrapperConfig, RouteMatch, RequestContext, RoutesConfig, RoutesData, RenderMode } from './types.js';
|
import type { RouteItem, RouteModules, RouteWrapperConfig, RouteMatch, RequestContext, RoutesConfig, RoutesData, RenderMode } from './types.js';
|
||||||
import RouteWrapper from './RouteWrapper.js';
|
import RouteWrapper from './RouteWrapper.js';
|
||||||
import { useAppContext } from './AppContext.js';
|
import { useAppContext } from './AppContext.js';
|
||||||
import { loadDataByCustomFetcher } from './dataLoaderFetcher.js';
|
import { callDataLoader } from './dataLoader.js';
|
||||||
|
|
||||||
type RouteModule = Pick<RouteItem, 'id' | 'load'>;
|
type RouteModule = Pick<RouteItem, 'id' | 'load'>;
|
||||||
|
|
||||||
|
|
@ -79,16 +79,8 @@ export async function loadRoutesData(
|
||||||
loader = dataLoader;
|
loader = dataLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(loader)) {
|
if (loader) {
|
||||||
routesData[id] = await Promise.all(loader.map(load => {
|
routesData[id] = await callDataLoader(loader, requestContext);
|
||||||
if (typeof load === 'object') {
|
|
||||||
return loadDataByCustomFetcher(load);
|
|
||||||
}
|
|
||||||
|
|
||||||
return load(requestContext);
|
|
||||||
}));
|
|
||||||
} else if (loader) {
|
|
||||||
routesData[id] = await loader(requestContext);
|
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import getRequestContext from './requestContext.js';
|
||||||
import getAppConfig from './appConfig.js';
|
import getAppConfig from './appConfig.js';
|
||||||
import matchRoutes from './matchRoutes.js';
|
import matchRoutes from './matchRoutes.js';
|
||||||
import DefaultAppRouter from './AppRouter.js';
|
import DefaultAppRouter from './AppRouter.js';
|
||||||
import { setFetcher } from './dataLoaderFetcher.js';
|
import { setFetcher } from './dataLoader.js';
|
||||||
|
|
||||||
export interface RunClientAppOptions {
|
export interface RunClientAppOptions {
|
||||||
app: AppExport;
|
app: AppExport;
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,11 @@ export type RouteConfig<T = {}> = T & {
|
||||||
export interface AppExport {
|
export interface AppExport {
|
||||||
default?: AppConfig;
|
default?: AppConfig;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
getAppData?: GetAppData;
|
dataLoader?: DataLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GetAppData = (ctx: RequestContext) => (Promise<AppData> | AppData);
|
export type DataLoaderResult = (Promise<RouteData> | RouteData) | RouteData;
|
||||||
|
export type DataLoader = (ctx: RequestContext) => DataLoaderResult;
|
||||||
export type DataLoader = (ctx: RequestContext) => (Promise<RouteData> | RouteData) | RouteData;
|
|
||||||
|
|
||||||
interface StaticDataLoader {
|
interface StaticDataLoader {
|
||||||
key?: string;
|
key?: string;
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ describe('run client app', () => {
|
||||||
it('run with static runtime', async () => {
|
it('run with static runtime', async () => {
|
||||||
await runClientApp({
|
await runClientApp({
|
||||||
app: {
|
app: {
|
||||||
getAppData: async () => {
|
dataLoader: async () => {
|
||||||
return { msg: staticMsg };
|
return { msg: staticMsg };
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -258,7 +258,7 @@ describe('run client app', () => {
|
||||||
let executed = false;
|
let executed = false;
|
||||||
await runClientApp({
|
await runClientApp({
|
||||||
app: {
|
app: {
|
||||||
getAppData: async () => {
|
dataLoader: async () => {
|
||||||
executed = true;
|
executed = true;
|
||||||
return { msg: '-getAppData' };
|
return { msg: '-getAppData' };
|
||||||
},
|
},
|
||||||
|
|
@ -287,7 +287,7 @@ describe('run client app', () => {
|
||||||
|
|
||||||
await runClientApp({
|
await runClientApp({
|
||||||
app: {
|
app: {
|
||||||
getAppData: async () => {
|
dataLoader: async () => {
|
||||||
executed = true;
|
executed = true;
|
||||||
return { msg: 'app' };
|
return { msg: 'app' };
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -140,12 +140,14 @@ function Home() {
|
||||||
|
|
||||||
### useAppData
|
### useAppData
|
||||||
|
|
||||||
useAppData 返回应用全局数据,需要搭配 `src/app.ts` 中导出的 getAppData 使用:
|
useAppData 返回应用全局数据,需要搭配 `src/app.ts` 中导出的 `dataLoader` 使用:
|
||||||
|
|
||||||
```ts title="src/app.ts"
|
```ts title="src/app.ts"
|
||||||
export async function getAppData() {
|
import { defineDataLoader } from 'ice';
|
||||||
|
|
||||||
|
export const dataLoader = defineDataLoader(() => {
|
||||||
return await fetch('/api/user');
|
return await fetch('/api/user');
|
||||||
}
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
在任意组件内进行消费:
|
在任意组件内进行消费:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue