Server-Side Rendering¶
Superglue does not include server-side rendering out of the box, but you can easily add it with humid.
Follow the instructions.
Then, if you're using esbuild, create a app/javascript/packs/server_rendering.js
:
import React from 'react';
import { ApplicationBase } from '@thoughtbot/superglue';
import { pageIdentifierToPageComponent } from './page_to_page_mapping';
import { buildStore } from './store'
import { renderToString } from 'react-dom/server';
require("source-map-support").install({
retrieveSourceMap: filename => {
return {
url: filename,
map: readSourceMap(filename)
};
}
});
class Application extends ApplicationBase {
mapping() {
return pageIdentifierToPageComponent;
}
visitAndRemote(navRef, store) {
return {visit: () => {}, remote: () => {}}
}
buildStore(initialState, { superglue, pages}) {
return buildStore(initialState, superglue, pages);
}
}
setHumidRenderer((json) => {
const initialState = JSON.parse(json)
return renderToString(
<Application initialPage={initialState}/>
)
})
Next
and add a esbuild build file.
import * as esbuild from 'esbuild'
import { polyfillNode } from "esbuild-plugin-polyfill-node";
await esbuild.build({
entryPoints: ['app/javascript/server_rendering.js'],
bundle: true,
platform: "browser",
define: {
"process.env.NODE_ENV": '"production"'
},
sourcemap: true,
outfile: 'app/assets/builds/server_rendering.js',
logLevel: "info",
loader: {
".js": "jsx",
".svg": "dataurl"
},
inject: ["./shim.js"],
plugins: [
polyfillNode({
globals: false
}),
]
})
Add a shim.js
for the above. We'll need this for the v8 environment that mini-racer runs on.
Add a line to your package.json
like so:
Use Humid.render
in all your ERB templates index.html.erb
:
!> Do not render spacing above. If you do, React will not hydrate properly and
warn Hydration failed because the initial UI does not match what was rendered on the server
Change your application.js
to use hydrateRoot
:
and change the rest of application.js
accordingly.