prerender-loader
prerender-loader copied to clipboard
Question: What do you mean by "Meaningful content".
Sounds like a great way to optimize performance, but i'm very curious if this will serve actual content pre-rendered, or just some sort of placeholder skeleton?
Thanks for making this!
Good question! It's actually entirely up to you. If your app does its entire initial rendering synchronously, you'll get that as the pre-rendered HTML. In a lot of cases, it would be more common to end up with a pre-rendered "App Shell", since data loading is generally not included when doing the simplest form of prerendering.
However, this is where prerender-loader gives you control over what happens: if you point it at an async function (like in the second String Prerendering example), you get to decide what to return and how long to wait for data.
Here's an example to illustrate:
<!-- src/index.html -->
<body>
{{prerender:custom-prerender.js}}
</body>
// custom-prerender.js
import 'unfetch/polyfill';
import MyApp from './components/app';
import renderToString from 'preact-render-to-string';
export default async function prerenderWithData(params) {
let res = await fetch('https://api.example.com/items.json');
let items = await res.json();
// now we have data, so we can render something meaningful:
return renderToString(<MyApp items={items} />)
}
Note:
paramsgets populated with whatever is passed to prerender-loader's params option
Side note: hydration
In the above example, we're prerendering using "items" data, but that data isn't available when the client code boots up in our browser. We can fix that too:
export default async function prerenderWithData() {
let items = await (await fetch('https://api.example.com/items.json')).json();
let script = document.createElement('script');
script.textContent = `window.DATA = ${JSON.stringify(items)}`;
document.body.appendChild(script);
return renderToString(<MyApp items={items} />)
}
// now all we have to do is add a check in our MyApp component (or wherever "items" was being used) for window.DATA:
const MyApp = ({ items = window.DATA }) => (
<ul>{items.map( item => <li>{item}</li> )}</ul>
)