1 | # `@shopify/react-server`
|
2 |
|
3 | [![Build Status](https://travis-ci.org/Shopify/quilt.svg?branch=master)](https://travis-ci.org/Shopify/quilt)
|
4 | [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE.md) [![npm version](https://badge.fury.io/js/%40shopify%2Freact-server.svg)](https://badge.fury.io/js/%40shopify%2Freact-server.svg)
|
5 |
|
6 | A simple library for React server-side rendering using [`@shopify/react-html`](https://github.com/Shopify/quilt/tree/master/packages/react-html).
|
7 |
|
8 | ## Table of contents
|
9 |
|
10 | 1. [Installation](#installation)
|
11 | 1. [Node usage](#node-usage)
|
12 | 1. [Rails usage](#rails-usage)
|
13 | 1. [Deployment](#deployment)
|
14 | 1. [Webpack plugin](#webpack-plugin)
|
15 | 1. [API](#api)
|
16 |
|
17 | ## Installation
|
18 |
|
19 | ```bash
|
20 | $ yarn add @shopify/react-server
|
21 | ```
|
22 |
|
23 | ## Rails Usage
|
24 |
|
25 | We provide a [gem](https://github.com/Shopify/quilt/blob/master/gems/quilt_rails/README.md#L2) to automagically setup a proxy controller for react-server.
|
26 |
|
27 | ## Node Usage
|
28 |
|
29 | Node apps require a server entry point that calls the `createServer` function. At the minimum, this function requires a `render` function that renders the main `<App />` component.
|
30 |
|
31 | ```tsx
|
32 | import React from 'react';
|
33 | import {createServer} from '@shopify/react-server';
|
34 | import App from '../app';
|
35 |
|
36 | const app = createServer({
|
37 | render: ctx => <App location={ctx.request.url} />,
|
38 | });
|
39 | ```
|
40 |
|
41 | If you already have an existing node server, you can opt in to using only the render middleware provided by this package. See `createRender()`.
|
42 |
|
43 | ## Webpack Plugin
|
44 |
|
45 | We also provide a [webpack plugin](https://github.com/Shopify/quilt/blob/master/packages/react-server-webpack-plugin) to automatically generate the server and client entries for an application.
|
46 |
|
47 | ### Deployment (Shopify specific)
|
48 |
|
49 | For Shopifolk, we have a [walkthrough](https://docs.shopifycloud.com/getting_started/rails-with-node-walkthrough) for getting an app ready to deploy.
|
50 |
|
51 | ## API
|
52 |
|
53 | ### `createServer()`
|
54 |
|
55 | Creates a full `Koa` server which renders an `@shopify/react-html` application.
|
56 |
|
57 | ```tsx
|
58 | import {createServer} from '@shopify/react-server';
|
59 | ```
|
60 |
|
61 | The `createServer` function takes an `Options` object of the following interface.
|
62 |
|
63 | ```tsx
|
64 | interface Options {
|
65 | // the port to bind
|
66 | port?: number;
|
67 | // the ip to run the application on
|
68 | ip?: string;
|
69 | // the full base url for the cdn if applicable
|
70 | assetPrefix?: string;
|
71 | // the name of the asset on the cdn
|
72 | assetName?: string;
|
73 | // any additional Koa middleware to mount on the server
|
74 | serverMiddleware?: compose.Middleware<Context>[];
|
75 | // a function of `(ctx: Context, data: {locale: string}): React.ReactElement<any>`
|
76 | render: RenderFunction;
|
77 | // whether to run in debug mode
|
78 | debug?: boolean;
|
79 | }
|
80 | ```
|
81 |
|
82 | It returns a running [Koa](https://github.com/koajs/koa/) server.
|
83 |
|
84 | ### `createRender()`
|
85 |
|
86 | Creates a Koa middleware which renders an `@shopify/react-html` application.
|
87 |
|
88 | ```tsx
|
89 | import {createRender} from '@shopify/react-server';
|
90 | ```
|
91 |
|
92 | The `createRender` function takes two arguments. The first is a render function that should return the main component at the top of the application tree in JSX. This function receives the full [Koa](https://github.com/koajs/koa/) server context which can be used to derive any necessary props to feed into the main component.
|
93 |
|
94 | The second argument is a subset of [`@shopify/react-effect#extract`](../react-effect/README.md#extract)'s options which are simply delegated to the `extract` call within the `createRender` middleware.
|
95 |
|
96 | #### Options
|
97 |
|
98 | - `afterEachPass?(pass: Pass): any` see [`@shopify/react-effect#extract`](../react-effect/README.md#extract)
|
99 |
|
100 | - `betweenEachPass?(pass: Pass): any` see [`@shopify/react-effect#extract`](../react-effect/README.md#extract)
|
101 |
|
102 | It returns a [Koa](https://github.com/koajs/koa/) middleware.
|
103 |
|
104 | ### `createDefaultProvider()`
|
105 |
|
106 | This function return a set of providers based on a given set of options, defined below.
|
107 |
|
108 | ```ts
|
109 | interface Options {
|
110 | // determines whether to render a `CsrfUniversalProvider`, default is true.
|
111 | csrf: boolean;
|
112 | }
|
113 | ```
|
114 |
|
115 | _Example_
|
116 |
|
117 | ```tsx
|
118 | import React from 'react';
|
119 | import {createDefaultProvider} from '@shopify/react-server`;
|
120 |
|
121 | const MyDefaultProvider = createDefaultProvider({csrf: false});
|
122 |
|
123 | function App() {
|
124 | return (
|
125 | <MyDefaultProvider>
|
126 | {/* rest of app */}
|
127 | </MyDefaultProvider>
|
128 | )
|
129 | }
|
130 | ```
|
131 |
|
132 | ### `<DefaultProvider />`
|
133 |
|
134 | A single component that renders all of the providers and context required within a typical React application, including a [CookieUniversalProvider](../packages/react-cookie/README.md#client) and a [CrsfUniversalProvider](../packages/react-csrf-universal-provider/README.md).
|
135 |
|
136 | _Basic Cookie Example_
|
137 |
|
138 | ```tsx
|
139 | // app/ui/server.tsx
|
140 |
|
141 | import React from 'react';
|
142 | import {createServer} from '@shopify/react-server';
|
143 | import App from './App.tsx';
|
144 |
|
145 | const app = createServer({
|
146 | render(ctx) {
|
147 | return (
|
148 | <DefaultProviders>
|
149 | <App location={ctx.request.url} />
|
150 | </DefaultProviders>
|
151 | );
|
152 | },
|
153 | });
|
154 |
|
155 | export default app;
|
156 | ```
|
157 |
|
158 | ```tsx
|
159 | // app/ui/App.tsx
|
160 |
|
161 | import React from 'react';
|
162 | import {useCookie} from '@shopify/react-cookie';
|
163 |
|
164 | export default function App() {
|
165 | // this works
|
166 | const [someCookie] = useCookie('SomeCookieKey');
|
167 |
|
168 | return (
|
169 | <>
|
170 | The cookie is {someCookie}
|
171 | {/* rest of app */}
|
172 | </>
|
173 | );
|
174 | }
|
175 | ```
|