forked from seanpdoyle/select-your-own-seat
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enable server side rendering of HTML
Superglue does not support server side rendering of HTML out of the box. The functionality is available using [Humid] and is [documented]. Turbolinks + Stimulus has the upper hand here. With Superglue and React, there are some upfront costs to SSR: 1. Setup costs. SSR is run on the server side, and Browser APIs like the dom, window, or DOMParser are not available. Any Polyfill or browser specific behavior has to be moved to `componentDidMount`. This method never executes when used with ReactDOMServer. 2. Thoughtfulness. APIs differ depending on the JS runtime. Most JS packages are build with NodeJS, but its possible to use a different runtime that has a very different API. In this commit we are using [mini_racer] which only has a Least Common Denominator API across different JS runtimes. Care must be taken with package selection to ensure that they can run where they are used. Generally the strategy is to build for the `browser` and polyfill where possible. In this commit, we need to shim a `TextEncoder` and polyfill `path` using [esbuild-plugin-polyfill-node]. Long term costs: 3. It is another layer of tech that can go wrong and you have to debug. 4. Added latency. SSR with React is CPU bound, expect an additional 7ms added on production with React's production build, and 30ms during development. [mini_racer]: https://github.com/rubyjs/mini_racer [esbuild-plugin-polyfill-node]: https://github.com/cyco130/esbuild-plugin-polyfill-node
- Loading branch information
Showing
15 changed files
with
203 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import React from 'react'; | ||
import thunk from 'redux-thunk'; | ||
import { Provider } from 'react-redux'; | ||
import { createRoot } from 'react-dom/client'; | ||
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 | ||
// baseUrl={origin} | ||
// The global var SUPERGLUE_INITIAL_PAGE_STATE is set by your erb | ||
// template, e.g., index.html.erb | ||
initialPage={initialState} | ||
// The initial path of the page, e.g., /foobar | ||
// path={path} | ||
/> | ||
) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
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 | ||
}), | ||
] | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
Humid.configure do |config| | ||
# Path to your build file located in `app/assets/build/`. You should use a | ||
# separate build apart from your `application.js`. | ||
# | ||
# Required | ||
config.application_path = Rails.root.join('app', 'assets', 'builds', 'server_rendering.js') | ||
|
||
# Path to your source map file | ||
# | ||
# Optional | ||
config.source_map_path = Rails.root.join('app', 'assets', 'builds', 'server_rendering.js.map') | ||
|
||
# Raise errors if JS rendering failed. If false, the error will be | ||
# logged out to Rails log and Humid.render will return an empty string | ||
# | ||
# Defaults to true. | ||
config.raise_render_errors = Rails.env.development? || Rails.env.test? | ||
|
||
# The logger instance. | ||
# `console.log` and friends (`warn`, `error`) are delegated to | ||
# the respective logger levels on the ruby side. | ||
# | ||
# Defaults to `Logger.new(STDOUT)` | ||
config.logger = Rails.logger | ||
|
||
# Options passed to mini_racer. | ||
# | ||
# Defaults to empty `{}`. | ||
config.context_options = { | ||
timeout: 1000, | ||
ensure_gc_after_idle: 2000 | ||
} | ||
end | ||
|
||
# Common development options | ||
if Rails.env.development? || Rails.env.test? | ||
# Use single_threaded mode for Spring and other forked envs. | ||
MiniRacer::Platform.set_flags! :single_threaded | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export {TextEncoder, TextDecoder} from 'text-encoding' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters