Skip to content

A starter kit for React in combination with Relay including a GraphQL server, server side rendering, code splitting, i18n, SEO.

License

Notifications You must be signed in to change notification settings

jkettmann/universal-react-relay-starter-kit

Repository files navigation

This starter kit aims at helping developers starting a professional app to create a basic setup quickly. It will use AWS infrastructure, but it should be simple to switch to other providers.

Content

Setup

Currently necessary for development

Only for production

CI integrations

Installation

This project uses dotenv to set environment variables from a .env file. Therefore you need to add a file named .env to the root of the project. The content should be as follows. Please fill out ... with your AWS or Facebook keys etc.

### Common environment variables ###
NODE_ENV=development
AWS_REGION=eu-central-1
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...

### Environment variables for the app server ###
PORT_APP=3000
GRAPHQL_ENDPOINT=http://localhost:8080
# name of the AWS S3 Bucket used to store uploaded images
S3_IMAGE_BUCKET=...
FACEBOOK_APP_ID=...

### Environment variables for the GraphQL server ###
PORT_GRAPHQL=8080
# Important for allowing CORS access.
# Should be a domain including protocol, like https://example.com
APP_ENDPOINT=http://localhost:3000
# Important for setting cookie from GraphQL server for the app.
# Should be a domain, like example.com
COOKIE_DOMAIN=localhost
# Select a secret for cookies to be signed with
COOKIE_SECRET=...
AWS_COGNITO_USER_POOL_ID=...
AWS_COGNITO_USER_POOL_CLIENT_ID=...
AWS_COGNITO_IDENTITY_POOL_ID=...
  • Install watchman

  • (optional) When you installed watchman you can also easily switch to yarn

  • run following commands:

    • yarn install or npm install
    • yarn run relay-compiler or npm run relay-compiler
    • yarn start or npm start
  • open localhost:3000 in your browser

Technologies

Design decisions

  • Kind of flat component structure: The relay-compiler enforces unique fragment names. This is easily achieved using a flat component structure.

    At the same time styled-components requires defining simple styled wrapper components. Component files stay very clean when defining these wrapper components in own files.

    This is why components are defined in index.js inside their own folder with smaller wrapper components next to them. Currently Relay container components have to have the same name as their fragment due to relay-compiler. See this issue.

How to create a new route

Add your new page component to client/pages/MyNewPage/MyNewPage.js. If the component does not need any data from the server, just add your component like following

const MyNewPage = () => (
  <div>
    Some content
  </div>
)

export default MyNewPage

In order to enable code splitting via react-universal-component for this page, add the file client/async/MyNewPage.js and export your page component like following:

export { default } from '../pages/MyNewPage/MyNewPage'

Now we need to add a new route to the Router. Open client/Routes.js and add following route:

<Route
  path="/myNewPage"
  render={createRender('MyNewPage')}
/>

Now you should have a new page at /myNewPage.

If the page component needs fetched data, use Relay.createFragmentContainer or another appropriate container function

const MyNewPage = ({ viewer }) => (
  <div>
    You are currently {!viewer.isLoggedIn && 'not'} logged in.
  </div>
)

MyNewPage.propTypes = {
  viewer: PropTypes.shape({
    isLoggedIn: PropTypes.bool,
  }).isRequired,
}

export default createFragmentContainer(
  MyNewPage,
  graphql`
    fragment MyNewPage_viewer on Viewer {
      isLoggedIn
    }
  `,
)

Additionally you have to define a query for the route. Open the Routes.js and add the query.

const myNewPageQuery = graphql`query Routes_MyNewPage_Query { viewer { ...MyNewPage_viewer } }`

<Route
  path="/myNewPage"
  render={createRender('MyNewPage')}
  query={myNewPageQuery}
/>

In this case the necessary viewer attributes will be fetched by found-relay and passed to your component as viewer prop.

Functional components

Functional components are easier to test and understand, see following comparison.

class Button extends React.Component {
  render() {
    return (
      <button>
        {this.props.label}
      </button>
    )
  }
}
const Button = ({ label }) => (
  <button>
    {label}
  </button>
)

It becomes a bit trickier when the component needs to have some logic, for example a click handler which passes the components id to its parent or setting the label to upper case. This is what recompose is used for.

class Button extends React.Component {
  onClick = () => {
    const { id, onClick } = this.props
    onClick(id)
  }

  render() {
    const label = label.toUpperCase()
    return (
      <button onClick={this.onClick}>
        {label}
      </button>
    )
  }
}

export default Button
import { compose, withHandlers, withProps } from 'recompose'

const Button = ({ label, onClick }) => (
  <button onClick={onClick}>
    {label}
  </button>
)

const enhance = compose(
  withHandlers({
    onClick: ({ id, onClick }) => () => onClick(id)
  }),
  withProps(({ label }) => ({ label: label.toUpperCase() })),
})

export default enhance(Button)

See recompose for more information.

Notes

  • path-to-regexp is installed with version 1.7.0 for found. If not adding it to the dependencies a warning is logged (Incorrect version of path-to-regexp imported.) and server side rendering won't work. Compare this issue.

Roadmap

  • Use real database
  • Login and registration (probably using Passport and AWS Cognito)
  • Server side security using helmet
  • Use facebook identity provider on cognito user pool instead identity pool
  • Unit and snapshot tests using Jest and end-to-end tests using cypress

Credits

Icons

User icon made by Smashicons from www.flaticon.com is licensed by CC 3.0 BY Close icon made by Cole Bemis from www.flaticon.com is licensed by CC 3.0 BY

About

A starter kit for React in combination with Relay including a GraphQL server, server side rendering, code splitting, i18n, SEO.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published