Elmish.Boot
- Package
- purescript-elmish
- Repository
- collegevine/purescript-elmish
#BootRecord Source
type BootRecord props = { hydrate :: String -> props -> Effect Unit, mount :: String -> props -> Effect Unit, renderToString :: props -> String }
Support for the most common case entry point - i.e. mounting an Elmish
component (i.e. ComponentDef'
structure) to an HTML DOM element with a
known ID, with support for server-side rendering.
The function boot
returns what we call BootRecord
- a record of three
functions:
mount
- takes HTML element ID and props¹, creates an instance of the component, and mounts it to the HTML element in questionhydrate
- same asmount
, but expects the HTML element to already contain pre-rendered HTML inside. See React docs for more on server-side rendering: https://reactjs.org/docs/react-dom.html#hydraterenderToString
- meant to be called on the server (e.g. by running the code under NodeJS) to perform the server-side render. Takes props¹ and returns aString
containing the resulting HTML.
The idea is that the PureScript code would export such BootRecord
for
consumption by bootstrap JavaScript code in the page and/or server-side
NodeJS code (which could be written in PureScript or not). For "plain
React" scenario, the JavaScript code in the page would just call mount
.
For "server-side rendering", the server would first call renderToString
and serve the HTML to the client, and then the client-side JavaScript code
would call hydrate
.
¹ "props" here is a parameter used to instantiate the component (see example below). It is recommended that this parameter is a JavaScript record (hence the name "props"), because it would likely need to be supplied by some bootstrap JavaScript code.
Example:
-- PureScript:
module Foo(bootRecord) where
type Props = { hello :: String, world :: Int }
component :: Props -> ComponentDef' Aff Message State
component = ...
bootRecord :: BootRecord Props
bootRecord = boot component
// Server-side JavaScript NodeJS code
const foo = require('output/Foo/index.js')
const fooHtml = foo.bootRecord.renderToString({ hello: "Hi!", world: 42 })
serveToClient("<html><body><div id='foo'>" + fooHtml + "</div></body></html>")
// Client-side HTML + JS:
<html>
<body>
<div id='foo'>
... server-side-rendered HTML goes here
</div>
</body>
<script src="foo_bundle.js" />
<script>
Foo.bootRecord.hydrate('foo', { hello: "Hi!", world: 42 })
</script>
</html>
#boot Source
boot :: forall msg state props. (props -> ComponentDef msg state) -> BootRecord props
Creates a boot record for the given component. See comments for BootRecord
.
#defaultMain Source
defaultMain :: forall msg state. { def :: ComponentDef msg state, elementId :: String } -> Effect Unit
This function supports the simplest (almost toy?) use case where there is
no server, no server-side rendering, all that exists is an HTML page that
loads the JS bundle (compiled from PureScript), and expects the bundle to
breath life into the page. For this case, declare your bundle entry point
(i.e. your main
function) as a call to defaultMain
, passing it DOM
element ID to bind to and the UI component to bind to it.
Example:
module Main
import MyComponent(def)
import Elmish.Boot as Boot
main :: Effect Unit
main = Boot.defaultMain { elementId: "app", def: def }