2.2.1 • Published 3 years ago

fenris v2.2.1

Weekly downloads
3
License
MIT
Repository
github
Last release
3 years ago

Fenris

A helper library for rendering universal react+redux apps.

Uses naglfar for server/client view routing, and exports all module methods.

  • Server-side rendering
  • CSRF protection via signed expiring csrf token
  • Redux-based router (naglfar)
  • Server agnostic
  • SSR CSS-in-JS hook
  • Client and server caching of data and rendered html
  • Full control of rendered html through react-helmet
  • BelowTheFold component for SSR optimization

How to use

Install via npm i fenris.

App routes example

import {routeFragment, routeRedirect} from 'fenris'
import {getUsers, getUser} from './actions'

routeRedirect('/user', '/')

export const HomeRoute = routeFragment('/', getUsers)
export const UserRoute = routeFragment('/user/:id', getUser)
export const NotFoundRoute = routeFragment(404)

App example

import React from 'react'
import {Helmet} from "react-helmet"
import {Link} from 'fenris'
import Home from './pages/Home'
import User from './pages/User'
import NoMatch from './pages/NoMatch'
import {HomeRoute, UserRoute, NotFoundRoute} from './routes'

const App = ({ children }) => (
  <>
    <Helmet
      title="My App"
      titleTemplate="%s - My App"
      meta={[
        { 'char-set': 'utf-8' },
        { name: 'description', content: 'My super dooper dope app' },
      ]}
    />
    <nav>
      <ul>
        <li><Link to="/" prefetchData>Users</Link></li>
      </ul>
    </nav>
    <HomeRoute><Home /></HomeRoute>
    <UserRoute><User /></UserRoute>
    <NotFoundRoute><NoMatch /></NotFoundRoute>
  </>
)

export default App

Client entry example

import {renderClient} from 'fenris'
import AppComponent from './App'
import reducer from '/store'

renderClient({AppComponent, reducer})

Koa server example with CSRF

import Koa from 'koa'
import Router from 'koa-router'
import {routeRenderer, csrfCreator} from 'fenris/server'
import AppComponent from './App'
import reducer from './store'
import baseCss from './style.css'

const app = new Koa()
app.keys = ['cookie_secret']

const {create, validate} = csrfCreator('csrf_secret', 3600000)
const csrfMiddleware = (ctx, next) => {
  const sessionCookie = ctx.cookies.get('x-session', {signed:true})
  if (['GET', 'HEAD', 'OPTIONS'].includes(method.toUpperCase())) {
    const {session, csrf} = create(sessionCookie)
    ctx.cookies.set('x-session', session, {signed: true})
    // you can inject any initialState into redux via middleware
    // and doing so prevents caching the rendered body
    ctx.initialState = {csrf}
    return next()
  } else {
    if (!validate(sessionCookie, ctx.body.csrf)) ctx.throw(403, 'Invalid CSRF token')
    return next()
  }
}
app.use(csrfMiddleware)

const router = new Router()
const renderRoute = routeRenderer({
  reducer,
  AppComponent,
  baseCss,
  jsSource: 'script.js',
})
router.get('*', ctx => renderRoute(ctx).then({status, url, body}) => {
  if (url) ctx.status(status).redirect(url)
  ctx.status(status).body = body
})

app.listen(3000, _ => console.log('Server listening on port 3000'))
2.2.1

3 years ago

2.2.0

3 years ago

2.1.0

3 years ago

2.0.2

5 years ago

2.0.1

5 years ago

2.0.0

5 years ago

1.3.9

6 years ago

1.3.8

6 years ago

1.3.7

7 years ago

1.3.6

7 years ago

1.3.5

7 years ago

1.3.4

7 years ago

1.3.3

7 years ago

1.3.2

7 years ago

1.3.1

7 years ago

1.3.0

7 years ago

1.2.2

7 years ago

1.2.1

7 years ago

1.2.0

7 years ago

1.1.4

7 years ago

1.1.3

7 years ago

1.1.2

7 years ago

1.1.1

7 years ago

1.1.0

7 years ago

1.0.11

7 years ago

1.0.10

7 years ago

1.0.9

7 years ago

1.0.8

7 years ago

1.0.7

7 years ago

1.0.6

7 years ago

1.0.5

7 years ago

1.0.4

7 years ago

1.0.3

7 years ago

1.0.2

7 years ago

1.0.1

7 years ago

1.0.0

7 years ago