2.0.0-alpha.0 • Published 4 years ago

ssr-fatigue-react v2.0.0-alpha.0

Weekly downloads
2
License
ISC
Repository
github
Last release
4 years ago

ssr-fatigue-react

An Express middleware for server side rendering of React based web apps. It wraps:

When the ssr-fatigue-intl middleware is used, it will automatically add the messages, locale and, react-intl locale data to the output html.

For keeping things simple, the ssr-fatigue-config project contains some helper methods to build Webpack and Babel configurations in order to get things started without loosing too much sanity (no guarantees though).

Installation

$ npm i ssr-fatigue-react

Usage

src/server/index.js

import express from 'express'
import reactSSR from 'ssr-fatigue-react'

const app = express()

const assetDir = resolve(__dirname, 'path/to/webpack/output/dir')

app.use('/inc', express.static(assetDir))

app.get(
  '*',
  reactSSR({
    buildDir: assetDir,
    basePath: '', // (req, res) => res.get('X-Proxy-Base')
    publicPath: '/inc/web/', // path to assets (without basePath)
  })
)

src/client/entry-web.js

import { hot } from 'react-hot-loader/root'
import initClient from 'ssr-fatigue-react/client'

import App from '../shared/app'
import routeConfig from '../shared/routes'

// check out dynamic webpack public path
console.log('public path', __webpack_public_path__)

initClient(hot(App), routeConfig).then(() => console.log('App hydrated!'))

src/client/entry-node.js

export { default } from '../shared/app'
export routeConfig from '../shared/routes'

src/shared/routes.js

import React from 'react'
import loadable from '@loadable/component'

export default [
  {
    path: '/',
    exact: true,
    component: loadable(
      () => import(/* webpackPrefetch: true */ './pages/home'),
      {
        fallback: <div>Loading...</div>,
      }
    ),
  },
]

src/shared/app.js

import React from 'react'
import { Helmet } from 'react-helmet'

export default class App extends React.Component {
  static async getInitialProps({ getRouteProps, context }) {
    context.what = 'something to pass down to routes'

    return {
      routeProps: await getRouteProps(context),
    }
  }

  render() {
    return (
      <div className="container">
        <Helmet titleTemplate="My App - %s">
          <meta name="description" content="An example application" />
        </Helmet>
        {children}
      </div>
    )
  }
}

src/shared/pages/home.js

import React from 'react'
import { Helmet } from 'react-helmet'

export default class HomePage extends React.Component {
  static async getInitialProps(ctx) {
    const { req, what } = ctx

    return { what }
  }

  render() {
    return (
      <div className="row">
        <Helmet>
          <title>Home</title>
        </Helmet>
        <div className="col-xs-12">
          <h1>Home</h1>
          <p>{this.props.what}</p>
        </div>
      </div>
    )
  }
}

The given webpackConfig file should have two configurations for target web and node. Using the ssr-fatigue-config package:

webpack.config.js

const { resolve } = require('path')
const { buildWebpackConfig } = require('ssr-fatigue-config/webpack')

const entryDir = resolve(__dirname, 'src', 'client')
const buildDir = resolve(__dirname, 'build')

module.exports = [
  buildWebpackConfig({ target: 'node', buildDir, entryDir }),
  buildWebpackConfig({ target: 'web', buildDir, entryDir }),
]

babel.config.js

const { buildLocalBabelConfig } = require('ssr-fatigue-config/babel')

module.exports = buildLocalBabelConfig()