diff --git a/server/src/responders/landing-handler.js b/server/src/responders/landing-handler.js index 29ad59c80..db660b322 100644 --- a/server/src/responders/landing-handler.js +++ b/server/src/responders/landing-handler.js @@ -1,164 +1,159 @@ // @flow import html from 'common-tags/lib/html'; import type { $Response, $Request } from 'express'; import fs from 'fs'; import * as React from 'react'; import ReactDOMServer from 'react-dom/server'; import { promisify } from 'util'; import { type LandingSSRProps } from '../landing/landing-ssr.react'; import { waitForStream } from '../utils/json-stream'; -import { getLandingURLFacts } from '../utils/urls'; +import { getLandingURLFacts, clientURLFromLocalURL } from '../utils/urls'; import { getMessageForException } from './utils'; async function landingHandler(req: $Request, res: $Response) { try { await landingResponder(req, res); } catch (e) { console.warn(e); if (!res.headersSent) { res.status(500).send(getMessageForException(e)); } } } const access = promisify(fs.access); const googleFontsURL = 'https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@500&family=IBM+Plex+Sans:wght@400;500&display=swap'; const iaDuoFontsURL = 'fonts/duo.css'; const localFontsURL = 'fonts/local-fonts.css'; async function getDevFontURLs(): Promise<$ReadOnlyArray> { try { await access(localFontsURL); return [localFontsURL, iaDuoFontsURL]; } catch { return [googleFontsURL, iaDuoFontsURL]; } } type AssetInfo = { +jsURL: string, +fontURLs: $ReadOnlyArray, +cssInclude: string, }; let assetInfo: ?AssetInfo = null; async function getAssetInfo() { if (assetInfo) { return assetInfo; } if (process.env.NODE_ENV === 'development') { const fontURLs = await getDevFontURLs(); assetInfo = { jsURL: 'http://localhost:8082/dev.build.js', fontURLs, cssInclude: '', }; return assetInfo; } // $FlowFixMe landing/dist doesn't always exist const { default: assets } = await import('landing/dist/assets'); assetInfo = { jsURL: `compiled/${assets.browser.js}`, fontURLs: [googleFontsURL, iaDuoFontsURL], cssInclude: html` `, }; return assetInfo; } type LandingApp = React.ComponentType; let webpackCompiledRootComponent: ?LandingApp = null; async function getWebpackCompiledRootComponentForSSR() { if (webpackCompiledRootComponent) { return webpackCompiledRootComponent; } try { // $FlowFixMe landing/dist doesn't always exist const webpackBuild = await import('landing/dist/landing.build.cjs'); webpackCompiledRootComponent = webpackBuild.default.default; return webpackCompiledRootComponent; } catch { throw new Error( 'Could not load landing.build.cjs. ' + 'Did you forget to run `yarn dev` in the landing folder?', ); } } -const { basePath, baseRoutePath } = getLandingURLFacts(); +const urlFacts = getLandingURLFacts(); +const { basePath } = urlFacts; const { renderToNodeStream } = ReactDOMServer; -const replaceURLRegex = new RegExp(`^${baseRoutePath}(.*)$`); -const replaceURLModifier = `${basePath}$1`; -function clientURLFromLocalURL(url: string): string { - return url.replace(replaceURLRegex, replaceURLModifier); -} - async function landingResponder(req: $Request, res: $Response) { const [{ jsURL, fontURLs, cssInclude }, LandingSSR] = await Promise.all([ getAssetInfo(), getWebpackCompiledRootComponentForSSR(), ]); const fontsInclude = fontURLs .map(url => ``) .join(''); // prettier-ignore res.write(html` Comm ${fontsInclude} ${cssInclude}
`); // We remove trailing slash for `react-router` const routerBasename = basePath.replace(/\/$/, ''); - const publicURL = clientURLFromLocalURL(req.url); + const publicURL = clientURLFromLocalURL(req.url, urlFacts); const reactStream = renderToNodeStream( , ); reactStream.pipe(res, { end: false }); await waitForStream(reactStream); // prettier-ignore res.end(html`
`); } export default landingHandler; diff --git a/server/src/utils/urls.js b/server/src/utils/urls.js index 0480f8216..4be25c2a7 100644 --- a/server/src/utils/urls.js +++ b/server/src/utils/urls.js @@ -1,38 +1,44 @@ // @flow import commAppURLFacts from '../../facts/commapp_url'; import landingURLFacts from '../../facts/landing_url'; import squadCalURLFacts from '../../facts/squadcal_url'; export type AppURLFacts = { +baseDomain: string, +basePath: string, +https: boolean, +baseRoutePath: string, }; function getSquadCalURLFacts(): AppURLFacts { return squadCalURLFacts; } function getCommAppURLFacts(): AppURLFacts { return commAppURLFacts; } function getAppURLFactsFromRequestURL(url: string): AppURLFacts { const commURLFacts = getCommAppURLFacts(); return url.startsWith(commURLFacts.baseRoutePath) ? commURLFacts : getSquadCalURLFacts(); } function getLandingURLFacts(): AppURLFacts { return landingURLFacts; } +function clientURLFromLocalURL(url: string, urlFacts: AppURLFacts): string { + const { basePath } = urlFacts; + return basePath + url; +} + export { getSquadCalURLFacts, getCommAppURLFacts, getLandingURLFacts, getAppURLFactsFromRequestURL, + clientURLFromLocalURL, };