I'm began to use Suspense to my react app and then I turned it to SSR, but while reading the docs: https://reactjs.org/docs/react-dom-server.html#rendertopipeablestream
I do not see anywhere how to use a custom HTML, before we used to replace the div#root to the renderToString() and you could add the title of the document and meta tags, now, with that function I only see how to return the html string from <App /> with the renderToPipeableStream function:
const stream = renderToPipeableStream(
<StaticRouter location={req.url}>
<App
data={json}
pathLang={checkLanguage(lang) ? lang : ''}
statusCode={status}
cookiesAccepted={accepted}
/>
</StaticRouter>,
{
onShellReady() {
res.setHeader('Content-type', 'text/html');
stream.pipe(res);
},
}
);
Is there any way to intercept the constructed html in order to place it into my index.html?
I've just solved it by creating my own WritableStream following https://stackoverflow.com/a/70900625/6732429 this way:
// HtmlWritable.js
import {Writable} from 'stream';
class HtmlWritable extends Writable {
chunks = [];
html = '';
getHtml() {
return this.html;
}
_write(chunk, encoding, callback) {
this.chunks.push(chunk);
callback();
}
_final(callback) {
this.html = Buffer.concat(this.chunks).toString();
callback();
}
}
export default HtmlWritable;
and implementing it like this:
// server.jsx
import HtmlWritable from './HtmlWritable';
[...]
const writable = new HtmlWritable();
const stream = renderToPipeableStream(
<StaticRouter location={req.url}>
<App
data={json}
pathLang={checkLanguage(lang) ? lang : ''}
statusCode={status}
cookiesAccepted={accepted}
/>
</StaticRouter>,
{
onShellReady() {
res.setHeader('Content-type', 'text/html');
stream.pipe(writable);
},
}
);
writable.on('finish', () => {
const html = writable.getHtml();
data = data.replace('<div id="root"></div>', `<div id="root">${html}</div>`);
resolve({data, status});
});
[...]
Where data is the return fs.readFile of index.html.
That was my solution, if you solved it different, please share!
Thank a lot and feel free to comment, I would like to know your opinion!