-
-
Notifications
You must be signed in to change notification settings - Fork 10.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Disable FOW for all ssr:false and tighten up spa mode logic #12894
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
"@react-router/dev": patch | ||
"react-router": patch | ||
--- | ||
|
||
Disable Lazy Route Discovery for all `ssr:false` apps and not just "SPA Mode" because there is no runtime server to serve the search-param-configured `__manifest` requests | ||
|
||
- We previously only disabled this for "SPA Mode" which is `ssr:false` and no `prerender` config but we realized it should apply to all `ssr:false` apps, including those prerendering multiple pages | ||
- In those `prerender` scenarios we would prerender the `/__manifest` file assuming the static file server would serve it but that makes some unneccesary assumptions about the static file server behaviors |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -557,9 +557,8 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => { | |
)}; | ||
export const basename = ${JSON.stringify(ctx.reactRouterConfig.basename)}; | ||
export const future = ${JSON.stringify(ctx.reactRouterConfig.future)}; | ||
export const isSpaMode = ${ | ||
!ctx.reactRouterConfig.ssr && ctx.reactRouterConfig.prerender == null | ||
}; | ||
export const ssr = ${ctx.reactRouterConfig.ssr}; | ||
export const isSpaMode = ${isSpaModeEnabled(ctx.reactRouterConfig)}; | ||
export const publicPath = ${JSON.stringify(ctx.publicPath)}; | ||
export const entry = { module: entryServer }; | ||
export const routes = { | ||
|
@@ -1743,7 +1742,7 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => { | |
let route = getRoute(ctx.reactRouterConfig, id); | ||
if (!route) return; | ||
|
||
if (!options?.ssr && !ctx.reactRouterConfig.ssr) { | ||
if (!options?.ssr && isSpaModeEnabled(ctx.reactRouterConfig)) { | ||
let exportNames = getExportNames(code); | ||
let serverOnlyExports = exportNames.filter((exp) => | ||
SERVER_ONLY_ROUTE_EXPORTS.includes(exp) | ||
|
@@ -2150,6 +2149,19 @@ async function getRouteMetadata( | |
return info; | ||
} | ||
|
||
function isSpaModeEnabled( | ||
reactRouterConfig: ReactRouterPluginContext["reactRouterConfig"] | ||
) { | ||
return ( | ||
reactRouterConfig.ssr === false && | ||
(reactRouterConfig.prerender == null || | ||
reactRouterConfig.prerender === false || | ||
(Array.isArray(reactRouterConfig.prerender) && | ||
reactRouterConfig.prerender.length === 1 && | ||
reactRouterConfig.prerender[0] === "/")) | ||
); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the proper detection, the old buggy one was simply:
|
||
|
||
async function getPrerenderBuildAndHandler( | ||
viteConfig: Vite.ResolvedConfig, | ||
serverBuildDirectory: string, | ||
|
@@ -2284,13 +2296,6 @@ async function handlePrerender( | |
); | ||
} | ||
} | ||
|
||
await prerenderManifest( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Never need to prerender a manifest anymore
|
||
build, | ||
clientBuildDirectory, | ||
reactRouterConfig, | ||
viteConfig | ||
); | ||
} | ||
|
||
function determineStaticPrerenderRoutes( | ||
|
@@ -2418,24 +2423,6 @@ async function prerenderResourceRoute( | |
viteConfig.logger.info(`Prerender: Generated ${colors.bold(outfile)}`); | ||
} | ||
|
||
async function prerenderManifest( | ||
build: ServerBuild, | ||
clientBuildDirectory: string, | ||
reactRouterConfig: ResolvedReactRouterConfig, | ||
viteConfig: Vite.ResolvedConfig | ||
) { | ||
let normalizedPath = `${reactRouterConfig.basename}/__manifest`.replace( | ||
/\/\/+/g, | ||
"/" | ||
); | ||
let outdir = path.relative(process.cwd(), clientBuildDirectory); | ||
let outfile = path.join(outdir, ...normalizedPath.split("/")); | ||
await fse.ensureDir(path.dirname(outfile)); | ||
let manifestData = JSON.stringify(build.assets.routes); | ||
await fse.outputFile(outfile, manifestData); | ||
viteConfig.logger.info(`Prerender: Generated ${colors.bold(outfile)}`); | ||
} | ||
|
||
function validatePrerenderedResponse( | ||
response: Response, | ||
html: string, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,8 +26,8 @@ const discoveredPaths = new Set<string>(); | |
// https://stackoverflow.com/a/417184 | ||
const URL_LIMIT = 7680; | ||
|
||
export function isFogOfWarEnabled(isSpaMode: boolean) { | ||
return !isSpaMode; | ||
export function isFogOfWarEnabled(ssr: boolean) { | ||
return ssr === true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only enable fog of war for |
||
} | ||
|
||
export function getPartialManifest( | ||
|
@@ -70,10 +70,11 @@ export function getPartialManifest( | |
export function getPatchRoutesOnNavigationFunction( | ||
manifest: AssetsManifest, | ||
routeModules: RouteModules, | ||
ssr: boolean, | ||
isSpaMode: boolean, | ||
basename: string | undefined | ||
): PatchRoutesOnNavigationFunction | undefined { | ||
if (!isFogOfWarEnabled(isSpaMode)) { | ||
if (!isFogOfWarEnabled(ssr)) { | ||
return undefined; | ||
} | ||
|
||
|
@@ -96,14 +97,12 @@ export function useFogOFWarDiscovery( | |
router: DataRouter, | ||
manifest: AssetsManifest, | ||
routeModules: RouteModules, | ||
ssr: boolean, | ||
isSpaMode: boolean | ||
) { | ||
React.useEffect(() => { | ||
// Don't prefetch if not enabled or if the user has `saveData` enabled | ||
if ( | ||
!isFogOfWarEnabled(isSpaMode) || | ||
navigator.connection?.saveData === true | ||
) { | ||
if (!isFogOfWarEnabled(ssr) || navigator.connection?.saveData === true) { | ||
return; | ||
} | ||
|
||
|
@@ -176,7 +175,7 @@ export function useFogOFWarDiscovery( | |
}); | ||
|
||
return () => observer.disconnect(); | ||
}, [isSpaMode, manifest, routeModules, router]); | ||
}, [ssr, isSpaMode, manifest, routeModules, router]); | ||
} | ||
|
||
export async function fetchAndApplyManifestPatches( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only reject server-only exports in true SPA mode