koajs / koa

Expressive middleware for node.js using ES2017 async functions

Home Page:https://koajs.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

how to res koa2 with react 18.0.0 renderToPipeableStream

gseok opened this issue · comments

  • react release 18.0.0 and there are support node stream api(ssr) 'renderToPipeableStream'.
  • so I'm try to using 'renderToPipeableStream' in my code But Res failed....
  • plz, help me the React(18.0.0) + Koa2.... how to stream res...
// this is my code block
import { Context, Next } from 'koa';
import Router from 'koa-router';
...

const router = new Router();

const ssrTest = async (ctx: Context) => {
  const { pipe } = ReactDomServer.renderToPipeableStream(
    <App />,
    {
      onCompleteShell() {
        ctx.respond = false;
        ctx.res.statusCode = 200;
        ctx.response.set('content-type', 'txt/html');
        ctx.type = 'html';
        pipe(ctx.res);
        ctx.res.end();
      },
    },
  );
}

router.get('/test', ssrTest);

What is the error when are trying to use the renderToPipeableStream?

  • I think my final response is stream data ( html), But Final response is my final route code (page not found)
  • stream res is not wait?
...
app.use(router.routes()); // <-- code is ok but not res this code

...

app.use(finalPageNotFound); // <-- res is this code...
  • renderToPipeableStream's onCompleteShell function is callback style.. so .. there are no await and pass the final route?
  • change code and success..
    • using promise and await
    • change callback fn onCompleteShell to onAllReady
// this is my code block
import { Context, Next } from 'koa';
import Router from 'koa-router';
...

const router = new Router();

const sendStreamRes = async (ctx: Context) => {
  const prefix = `<!DOCTYPE html><html><body><div>`;
  const postfix = `</div></body></html>`;

  return new Promise((_resolve, reject) => {
	    const { pipe } = ReactDomServer.renderToPipeableStream(
	      <App />,
	      {
	          onAllReady() {
	            ctx.respond = false;
	            ctx.res.statusCode = 200;
	            ctx.response.set('content-type', 'txt/html');
	            ctx.type = 'html';
	            ctx.res.write(prefix);
	            pipe(ctx.res);
	            ctx.res.write(postfix);
	            ctx.res.end();
	          },
	          onShellError() {
	            reject();
	          }
	      },
	    );
  });
}

const ssrTest = async (ctx: Context) => {
  await sendStreamRes(ctx);
}

router.get('/test', ssrTest);
...
commented

@gseok use onAllReady React won't streaming HTML

commented

To bypass Koa's built-in response handling, you may explicitly set ctx.respond = false;. Use this if you want to write to the raw res object instead of letting Koa handle the response for you.

Note that using this is not supported by Koa. This may break intended functionality of Koa middleware and Koa itself. Using this property is considered a hack and is only a convenience to those wishing to use traditional fn(req, res) functions and middleware within Koa.

Is there any other way without using ctx.respond? if you want streaming HTML.