1 | # `@shopify/react-server-webpack-plugin`
|
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-webpack-plugin.svg)](https://badge.fury.io/js/%40shopify%2Freact-server-webpack-plugin.svg)
|
5 |
|
6 | A webpack plugin which generates "virtual" in-memory entrypoints for `@shopify/react-server` based applications. This plugin allows you to run a universal React application without needing any client/server-specific code.
|
7 |
|
8 | ## Installation
|
9 |
|
10 | ```bash
|
11 | $ yarn add @shopify/react-server-webpack-plugin
|
12 | ```
|
13 |
|
14 | ## Usage
|
15 |
|
16 | ### With sewing-kit
|
17 |
|
18 | As of version [0.102.0](https://github.com/Shopify/sewing-kit/blob/big-docs-update/CHANGELOG.md#L35) `sewing-kit` consumes this plugin by default if you have `@shopify/react-server` in your `package.json`.
|
19 |
|
20 | For detailed instructions on usage with Rails and sewing-kit see the documentation for [quilt_rails](/gems/quilt_rails/README.md).
|
21 |
|
22 | ### Without sewing-kit
|
23 |
|
24 | First you will need to install all of the dependencies you'll need for your application
|
25 |
|
26 | ```sh
|
27 | yarn add react react-dom
|
28 | yarn add webpack @shopify/react-server @shopify/react-server-webpack-plugin @shopify/webpack-asset-metadata-plugin --dev
|
29 | ```
|
30 |
|
31 | Since `@shopify/react-server` relies on `@shopify/webpack-asset-metadata-plugin`, you will need to setup both plugins in your webpack configuration. A simple starter (not production optimized) webpack setup is as follows:
|
32 |
|
33 | ```tsx
|
34 | // webpack.config.js
|
35 |
|
36 | const {ReactServerPlugin} = require('@shopify/react-server-webpack-plugin');
|
37 | const {AssetMetadataPlugin} = require('@shopify/webpack-asset-metadata-plugin');
|
38 |
|
39 | const universal = {
|
40 | mode: 'development',
|
41 | optimization: {
|
42 | minimize: false,
|
43 | },
|
44 | plugins: [new AssetMetadataPlugin(), new ReactServerPlugin()],
|
45 | };
|
46 |
|
47 | const server = {
|
48 | ...universal,
|
49 | name: 'server',
|
50 | target: 'node',
|
51 | entry: './server',
|
52 | externals: [
|
53 | (context, request, callback) => {
|
54 | if (/node_modules/.test(context)) {
|
55 | return callback(null, `commonjs ${request}`);
|
56 | }
|
57 | callback();
|
58 | },
|
59 | ],
|
60 | };
|
61 |
|
62 | const client = {
|
63 | ...universal,
|
64 | name: 'client',
|
65 | target: 'web',
|
66 | entry: './client',
|
67 | };
|
68 |
|
69 | module.exports = [server, client];
|
70 | ```
|
71 |
|
72 | By default, this plugin expects the entrypoint to your application to be in the root directory.
|
73 |
|
74 | ```jsx
|
75 | // index.jsx
|
76 | import React from 'react';
|
77 |
|
78 | export default function App() {
|
79 | return <div>I am an app</div>;
|
80 | }
|
81 | ```
|
82 |
|
83 | Next you can run `webpack && node dist/server.js`. When the server starts up you should see:
|
84 |
|
85 | ```sh
|
86 | started react-server on localhost:PORT
|
87 | ```
|
88 |
|
89 | If you point your browser at `localhost:PORT` you should see "I am an app". :)
|
90 |
|
91 | ### Automatic Props
|
92 |
|
93 | The plugin passes some props to your application automatically.
|
94 |
|
95 | ```typescript
|
96 | interface DefaultProps {
|
97 | /*
|
98 | The full WHATWG URL object for the initial request. On the client this will *not* update reactively. It is always the URL for the initial request.
|
99 | */
|
100 | url: URL;
|
101 |
|
102 | /*
|
103 | An object containing any data sent via the `x-quilt-data` header.
|
104 | This header is used by `quilt_rails` for sending data directly from ruby to React.
|
105 | */
|
106 | data: Record<string, any>;
|
107 | }
|
108 | ```
|
109 |
|
110 | These props are provided during both server-side and client-side rendering, so they can be used without any special logic around what environment your app is in.
|
111 |
|
112 | These props can be used to feed initial data into your application for use with libraries such as `react-router`, as well as for simple app logic.
|
113 |
|
114 | ```tsx
|
115 | // index.jsx
|
116 | import React from 'react';
|
117 |
|
118 | export default function App({url, data}: {url: Url, data: Record<string, any>}) {
|
119 | const {href} = url;
|
120 | if (href.endsWith('/about')) {
|
121 | return <div>this is an about page</div>;
|
122 | }
|
123 |
|
124 | return (
|
125 | <div>
|
126 | I am an app, here are some items:
|
127 | <ul>
|
128 | {data.items.forEach(({content, id}) => (
|
129 | <li key={id}>{content}</li>;
|
130 | ))}
|
131 | </ul>
|
132 | </div>
|
133 | );
|
134 | }
|
135 | ```
|
136 |
|
137 | ### API
|
138 |
|
139 | The plugin is exported as a named export.
|
140 |
|
141 | ```tsx
|
142 | import {ReactServerPlugin} from '@shopify/react-server-webpack-plugin';
|
143 | ```
|
144 |
|
145 | It accepts a configuration object with the following interface:
|
146 |
|
147 | ```tsx
|
148 | interface Options {
|
149 | /*
|
150 | The base-path to use for the `client.js` and `server.js` virtual entry files,
|
151 | this should also be where your index.tsx/jsx is.
|
152 |
|
153 | default: '.'
|
154 | */
|
155 |
|
156 | basePath: string;
|
157 |
|
158 | /*
|
159 | The host to use when calling `createServer` from `@shopify/react-server`,
|
160 | this should also be where your index.tsx/jsx is.
|
161 |
|
162 | default: process.env.REACT_SERVER_IP || "localhost"
|
163 | */
|
164 | host: string;
|
165 |
|
166 | /*
|
167 | The port to use when calling `createServer` from `@shopify/react-server`
|
168 |
|
169 | default: process.env.REACT_SERVER_PORT || 8081
|
170 | */
|
171 | port: number;
|
172 |
|
173 | /*
|
174 | The assetPrefix to use when calling `createServer` from `@shopify/react-server`.
|
175 |
|
176 | default: process.env.CDN_URL || "localhost:8080/assets/webpack"
|
177 | */
|
178 | assetPrefix: string;
|
179 | }
|
180 | ```
|
181 |
|
182 | An example configuration for a `sewing-kit` app named `cool-app` might look like this:
|
183 |
|
184 | ```tsx
|
185 | new ReactServerPlugin({
|
186 | assetPrefix: process.env.CDN_URL || 'https://localhost:8080/webpack/assets/';
|
187 | });
|
188 | ```
|