react-router#StaticRouterContext TypeScript Examples
The following examples show how to use
react-router#StaticRouterContext.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: routerUtil.tsx From clearflask with Apache License 2.0 | 6 votes |
// React-Router Redirect component (within domain)
export function RedirectIso(props: { to: string, httpCode?: number }) {
return (
<Route
render={({ staticContext }) => {
if (windowIso.isSsr && staticContext) {
(staticContext as StaticRouterContext).statusCode = props.httpCode || 302;
(staticContext as StaticRouterContext).url = props.to;
}
return <Redirect to={props.to} />;
}}
/>
);
}
Example #2
Source File: windowIso.tsx From clearflask with Apache License 2.0 | 6 votes |
WindowIsoSsrProvider = (props: {
children: React.ReactElement;
fetch: any;
apiBasePath: string;
url: string;
setTitle: (title: string) => void;
setFaviconUrl: (title: string) => void;
setMaxAge: (maxAge: number) => void;
storesState: StoresState;
awaitPromises: Array<Promise<any>>;
staticRouterContext: StaticRouterContext;
parentDomain: string;
}) => {
win['fetch'] = props.fetch;
win['apiBasePath'] = props.apiBasePath;
const url = new URL(props.url);
win['location'] = url;
win['setTitle'] = props.setTitle;
win['setFaviconUrl'] = props.setFaviconUrl;
win['setMaxAge'] = props.setMaxAge;
win['storesState'] = props.storesState;
win['awaitPromises'] = props.awaitPromises;
win['staticRouterContext'] = props.staticRouterContext;
win['parentDomain'] = props.parentDomain;
return props.children;
}
Example #3
Source File: index-ssr.tsx From clearflask with Apache License 2.0 | 6 votes |
renderIndexSsr = (props: {
i18n: typeof i18n;
url: string;
staticRouterContext: StaticRouterContext;
storesState: StoresState;
awaitPromises: Array<Promise<any>>;
renderResult: RenderResult;
requestedUrl: string;
}) => renderToString(props.renderResult.muiSheets.collect(
<ChunkExtractorManager extractor={props.renderResult.extractor}>
<WindowIsoSsrProvider
fetch={fetch}
apiBasePath={connectConfig.apiBasePath}
url={props.requestedUrl}
setTitle={newTitle => props.renderResult.title = newTitle}
setFaviconUrl={newFaviconUrl => props.renderResult.faviconUrl = newFaviconUrl}
setMaxAge={maxAge => props.renderResult.maxAge = maxAge}
storesState={props.storesState}
awaitPromises={props.awaitPromises}
staticRouterContext={props.staticRouterContext}
parentDomain={connectConfig.parentDomain}
>
<Main
i18n={props.i18n}
ssrLocation={props.url}
ssrStaticRouterContext={props.staticRouterContext}
/>
</WindowIsoSsrProvider>
</ChunkExtractorManager>
))
Example #4
Source File: InitServer.tsx From foundation-lib-spa-core with Apache License 2.0 | 6 votes |
export default function RenderServerSide(config: AppConfig, serviceContainer?: IServiceContainer): SSRResponse
{
// Update context
const ctx = getGlobal();
ctx.epi = ctx.epi || {};
ctx.epi.isServerSideRendering = true;
// Initialize Episerver Context, for Server Side Rendering
serviceContainer = serviceContainer || new DefaultServiceContainer();
config.enableSpinner = false;
config.noAjax = true;
config.enableDebug = true;
EpiSpaContext.init(config, serviceContainer, true);
const staticContext : StaticRouterContext = {};
const body = ReactDOMServer.renderToString(<CmsSite context={ EpiSpaContext } staticContext={ staticContext } />);
const meta = Helmet.renderStatic();
return {
Body: body,
HtmlAttributes: meta.htmlAttributes.toString(),
Title: meta.title.toString(),
Meta: meta.meta.toString(),
Link: meta.link.toString(),
Script: meta.script.toString(),
Style: meta.style.toString(),
BodyAttributes: meta.bodyAttributes.toString()
};
}
Example #5
Source File: renderer.ts From clearflask with Apache License 2.0 | 4 votes |
export default function render(): Handler {
return async (req, res, next) => {
try {
const staticRouterContext: StaticRouterContext = {};
const storesState: StoresState = {};
const port = req.app.settings.port;
const requestedUrl = `${req.protocol}://${req.hostname}${(!port || port == 80 || port == 443) ? '' : (':' + port)}${req.path}`;
const awaitPromises: Array<Promise<any>> = [];
// From i18next-http-middleware
const i18n = req.i18n as i18n;
const lng = i18n.language;
var renderResult: RenderResult | undefined;
var isFinished = false;
var renderCounter = 0;
const renderPromise = new Promise<void>(async (resolve, reject) => {
try {
do {
if (++renderCounter > 10) {
console.warn(`Render give up after too many passes ${renderCounter} on ${requestedUrl}`);
resolve();
return;
}
// console.debug(`Rendering ${requestedUrl} pass #${renderCounter} with ${awaitPromises.length} promises`);
const renderPassResult: RenderResult = {
title: 'ClearFlask',
extractor: renderResult?.extractor || new ChunkExtractor({
statsFile: path.resolve(connectConfig.publicPath, 'loadable-stats.json'),
entrypoints: ['main'],
// SSR public path, for CSR see index.tsx
outputPath: path.resolve(__dirname, '..', '..', 'build'),
publicPath: (connectConfig.parentDomain !== 'clearflask.com')
? '/' : undefined,
}),
muiSheets: new ServerStyleSheets(),
renderedScreen: '',
};
try {
await Promise.allSettled(awaitPromises);
} catch (e) { }
awaitPromises.length = 0;
if (isFinished) return; // Request timed out
resetServerContext(); // For react-beautiful-dnd library
renderPassResult.renderedScreen = renderIndexSsr({
i18n,
url: req.url,
staticRouterContext,
storesState,
awaitPromises,
renderResult: renderPassResult,
requestedUrl: requestedUrl,
});
if (isFinished) return; // Request timed out
renderResult = renderPassResult;
} while (awaitPromises.length > 0);
console.info(`Rendered ${requestedUrl} in ${renderCounter} pass(es)`);
resolve();
} catch (e) {
reject(e);
}
});
const timeoutPromise = new Promise<void>(resolve => setTimeout(() => {
!isFinished && console.warn(`Render timeout on ${requestedUrl} after ${renderCounter} pass(es)`);
resolve();
}, 10000));
await Promise.race([timeoutPromise, renderPromise]);
isFinished = true;
if (!renderResult) {
// Timeout with no render finished, fallback to client-side rendering
res.status(500);
res.sendFile(path.join(__dirname, '..', '..', "build", "index.html"));
return;
}
var html = await indexHtmlPromise;
if (process.env.ENV !== 'production') {
html = html.replace(PH_ENV, `<script>window.ENV='${process.env.ENV}'</script>`);
} else {
html = html.replace(PH_ENV, '');
}
if (connectConfig.parentDomain !== 'clearflask.com') {
html = html.replace(PH_PARENT_DOMAIN, `<script>window.parentDomain='${connectConfig.parentDomain}'</script>`);
} else {
html = html.replace(PH_PARENT_DOMAIN, '');
}
// Favicon
html = html.replace(PH_FAVICON_URL, renderResult.faviconUrl || `${getParentDomainUrl()}/favicon.ico`);
// Page title
html = html.replace(PH_PAGE_TITLE, renderResult.title);
// JS, CSS
html = html.replace(PH_LINK_TAGS, renderResult.extractor.getLinkTags());
html = html.replace(PH_STYLE_TAGS, renderResult.extractor.getStyleTags());
html = html.replace(PH_SCRIPT_TAGS, renderResult.extractor.getScriptTags());
html = html.replace(PH_MUI_STYLE_TAGS, renderResult.muiSheets.toString());
// Add rendered html
html = html.replace(PH_MAIN_SCREEN, renderResult.renderedScreen);
// Add populated stores
if (storesState.serverAdminStore !== undefined || storesState.serverStores !== undefined) {
const storesStateSerializable: StoresStateSerializable = {
serverAdminStore: storesState.serverAdminStore?.getState(),
serverStores: {},
};
!!storesState.serverStores && Object.entries(storesState.serverStores)
.forEach(([id, store]) => storesStateSerializable.serverStores![id] = store.getState());
html = html.replace(PH_STORE_CONTENT, htmlDataCreate('__SSR_STORE_INITIAL_STATE__', storesStateSerializable));
} else {
html = html.replace(PH_STORE_CONTENT, '');
}
// I18N initial language and in-memory store
html = html.replace(PH_I18N_INIT_LNG, htmlDataCreate('__SSR_I18N_INIT_LNG__', lng));
const i18nStore: Resource = { [lng]: {} };
(lng === 'en' ? ['en'] : ['en', lng]).forEach(l => {
i18nStore[l] = {};
i18n.reportNamespaces.getUsedNamespaces().forEach(ns => {
i18nStore[l][ns] = i18n.services.resourceStore.data[l][ns];
});
});
html = html.replace(PH_I18N_INIT_STORE, htmlDataCreate('__SSR_I18N_INIT_STORE__', i18nStore));
res.writeHead(staticRouterContext.statusCode || 200, {
'Content-Type': 'text/html',
...(renderResult.maxAge !== undefined && { 'Cache-Control': 'public, max-age=' + renderResult.maxAge }),
...(staticRouterContext.url && { Location: staticRouterContext.url }),
});
res.end(html);
} catch (e) {
console.error('Failed to get page', e);
res.header('Cache-Control', 'public, max-age=10');
res.status(500);
if (process.env.ENV === 'production') {
// fallback to client-side rendering (still throwing 500)
// This is not exactly necessary for CloudFront as it is configured to get index.html on http 500
// It is necessary for custom domains bypassing CloudFront
res.sendFile(path.join(__dirname, 'public', 'index.html'));
} else {
res.end();
}
}
};
}