remix-sitemap icon indicating copy to clipboard operation
remix-sitemap copied to clipboard

Any chance this can be updated to support react router 7?

Open mattoni opened this issue 1 year ago • 4 comments

Is your feature request related to a problem? Please describe. Now that remix is merging with react router 7, it seems this library no longer works. None of the dynamic sitemap functions are being called.

Describe the solution you'd like Update to work with react router 7

Additional context It looks like the context object has changed a bit, which might be causing the issue.

mattoni avatar Dec 16 '24 23:12 mattoni

Hi, I was on vacation, I'm not aware of the changes. I'll check this as soon as possible.

fedeya avatar Jan 10 '25 17:01 fedeya

Ok, looks like using react-router reveal and using the library like the getting started works as expected with a little warning saying "Error: No route matches URL" but works, at least in runtime

import { PassThrough } from 'node:stream';

import type { AppLoadContext, EntryContext } from 'react-router';
import { createReadableStreamFromReadable } from '@react-router/node';
import { ServerRouter } from 'react-router';
import { isbot } from 'isbot';
import type { RenderToPipeableStreamOptions } from 'react-dom/server';
import { renderToPipeableStream } from 'react-dom/server';
import { createSitemapGenerator } from 'remix-sitemap';

export const streamTimeout = 5_000;

export default async function handleRequest(
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  routerContext: EntryContext,
  loadContext: AppLoadContext
) {
  const { sitemap, isSitemapUrl } = createSitemapGenerator({
    siteUrl: 'https://example.com',
  });

  if (isSitemapUrl(request)) {
    return await sitemap(request, routerContext as any);
  }

  return new Promise((resolve, reject) => {
    let shellRendered = false;
    let userAgent = request.headers.get('user-agent');

    // Ensure requests from bots and SPA Mode renders wait for all content to load before responding
    // https://react.dev/reference/react-dom/server/renderToPipeableStream#waiting-for-all-content-to-load-for-crawlers-and-static-generation
    let readyOption: keyof RenderToPipeableStreamOptions =
      (userAgent && isbot(userAgent)) || routerContext.isSpaMode
        ? 'onAllReady'
        : 'onShellReady';

    const { pipe, abort } = renderToPipeableStream(
      <ServerRouter context={routerContext} url={request.url} />,
      {
        [readyOption]() {
          shellRendered = true;
          const body = new PassThrough();
          const stream = createReadableStreamFromReadable(body);

          responseHeaders.set('Content-Type', 'text/html');

          resolve(
            new Response(stream, {
              headers: responseHeaders,
              status: responseStatusCode,
            })
          );

          pipe(body);
        },
        onShellError(error: unknown) {
          reject(error);
        },
        onError(error: unknown) {
          responseStatusCode = 500;
          // Log streaming rendering errors from inside the shell.  Don't log
          // errors encountered during initial shell rendering since they'll
          // reject and get logged in handleDocumentRequest.
          if (shellRendered) {
            console.error(error);
          }
        },
      }
    );

    // Abort the rendering stream after the `streamTimeout` so it has time to
    // flush down the rejected boundaries
    setTimeout(abort, streamTimeout + 1000);
  });
}

fedeya avatar Jan 20 '25 01:01 fedeya

Maybe i need to find a better way to use the lib (without the entry.server.ts)

currently idk how to get the server build at runtime to use the experimental_sitemap fn

fedeya avatar Jan 20 '25 02:01 fedeya

Was there any progress on this? Got a project that is still on Remix using this package, but another that is RR7 and I'd love to continue using the package if it were compatible.

prblackburn avatar Mar 06 '25 13:03 prblackburn