A blazing fast zero-configuration async server-side React with GraphQL toolbelt
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
examples
.babelrc
.gitignore
.npmignore
CHANGELOG.md
CONTRIBUTING.md
ISSUE_TEMPLATE.md
LICENSE.md
README.md
ROADMAP.md
index.js
package.json
racy.js
react-client.js
react-server.js
sw.js
yarn.lock

README.md

Racy

A blazing fast zero-configuration async server-side React with GraphQL toolbelt.

Stack

Setup

  • npm init -f
  • yarn add racy

package.json

"scripts": {
  "dev": "racy dev",
  "build": "racy build",
  "serve": "racy serve",
  "export": "racy export",
  "start": "NODE_ENV=production racy build && racy serve",
  "static": "NODE_ENV=production npm run export && racy static"
}

How to

CLI

  • racy dev - Develop an App
  • racy build - Build an App for dynamically serving
  • racy serve - Dynamically serve an App
  • racy export - Export an App for statically serving
  • racy static - Statically serve an App
  • racy graphql schema - Fetch and save GraphQL schema to a file
  • racy graphql fragments - Fetch and save GraphQL fragment types to a file

How to create a simple React-App?

Just enter yarn add react and create a App.js in your project root folder.

App.js

import React, { Fragment as F } from 'react';
import Helmet from 'react-helmet';
import styled from 'styled-components';

const Headline = styled.h1`
  color: blue;
`;

export default async ({ name, version, port }) => (
  <F>
    <Helmet>
      <meta charSet="utf-8" />
      <title>React-App</title>
    </Helmet>
    <Headline>
      Racy Basic App Example {name} {version}
    </Headline>
  </F>
);

How to customize the default configuration?

Just create a config.js in your project root folder.

config.js

export default {
  // Listen on port?
  port: process.env.PORT || 8080,
  // GraphQL prefetch on server?
  shouldPrefetch: false,
  // SSR mode only?
  ssrMode: false,
};

How to map a component to a route?

App.js

import React from 'react';
import Home from './components/Home';
import About from './components/About';
import NotFound from './components/NotFound';

export default async () => [
  { path: '/', exact: true, component: Home },
  { path: '/about', exact: true, component: About },
  { component: NotFound },
];

How to use dynamic imports and code splitting?

App.js

import React from 'react';

export default async () => {
  const { default: Home } = await import('./components/Home');
  const { default: About } = await import('./components/About');

  return [
    { path: '/', exact: true, component: Home },
    { path: '/about', exact: true, component: About },
  ];
};

How to use GraphQL on the client?

App.js

import React, { Fragment as F } from 'react';
import { Query } from 'react-apollo';

import GITHUB_QUERY from './Github.gql';

export default async ({ name, version }) => {
  return (
    <F>
      <h1>
        App: {name} {version}
      </h1>
      <Query query={GITHUB_QUERY}>
        {({ data, error, loading }) => {
          if (loading) return <div>loading ...</div>;
          if (error) return <div>{error.message}</div>;
          return <pre>{JSON.stringify(data, null, 4)}</pre>;
        }}
      </Query>
    </F>
  );
};

config.js

export default {
  // Listen on port
  port: process.env.PORT || 8080,
  // GraphQL URL for GraphQL queries
  graphqlUrl: process.env.GRAPHQLURL || 'https://www.graphqlhub.com/graphql',
  // Import fragment types file to resolve union and interface types
  createFragmentTypes: async () => await import('./fragmentTypes.json'),
  // Enable prefetching on server-side
  shouldPrefetch: true,
};

How to use customize Apollo links?

config.js

import { withClientState } from 'apollo-link-state';
import resolvers from './resolvers';

export default {
  port: process.env.PORT || 8080,
  createLink: async ({ cache }) =>
    withClientState({
      cache,
      resolvers,
      defaults: {
        visible: false,
      },
    }),
};

How to extend Express with additional middleware?

Just create a express-server.js in your project root folder.

express-server.js

import morgan from 'morgan';
import cors from 'cors';
import compression from 'compression';
import examples from './examples';

export default ({ config, app }) => {
  app.use(morgan('combined'));
  app.use(cors());
  app.use(compression());

  app.use('/api/examples', examples);
};

How to create a GraphQL server?

Just create a graphql-server.js in your project root folder.

graphql-server.js

export default ({ config }) => ({
  context: ({ req }) => ({ req, config }),
  typeDefs: `type Todo {
      id: ID!
      description: String!
      done: Boolean
    }

    type Query {
      todos: [Todo]
    }`,
  resolvers: {
    Query: {
      todos: () => [{ id: 1, description: 'Demo 1', done: false }],
    },
  },
});

How to add GraphQL subscriptions on the client?

config.js

import { split } from 'apollo-link';
import { HttpLink } from 'apollo-link-http';
import { WebSocketLink } from 'apollo-link-ws';
import { getMainDefinition } from 'apollo-utilities';

export default {
  port: 8080,
  createLink,
};

function createLink({ isServer }) {
  const httpLink = new HttpLink({
    uri: `http://localhost:8080/graphql`,
  });

  const wsLink = isServer
    ? null
    : new WebSocketLink({
        uri: `ws://localhost:8080/graphql`,
        options: {
          reconnect: true,
        },
      });

  return isServer
    ? httpLink
    : split(
        ({ query }) => {
          const { kind, operation } = getMainDefinition(query);
          return kind === 'OperationDefinition' && operation === 'subscription';
        },
        wsLink,
        httpLink,
      );
}

App.js

import React, { Fragment as F } from 'react';
import { Subscription } from 'react-apollo';
import gql from 'graphql-tag';

const GRAPHQL_SUBSCRIPTION = gql`
  subscription OnChanged {
    changed {
      id
      name
    }
  }
`;

export default async () => (
  <Subscription subscription={GRAPHQL_SUBSCRIPTION}>
    {({ data }) => <pre>{JSON.stringify(data, null, 2)}</pre>}
  </Subscription>
);