Examples - Rabsztok/arboris GitHub Wiki
Example based on Razzle server.js
configuration.
import Arboris from "arboris"
import ApiClient from "axios-api-client"
import App from "./app"
import React from "react"
import { StaticRouter } from "react-router-dom"
import express from "express"
import expressStaticGzip from "express-static-gzip"
import cookieParser from "cookie-parser"
import template from "lodash/template"
import { Provider, useStaticRendering } from "mobx-react"
import { addMiddleware, getSnapshot } from "mobx-state-tree"
import Helmet from "react-helmet"
// eslint-disable-next-line
import indexFile from "!!raw-loader!./index.html"
import AppStore from "stores/app_store"
const apiUrl = process.env.API_URL
useStaticRendering(true)
const environment = process.env.NODE_ENV || "development"
const assets = require(process.env.RAZZLE_ASSETS_MANIFEST)
const renderTemplate = template(indexFile)
const server = express()
server
.disable("x-powered-by")
.use(
expressStaticGzip(process.env.RAZZLE_PUBLIC_DIR, {
indexFromEmptyFile: false
})
)
.use(cookieParser())
.get("/*", async (req, res) => {
// Initialize Arboris per request
const arboris = Arboris()
// Always pass your access and refresh token via cookies to make sure
// they are available to server without any special preparation.
const { access_token, refresh_token } = req.cookies
// You should use MST environments to pass your API client,
// if you use some kind of global, it will leak between requests!
const apiClient = new ApiClient({ access_token, refresh_token, apiUrl })
// Attach Arboris middleware to your store
const store = AppStore.create({}, { track, apiClient })
addMiddleware(store, arboris.middleware)
const context = {}
// Render is asynchronous as it waits for promises to resolve
const markup = await arboris.render(
<Provider store={store}>
<StaticRouter context={context} location={req.url}>
<App />
</StaticRouter>
</Provider>
)
const helmet = Helmet.renderStatic()
// Create a snapshot to make sure you're not double-running network
// requests for the data you could already have in store
const snapshot = getSnapshot(store)
if (context.url) {
res.redirect(context.url)
} else {
// When rendering a template, remember to set your snapshot to a global
// variable like window.INITIAL_STATE. Then pick it up on client-side
// when initializing your store.
// (example: AppStore.create(window.INITIAL_STATE))
res
.status(200)
.send(
renderTemplate({ assets, environment, markup, helmet, snapshot })
)
}
})
export default server
MST store with Arboris async tracking
import { types, flow, getEnv } from "mobx-state-tree"
import track from "arboris/lib/track"
const SessionStore = types
.model("SessionStore", {
ready: types.optional(types.boolean, false)
})
.actions(self => {
const { apiClient } = getEnv(self)
return {
// Remember to use flow() for asynchronous actions!
signIn: flow(function* signIn(email, password) {
yield apiClient.requestOauthToken(email, password)
})
}
})
export default track(SessionStore, {
signIn: track.async()
})