Skip to content

Commit

Permalink
Experimental support for disabling SSR for waku/router (#569)
Browse files Browse the repository at this point in the history
* refactor: rename files

* disable ssr for unstable_defineRouter

* unstable_disableSSR option
  • Loading branch information
dai-shi authored Mar 6, 2024
1 parent ddfc33e commit 7bc56c8
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createElement } from 'react';
import type { FunctionComponent, ReactNode } from 'react';

import { defineRouter } from './defineRouter.js';
import { unstable_defineRouter as defineRouter } from './define-router.js';
import type { RouteProps } from './common.js';
import {
joinPath,
Expand Down Expand Up @@ -52,7 +52,7 @@ type CreatePage = <
SlugKey extends string,
WildSlugKey extends string,
>(
page:
page: (
| {
render: 'static';
path: PathWithoutSlug<Path>;
Expand All @@ -75,7 +75,8 @@ type CreatePage = <
component: FunctionComponent<
RouteProps & Record<SlugKey, string> & Record<WildSlugKey, string[]>
>;
},
}
) & { unstable_disableSSR?: boolean },
) => void;

type CreateLayout = <T extends string>(layout: {
Expand All @@ -91,10 +92,14 @@ export function createPages(
}) => Promise<void>,
) {
let configured = false;

// TODO I think there's room for improvement to refactor these structures
const staticPathSet = new Set<PathSpec>();
const dynamicPathMap = new Map<string, [PathSpec, FunctionComponent<any>]>();
const wildcardPathMap = new Map<string, [PathSpec, FunctionComponent<any>]>();
const staticComponentMap = new Map<string, FunctionComponent<any>>();
const noSsrSet = new WeakSet<PathSpec>();

const registerStaticComponent = (
id: string,
component: FunctionComponent<any>,
Expand All @@ -113,6 +118,9 @@ export function createPages(
throw new Error('no longer available');
}
const pathSpec = parsePathWithSlug(page.path);
if (page.unstable_disableSSR) {
noSsrSet.add(pathSpec);
}
const numSlugs = pathSpec.filter(({ type }) => type !== 'literal').length;
const numWildcards = pathSpec.filter(
({ type }) => type === 'wildcard',
Expand Down Expand Up @@ -179,23 +187,26 @@ export function createPages(
return defineRouter(
async () => {
await ready;
const paths: { path: PathSpec; isStatic: boolean }[] = [];
const paths: { path: PathSpec; isStatic: boolean; noSsr: boolean }[] = [];
for (const pathSpec of staticPathSet) {
paths.push({ path: pathSpec, isStatic: true });
const noSsr = noSsrSet.has(pathSpec);
paths.push({ path: pathSpec, isStatic: true, noSsr });
}
for (const [pathSpec] of dynamicPathMap.values()) {
paths.push({ path: pathSpec, isStatic: false });
const noSsr = noSsrSet.has(pathSpec);
paths.push({ path: pathSpec, isStatic: false, noSsr });
}
for (const [pathSpec] of wildcardPathMap.values()) {
paths.push({ path: pathSpec, isStatic: false });
const noSsr = noSsrSet.has(pathSpec);
paths.push({ path: pathSpec, isStatic: false, noSsr });
}
return paths;
},
async (id, unstable_setShouldSkip) => {
async (id, setShouldSkip) => {
await ready;
const staticComponent = staticComponentMap.get(id);
if (staticComponent) {
unstable_setShouldSkip({});
setShouldSkip({});
return staticComponent;
}
for (const [pathSpec, Component] of dynamicPathMap.values()) {
Expand All @@ -205,12 +216,12 @@ export function createPages(
);
if (mapping) {
if (Object.keys(mapping).length === 0) {
unstable_setShouldSkip();
setShouldSkip();
return Component;
}
const WrappedComponent = (props: Record<string, unknown>) =>
createElement(Component, { ...props, ...mapping });
unstable_setShouldSkip();
setShouldSkip();
return WrappedComponent;
}
}
Expand All @@ -222,11 +233,11 @@ export function createPages(
if (mapping) {
const WrappedComponent = (props: Record<string, unknown>) =>
createElement(Component, { ...props, ...mapping });
unstable_setShouldSkip();
setShouldSkip();
return WrappedComponent;
}
}
unstable_setShouldSkip({}); // negative cache
setShouldSkip({}); // negative cache
return null; // not found
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,23 @@ import { getPathMapping } from '../lib/utils/path.js';
import type { PathSpec } from '../lib/utils/path.js';
import { ServerRouter } from './client.js';

// TODO revisit shouldSkip API
const ShoudSkipComponent = ({ shouldSkip }: { shouldSkip: ShouldSkip }) =>
createElement('meta', {
name: 'waku-should-skip',
content: JSON.stringify(shouldSkip),
});

export function defineRouter(
export function unstable_defineRouter(
getPathConfig: () => Promise<
Iterable<{ path: PathSpec; isStatic?: boolean }>
Iterable<{ path: PathSpec; isStatic?: boolean; noSsr?: boolean }>
>,
getComponent: (
componentId: string, // "**/layout" or "**/page"
unstable_setShouldSkip: (val?: ShouldSkip[string]) => void,
/**
* HACK setShouldSkip API is too hard to understand
*/
setShouldSkip: (val?: ShouldSkip[string]) => void,
) => Promise<
| FunctionComponent<RouteProps>
| FunctionComponent<RouteProps & { children: ReactNode }>
Expand All @@ -49,11 +53,14 @@ export function defineRouter(
const has404Promise = pathConfigPromise.then((pathConfig) =>
pathConfig.some(({ is404 }) => is404),
);
const existsPath = async (pathname: string) => {
const existsPath = async (
pathname: string,
): Promise<false | true | 'NO_SSR'> => {
const pathConfig = await pathConfigPromise;
return pathConfig.some(({ path: pathSpec }) =>
const found = pathConfig.find(({ path: pathSpec }) =>
getPathMapping(pathSpec, pathname),
);
return found ? (found.noSsr ? 'NO_SSR' : true) : false;
};
const shouldSkip: ShouldSkip = {};

Expand Down Expand Up @@ -144,7 +151,11 @@ globalThis.__WAKU_ROUTER_PREFETCH__ = (path) => {
};

const getSsrConfig: GetSsrConfig = async (pathname, { searchParams }) => {
if (!(await existsPath(pathname))) {
const found = await existsPath(pathname);
if (found === 'NO_SSR') {
return null;
}
if (!found) {
if (await has404Promise) {
pathname = '/404';
} else {
Expand Down
4 changes: 2 additions & 2 deletions packages/waku/src/router/server.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { defineRouter as unstable_defineRouter } from './defineRouter.js';
export { createPages } from './createPages.js';
export { unstable_defineRouter } from './define-router.js';
export { createPages } from './create-pages.js';

0 comments on commit 7bc56c8

Please sign in to comment.