Skip to content

Commit

Permalink
Refactor: router (#6123)
Browse files Browse the repository at this point in the history
* chore: refactor unfinished

* feat: support create router

* refactor: render mode

* fix: code splitting false

* feat: add location for icestark

* chore: remove console

* test: examples

* fix: dataloader is undefined

* fix: test

* fix: test case

* fix: test case

* fix: types

* fix: test case

* fix: lock

* fix: update lock

* fix: hydration

* fix: router

* fix: router

* chore: log

* fix: hmr

* fix: test

* fix: test

* chore: optimize code

* Update singleRoute.test.tsx

* fix: types
  • Loading branch information
ClarkXia authored Apr 13, 2023
1 parent 7b04ca7 commit 4763bc7
Show file tree
Hide file tree
Showing 52 changed files with 889 additions and 1,077 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ export default function FrameworkLayout({ children }) {
</div>
</>
);
}
}
2 changes: 1 addition & 1 deletion examples/icestark-layout/src/pages/about.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ export default function About() {
<Link to="/">home</Link>
</>
);
}
}
1 change: 0 additions & 1 deletion examples/multi-target/ice.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { defineConfig } from '@ice/app';

export default defineConfig(() => ({
ssr: true,
ssg: true,
define: {
'process.env.NODE_ENV': JSON.stringify(true),
},
Expand Down
2 changes: 1 addition & 1 deletion examples/with-ssg/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ export const staticDataLoader = defineStaticDataLoader(() => {
return {
price: '0.00',
};
});
});
1 change: 1 addition & 0 deletions examples/with-store/ice.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { defineConfig } from '@ice/app';
import store from '@ice/plugin-store';

export default defineConfig(() => ({
ssg: false,
plugins: [
store({
resetPageState: true,
Expand Down
6 changes: 5 additions & 1 deletion examples/with-store/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@ export const dataLoader = defineDataLoader(() => {
});
});

export default defineAppConfig(() => ({}));
export default defineAppConfig(() => ({
router: {
type: 'hash',
},
}));
2 changes: 1 addition & 1 deletion packages/ice/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
"esbuild": "^0.16.5",
"jest": "^29.0.2",
"react": "^18.2.0",
"react-router": "^6.8.2",
"react-router": "6.10.0",
"unplugin": "^0.9.0",
"webpack": "^5.76.2",
"webpack-dev-server": "^4.7.4"
Expand Down
15 changes: 11 additions & 4 deletions packages/ice/src/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,22 @@ export const TARGETS = [

export const RUNTIME_EXPORTS = [
{
specifier: ['Link', 'Outlet', 'useParams', 'useSearchParams', 'useLocation', 'useNavigate'],
specifier: [
'Link',
'Outlet',
'useParams',
'useSearchParams',
'useLocation',
'useData',
'useConfig',
'useNavigate',
],
source: '@ice/runtime/router',
},
{
specifier: [
'defineAppConfig',
'useAppData',
'useData',
'useConfig',
'history',
'KeepAliveOutlet',
'useMounted',
Expand All @@ -60,4 +67,4 @@ export const RUNTIME_EXPORTS = [
],
source: '@ice/runtime',
},
];
];
24 changes: 22 additions & 2 deletions packages/ice/src/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,35 @@ export function getRoutesDefination(nestRouteManifest: NestedRouteManifest[], la
routeImports.push(`import * as ${routeSpecifier} from '${formatPath(componentPath)}';`);
loadStatement = routeSpecifier;
}
const component = `Component: () => WrapRouteComponent({
routeId: '${id}',
isLayout: ${layout},
routeExports: ${lazy ? 'componentModule' : loadStatement},
})`;
const loader = `loader: createRouteLoader({
routeId: '${id}',
requestContext,
renderMode,
module: ${lazy ? 'componentModule' : loadStatement},
})`;
const routeProperties: string[] = [
`path: '${formatPath(routePath || '')}',`,
`load: () => ${loadStatement},`,
`async lazy() {
${lazy ? `const componentModule = await ${loadStatement}` : ''};
return {
${lazy ? '...componentModule' : `...${loadStatement}`},
${component},
${loader},
};
},`,
// Empty errorElement to avoid default ui provided by react-router.
'ErrorBoundary: RouteErrorComponent,',
`componentName: '${componentName}',`,
`index: ${index},`,
`id: '${id}',`,
'exact: true,',
`exports: ${JSON.stringify(exports)},`,
];
].filter(Boolean);

if (layout) {
routeProperties.push('layout: true,');
Expand Down
2 changes: 1 addition & 1 deletion packages/ice/src/utils/injectInitialEntry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function injectInitialEntry(routeManifest: RouteManifest, outputDir: string) {
const routePaths = routeManifest.getFlattenRoute();
const routeItems = routeManifest.getNestedRoute();
routePaths.forEach((routePath) => {
const routeAsset = getRouteAsset(routeItems, routePath);
const routeAsset = getRouteAsset(routeItems as unknown as RouteItem[], routePath);
// Inject `initialPath` when router type is memory.
const routeAssetPath = path.join(outputDir, 'js', routeAsset);
if (fse.existsSync(routeAssetPath)) {
Expand Down
4 changes: 2 additions & 2 deletions packages/ice/templates/core/entry.client.tsx.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { runClientApp, getAppConfig } from '<%- iceRuntimePath %>';
import { commons, statics } from './runtimeModules';
import * as app from '@/app';
<% if (enableRoutes) { -%>
import routes from './routes';
import createRoutes from './routes';
<% } -%>
<%- runtimeOptions.imports %>
<% if(dataLoaderImport.imports) {-%><%-dataLoaderImport.imports%><% } -%>
Expand All @@ -23,7 +23,7 @@ const render = (customOptions = {}) => {
commons,
statics,
},
<% if (enableRoutes) { %>routes,<% } %>
<% if (enableRoutes) { %>createRoutes,<% } %>
basename: getRouterBasename(),
hydrate: <%- hydrate %>,
memoryRouter: <%- memoryRouter || false %>,
Expand Down
10 changes: 5 additions & 5 deletions packages/ice/templates/core/entry.server.ts.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Document from '@/document';
import type { RenderMode, DistType } from '@ice/runtime';
// @ts-ignore
import assetsManifest from 'virtual:assets-manifest.json';
import routes from './routes';
import createRoutes from './routes';
import routesConfig from './routes-config.bundle.mjs';
<% if(dataLoaderImport.imports) {-%><%-dataLoaderImport.imports%><% } -%>
<%- runtimeOptions.imports %>
Expand Down Expand Up @@ -47,15 +47,15 @@ interface RenderOptions {
export async function renderToHTML(requestContext, options: RenderOptions = {}) {
const { renderMode = 'SSR' } = options;
setRuntimeEnv(renderMode);

const mergedOptions = mergeOptions(options);
return await runtime.renderToHTML(requestContext, mergedOptions);
}

export async function renderToResponse(requestContext, options: RenderOptions = {}) {
const { renderMode = 'SSR' } = options;
setRuntimeEnv(renderMode);

const mergedOptions = mergeOptions(options);
return runtime.renderToResponse(requestContext, mergedOptions);
}
Expand All @@ -80,7 +80,7 @@ function mergeOptions(options) {
return {
app,
assetsManifest,
routes,
createRoutes,
runtimeModules,
Document,
serverOnlyBasename,
Expand All @@ -98,4 +98,4 @@ function mergeOptions(options) {
},
<% } -%>
};
}
}
4 changes: 0 additions & 4 deletions packages/ice/templates/core/routes.ts.ejs

This file was deleted.

8 changes: 8 additions & 0 deletions packages/ice/templates/core/routes.tsx.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { createRouteLoader, WrapRouteComponent, RouteErrorComponent } from '@ice/runtime';
<%- routeImports.length ? routeImports.join('\n') + '\n\n' : ''; -%>
export default ({
requestContext,
renderMode,
}) => ([
<%- routeDefination %>
]);
2 changes: 1 addition & 1 deletion packages/miniapp-runtime/src/app/connect.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { EMPTY_OBJ, hooks } from '@ice/shared';
import React, { createElement } from 'react';
import * as ReactDOM from 'react-dom';
import { ConfigProvider, DataProvider } from '@ice/runtime';
import type { MiniappAppConfig } from '../types.js';
import { Current, getPageInstance,
incrementId, injectPageInstance,
Expand All @@ -12,6 +11,7 @@ import type {
PageLifeCycle, PageProps,
ReactAppInstance, ReactPageComponent,
} from '../index.js';
import { ConfigProvider, DataProvider } from './routeContext.js';
import enableHtmlRuntime from './html/runtime.js';
import { reactMeta } from './react-meta.js';
import { ensureIsArray, HOOKS_APP_ID, isClassComponent, setDefaultDescriptor, setRouterParams } from './utils.js';
Expand Down
3 changes: 2 additions & 1 deletion packages/miniapp-runtime/src/app/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { getAppConfig, defineAppConfig, useAppData, useData, useConfig, defineDataLoader } from '@ice/runtime';
import { getAppConfig, defineAppConfig, useAppData, defineDataLoader } from '@ice/runtime';
import runClientApp from './runClientApp.js';
import Link from './Link.js';
import useSearchParams from './useSearchParams.js';
import { routerHistory as history } from './history.js';
import { useData, useConfig } from './routeContext.js';

export {
runClientApp,
Expand Down
26 changes: 26 additions & 0 deletions packages/miniapp-runtime/src/app/routeContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as React from 'react';

const DataContext = React.createContext(undefined);
DataContext.displayName = 'Data';

function useData<T = any>(): T {
const value = React.useContext(DataContext);
return value;
}
const DataProvider = DataContext.Provider;

const ConfigContext = React.createContext(undefined);
ConfigContext.displayName = 'Config';

function useConfig<T = {}>(): T {
const value = React.useContext(ConfigContext);
return value;
}
const ConfigProvider = ConfigContext.Provider;

export {
useData,
DataProvider,
useConfig,
ConfigProvider,
};
23 changes: 4 additions & 19 deletions packages/miniapp-runtime/src/app/runClientApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import type {
AppContext, RunClientAppOptions,
} from '@ice/runtime';
import { AppContextProvider, AppDataProvider, getAppData, getAppConfig, Runtime } from '@ice/runtime';
import { AppContextProvider, getAppData, getAppConfig, Runtime } from '@ice/runtime';
import { eventCenter } from '../emitter/emitter.js';
import { APP_READY } from '../constants/index.js';
import App from './App.js';
Expand Down Expand Up @@ -42,30 +42,15 @@ async function render(
runtime: Runtime,
) {
const appContext = runtime.getAppContext();
const { appData } = appContext;
const render = runtime.getRender();
const AppRuntimeProvider = runtime.composeAppProvider() || React.Fragment;

render(
document.getElementById('ice-container'),
<AppDataProvider value={appData}>
<AppContextProvider value={appContext}>
<AppRuntimeProvider>
<BrowserEntry appContext={appContext} />
<App />
</AppRuntimeProvider>
</AppDataProvider>,
);
}

interface BrowserEntryProps {
appContext: AppContext;
}

function BrowserEntry({
appContext,
}: BrowserEntryProps) {
return (
<AppContextProvider value={appContext}>
<App />
</AppContextProvider>
</AppContextProvider>,
);
}
20 changes: 19 additions & 1 deletion packages/plugin-icestark/src/runtime/framework.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import type { RuntimePlugin, AppRouterProps } from '@ice/runtime/types';
import type { RouteInfo, AppConfig } from '../types';

const { useState, useEffect } = React;

const runtime: RuntimePlugin = ({ getAppRouter, setAppRouter, appContext }) => {
const { appExport, appData } = appContext;
const OriginalRouter = getAppRouter();
const { layout, getApps, appRouter } = appExport?.icestark || {};

if (getApps) {
const FrameworkRouter = (props: AppRouterProps) => {
const [routeInfo, setRouteInfo] = useState<RouteInfo>({});
Expand Down Expand Up @@ -62,7 +64,23 @@ const runtime: RuntimePlugin = ({ getAppRouter, setAppRouter, appContext }) => {
path="/"
location={props.location}
render={() => {
return <OriginalRouter {...props} />;
const { routerContext } = props;
routerContext.routes = [
...routerContext.routes,
{
path: '*',
Component: () => (
process.env.NODE_ENV === 'development'
? <div>Add $.tsx to folder pages as a 404 component</div>
: null
),
},
];
const routerProps = {
...props,
routerContext,
};
return <OriginalRouter {...routerProps} />;
}}
/>
</AppRouter>
Expand Down
12 changes: 5 additions & 7 deletions packages/plugin-store/src/runtime.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { StoreConfig } from './types.js';

const EXPORT_CONFIG_NAME = 'storeConfig';

const runtime: RuntimePlugin = async ({ appContext, addWrapper, addProvider, useAppContext }, runtimeOptions) => {
const runtime: RuntimePlugin = async ({ appContext, addWrapper, addProvider }, runtimeOptions) => {
const { appExport, appData } = appContext;
const exported = appExport[EXPORT_CONFIG_NAME];
const storeConfig: StoreConfig = (typeof exported === 'function' ? await exported(appData) : exported) || {};
Expand All @@ -27,12 +27,10 @@ const runtime: RuntimePlugin = async ({ appContext, addWrapper, addProvider, use
addProvider(StoreProvider);

// Add page store <Provider />.
const StoreProviderWrapper: RouteWrapper = ({ children, routeId }) => {
const { routeModules } = useAppContext();
const routeModule = routeModules[routeId];
if (routeModule?.[PAGE_STORE_PROVIDER]) {
const Provider = routeModule[PAGE_STORE_PROVIDER];
const initialStates = routeModule[PAGE_STORE_INITIAL_STATES];
const StoreProviderWrapper: RouteWrapper = ({ routeExports, children }) => {
if (routeExports?.[PAGE_STORE_PROVIDER]) {
const Provider = routeExports[PAGE_STORE_PROVIDER];
const initialStates = routeExports[PAGE_STORE_INITIAL_STATES];
if (initialStates) {
return <Provider initialStates={initialStates}>{children}</Provider>;
}
Expand Down
Loading

0 comments on commit 4763bc7

Please sign in to comment.