UNPKG

13.5 kBMarkdownView Raw
1<p align='center'>
2 <h1 align='center'>React, Universally</h1>
3 <p align='center'><img width='150' src='https://raw.githubusercontent.com/ctrlplusb/assets/master/logos/react-universally.png' /></p>
4 <p align='center'>A starter kit giving you the minimum requirements for a production ready universal react application.</p>
5</p>
6
7## TOC
8
9 - [About](https://github.com/ctrlplusb/react-universally#about)
10 - [Features](https://github.com/ctrlplusb/react-universally#features)
11 - [Overview](https://github.com/ctrlplusb/react-universally#overview)
12 - [Extensions and Alternatives](https://github.com/ctrlplusb/react-universally#extensions-and-alternatives)
13 - [Project Structure](https://github.com/ctrlplusb/react-universally#project-structure)
14 - [Project Dependencies](https://github.com/ctrlplusb/react-universally#project-dependencies)
15 - [Server Runtime Dependencies](https://github.com/ctrlplusb/react-universally#server-runtime-dependencies)
16 - [Deploy your very own Server Side Rendering React App in 5 easy steps](https://github.com/ctrlplusb/react-universally#deploy-your-very-own-server-side-rendering-react-app-in-5-easy-steps)
17 - [npm script commands](https://github.com/ctrlplusb/react-universally#npm-script-commands)
18 - [References](https://github.com/ctrlplusb/react-universally#references)
19
20## About
21
22This starter kit contains all the build tooling and configuration you need to kick off your next universal react project, whilst containing a minimal "project" set up allowing you to make your own architecture decisions (redux/mobx etc).
23
24## Features
25
26 - 🌍 Server side rendering.
27 - 🔥 Extreme live development - hot reloading of client/server source as well as your _webpack configuration_, with high level of error tolerance.
28 - 🚄 `express` server.
29 - 👮 Security on the `express` server using `helmet` and `hpp`.
30 - 👀 `react` as the view.
31 - 🔀 `react-router` as the router, along with a dynamic routing configuration (i.e. you get code splitting based on your routes).
32 - `react-helmet` allowing control of the page title/meta/styles/scripts from within your components. Direct control for your SEO needs.
33 - 🖌 Very basic CSS support - it's up to you to extend it into CSS Modules, SASS, PostCSS, Aphrodite etc.
34 - 🏜 Image and Font support.
35 - 🚀 Full ES2015 support, using `babel` to transpile where needed.
36 - 📦 Bundling of both client and server using `webpack` v2.
37 - ✂️ Client bundle is split by routes.
38 - 🐘 Long term caching of the client bundle. Thanks to @mjackson for the inspiration from his super cool [`web-starter`](https://github.com/mjackson/web-starter) project. Check it out!
39 - 🍃 Tree-shaking, supported by `webpack`.
40 - ✔️ Type checking via Flow, a beautiful and unobtrusive type framework. NOTE: Flow is a completely optional feature. The flow type annotations get ripped out of the source by the webpack build step. You have no obligation to use flow within your code and can even uninstall the dependency (flow-bin) without breaking the project. I do highly recommend you try it out though.
41 - 🎛 A development and optimized production configuration.
42 - 🔧 Easy environment configuration via `dotenv` files.
43 - 👼 Airbnb's eslint configuration.
44
45## Overview
46
47Redux/MobX, data persistence, test frameworks, and all the other bells and whistles have been explicitly excluded from this boilerplate. It's up to you to decide what technologies you would like to add to your own implementation based upon your own needs, this boilerplate simply serves as a clean base upon which to do so.
48
49This boilerplate uses Webpack 2 to produce bundles for both the client and the
50server code. You will notice two Webpack configuration files that allow you to target the respective environments:
51
52 - `tools/webpack/client.config.js`
53 - `tools/webpack/server.config.js`
54
55Both of these then call into the `tools/webpack/configFactory.js` in order to generate their respective webpack configurations. I've tried to keep the webpack configuration as centralized and well documented as possible as it can be a confusing topic at times.
56
57My reasoning for using webpack to bundle both the client and the server is that it allows our server code to handle React components which require support for additional file imports (e.g. CSS/Images (as and when you add the respective loaders).
58
59Given that we are bundling our server code I have included the `source-map-support` module to ensure that we get nice stack traces when executing our code via node.
60
61The application configuration is supported by the `dotenv` module and it requires you to create a `.env` file in the project root (you can use the `.env_example` as a base). The `.env` file has been explicitly ignored from git as it will typically contain environment sensitive/specific information. In the usual case your continuous deployment tool of choice should configure the specific `.env` file that is needed for a target environment.
62
63## Extensions and Alternatives
64
65### [`react-universally-skinny`](https://github.com/ctrlplusb/react-universally-skinny)
66
67When size matters. A lightweight alternative to `react-universally`. ___Provides over 60% bundle output savings from 75kb to 25kb___!
68
69### [`advanced-boilerplate`](https://github.com/sebastian-software/advanced-boilerplate)
70
71This boilerplate provides extended features on top of `react-universally` such as CSS Support with CSS modules alongside a flexible full PostCSS chain for advanced transformations e.g. autoprefixer.
72
73## Project Structure
74
75```
76/
77|- build // The target output dir for our build commands.
78| |- client // The built client module.
79| |- server // The built server module
80|
81|- src // All the source code
82| |- server // The server specific source
83| |- client // The client specific source
84| |- shared // The shared code between the client/server
85|
86|- tools
87| |- development
88| | |- server.js // Creates a hot reloading development environment
89| |
90| |- webpack
91| |- client.config.js // Client target webpack configuration
92| |- server.config.js // Server target webpack configuration
93| |- configFactory.js // Webpack configuration builder
94|
95|- .env_example // An example from which to create your own .env file.
96```
97
98## Project Dependencies
99
100The dependencies within `package.json` are structured so that the libraries required to transpile/bundle the source are contained within the `devDependencies` section, whilst the libraries required during the server runtime are contained within the `dependencies` section.
101
102If you do building on your production environment you must ensure that you have allowed the installation of the `devDependencies` too (Heroku, for example doesn't do this by default).
103
104## Server Runtime Dependencies
105
106Even though we are using webpack to support our universal application we keep the webpack runtime out of our production runtime environment. Everything is prebundled in prep for production execution. Therefore we only have the following runtime dependencies:
107
108 - `node` v6
109 - `app-root-path` - Gives us the ability to easily resolve files from the root of our app.
110 - `compression` - Gzip compression support for express server responses.
111 - `express` - Web server.
112 - `helmet` - Provides a content security policy for express.
113 - `hpp` - Express middleware to protect against HTTP Parameter Pollution attacks.
114 - `react` - A declarative, efficient, and flexible JavaScript library for building user interfaces.
115 - `react-dom` - React support for the DOM.
116 - `react-helmet` - Control the page header from your components.
117 - `react-router` - A complete routing library for React.
118 - `serialize-javascript` - Allows us to serialize our js in a format safe for embedding in webpages.
119 - `source-map-support` - Adds source map support to node.js (for stack traces).
120
121## Deploy your very own Server Side Rendering React App in 5 easy steps ##
122
123__Step 1: Clone the repository.__
124
125 git clone https://github.com/ctrlplusb/react-universally
126
127__Step 2: `cd` into the cloned directory__
128
129 cd react-universally
130
131__Step 3: Set up your env configuration file__
132
133The application depends on environment settings which are exposed to the application via a `.env` file. You will have to create one of these using the example version (`.env_example`). You could simply copy the example:
134
135 cp .env_example .env
136
137I would recommend that you review the options within the `.env` file.
138
139__Step 4: Install the awesome "now" CLI__
140
141 npm install -g now
142
143These guys are amazing hosts. [Check them out.](https://zeit.co/now#)
144
145__Step 5: Deploy to "now"__
146
147 cp .env .envnow && now && rm -r .envnow
148
149The above command will create a temporary file to expose your `.env` file to the `now` host. It will then deploy to `now` and subsequently delete the temp env file.
150
151That's it. Your clipboard will contain the address of the deployed app. Open your browser, paste, go.
152
153## npm script commands##
154
155### `npm run development`
156
157Starts a development server for both the client and server bundles. We use `react-hot-loader` v3 to power the hot reloading of the client bundle, whilst a filesystem watch is implemented to reload the server bundle when any changes have occurred.
158
159### `npm run build`
160
161Builds the client and server bundles, with the output being production optimized.
162
163### `npm run start`
164
165Executes the server. It expects you to have already built the bundles either via the `npm run build` command or manually.
166
167### `npm run clean`
168
169Deletes any build output that would have originated from the other commands.
170
171### `npm run lint`
172
173Executes `esling` (using the Airbnb config) against the src folder. Alternatively you could look to install the `eslint-loader` and integrate it into the `webpack` bundle process.
174
175### `npm run typecheck`
176
177Executes `flow-bin`, performing type checking on the source. If you really like flow I would recommend getting a plugin for your IDE. For Atom I recommend `flow-ide`.
178
179## Troubleshooting ##
180
181___Q:___ __My project fails to build and execute when I deploy it to my host__
182
183The likely issue in this case, is that your hosting provider doesn't install the `devDependencies` by default. The dependencies within `package.json` are structured so that the libraries required to transpile/bundle the source are contained within the `devDependencies` section, whilst the libraries required during the server runtime are contained within the `dependencies` section.
184You two options to fix this:
185
186 1. Prebuild your project and then deploy it along with the build output.
187 2. Change your host configuration so that it will install the `devDependencies` too. In the case of Heroku for example see [here](https://devcenter.heroku.com/articles/nodejs-support#devdependencies).
188
189___Q:___ __My server bundle fails to execute after installing a new library.__
190
191This may occur if the library you added contains a file format that depends on one of your webpack loaders to process it (e.g. `react-toolbox` contains sass/css). For these cases you need to ensure that you add the file types to the whitelist of the `externals` section in the `webpackConfigFactory`. For example:
192
193```
194// Anything listed in externals will not be included in our bundle.
195externals: removeEmpty([
196 // We don't want our node_modules to be bundled with our server package,
197 // prefering them to be resolved via native node module system. Therefore
198 // we use the `webpack-node-externals` library to help us generate an
199 // externals config that will ignore all node_modules.
200 ifServer(nodeExternals({
201 // NOTE: !!!
202 // However the node_modules may contain files that will rely on our
203 // webpack loaders in order to be used/resolved, for example CSS or
204 // SASS. For these cases please make sure that the file extensions
205 // are added to the below list. We have added the most common formats.
206 whitelist: [
207 /\.(eot|woff|woff2|ttf|otf)$/,
208 /\.(svg|png|jpg|jpeg|gif)$/,
209 /\.(mp4|mp3|ogg|swf|webp)$/,
210 /\.(css|scss|sass|sss|less)$/,
211 ],
212 })),
213]),
214```
215
216As you can see above we have already added the most common formats, so you are unlikely to hit this issue, however, it is good to be aware of.
217
218___Q:___ __I see `react-router` warnings during hot reloading.__
219
220For example:
221
222```
223Warning: [react-router] You cannot change <Router history>;
224Warning: [react-router] You cannot change <Router routes>;
225```
226
227Fret not! This is a known issue when using React Hot Loader 3 alongside React Router. It is being looked in to. Everything still works, unfortunately you just get a few warnings alongside your changes. They are harmless though, promise. :)
228
229__Q:__ __I get checksum warning errors after receiving content from a server rendered request__
230
231I have experienced some cases of this myself. The below stackoverflow post talks about a strange case where you are required to surround the server rendered content with an additional `div`. At the moment this boilerplate doesn't seem to require it, but I have extended versions of this boilerplate where all of a sudden I had to do this. It is worth knowing about.
232
233[Here is the post.](http://stackoverflow.com/questions/33521047/warning-react-attempted-to-reuse-markup-in-a-container-but-the-checksum-was-inv)
234
235## References ##
236
237 - __Webpack 2__ - https://gist.github.com/sokra/27b24881210b56bbaff7
238 - __React Hot Loader v3__ - https://github.com/gaearon/react-hot-boilerplate/pull/61
239 - __dotenv__ - https://github.com/bkeepers/dotenv