To get started:
$ npm install -g react-server-cli
$ react-server init
$ react-server add-page '/' Homepage
$ react-server start
The CLI builds and runs a React Server project, using Express. It compiles JS(X) and CSS into efficiently loadable bundles with code splitting using webpack, and it supports hot reloading of React components on the client-side during development.
It's rare to see a project these days in the JavaScript world that isn't at least experimenting with ES2015 and ES7. To make this easier, all code in your project will be run through Babel, and source maps will be generated back to the original file.
To take advantage of the Babel compilation, you need to install the Babel
plugins and presets you want and reference them in a .babelrc
file in your
code directory. For more on the .babelrc
format, see its documentation
here.
This is where URLs are mapped to pages. It's also where global middleware (applied to all pages in the site) is defined.
By default this is created at the site's root directory as routes.json
.
{
"middleware": [
"middleware/FooMiddleware",
"middleware/BarMiddleware"
],
"routes": {
"BazPage": {
"path": ["/"],
"page": "pages/BazPage"
},
"BakPage": {
"path": ["/bak"],
"page": "pages/BakPage"
}
}
}
You can also provide routes as a routes.js
file. The following routes.js
file loads all middleware and pages from a pages
and middleware
folder
and registers them.
const fs = require('fs');
const path = require('path');
const routes = fs.readdirSync('./pages').reduce((acc, curr) => {
const baseName = path.basename(curr, 'js');
return {
...acc,
[`${baseName}Page`]: {
path: [`/{baseName}`],
page: `pages/${baseName}`
}
};
}, {})
module.exports = {
middleware: fs.readdirSync('./middleware'),
routes
}
In general, you should prefer a routes.json file over a routes.js file, unless you need the full expressiveness of javascript for your routes, for instance, if you're dynamically generating routes at runtime.
You can define JSON options either in a .reactserverrc
or in a
reactServer
object in your package.json
.
You can provide environment-specific values in a sub-object at the key env
.
It looks like this:
{
"routesFile": "routes.json",
"port": "5000",
"env": {
"production": {
"port": "80"
}
}
}
The values in a particular environment override the main settings. In this
example configuration port
will be set to 80 if process.env.NODE_ENV
is
production
, and 5000 otherwise.
Smart defaults are the goal, and react-server-cli
has two base modes:
development and production. react-server-cli
will determine which
base mode it's in by looking at the NODE_ENV environment variable. If it's not
"production", then react-server-cli
will assume we are in development mode.
There are three ways to pass options to the CLI, through the command line,
.reactserverrc
JSON files, or as a reactServer
entry in package.json
files. If there's no config file (or package.json config) in the current
working directory, then parent directories are searched up to the root of the
filesystem. Options passed to the CLI take final precedence.
React Server will take care of the default Webpack options but if you need to set up custom loaders for example you can do it with a user callback function.
export default (webpackConfig) => {
// Insert a new sass and css loader before the default.
webpackConfig.module.loaders.unshift({
test: /\.s(a|c)ss$/,
loaders: ["style", "css", "sass", "customloader"],
});
return webpackConfig
}
In the .reactserverrc
file add an option for webpackConfig
that points to that function file and when React Server is setting up Webpack it will call your function with the result of the built in Webpack options, allowing you to make any modifications needed. This may also be specified on the command line with the --webpack-config=<FILE>
option.
Currently the default Express Middlewares used are
If you need to setup custom express middleware you can do it with a setup function.
export default (server, reactServerMiddleware) => {
server.use(compression());
server.use(bodyParser.urlencoded({ extended: false }));
server.use(bodyParser.json());
server.use(helmet());
server.use(session(options)); // Custom express middleware being added
reactServerMiddleware(); // Must be called once or server will not start
}
In the .reactserverrc
file add an option for customMiddlewarePath
that points to that function file and when React Server is setting up the server it will call your function for setup rather then the default middlewares mentioned above. This may also be specified on the command line with the --custom-middleware-path=<FILE>
option.
Development mode is the default, and its goals are rapid startup and code-test loops. Hot mode is enabled for all code, although at this time, editing the routes file or modules that export a Page class still requires a browser reload to see changes. Modules that export a React component should reload without a browser refresh.
In development mode, code is not minified in order to speed up startup time, so please do not think that the sizes of bundles in development mode is indicative of how big they will be in production. In fact, it's really best not to do any kind of perf testing in development mode; it will just lead you astray.
We are also considering completely getting rid of server-side rendering in development mode by default to speed startup.
Production mode's priority is optimization at the expense of startup time. A separate code bundle is generated for every entry point into your app so that there is at most just one JS and one CSS file loaded by the framework. All code is minified, and hot reloading is turned off.
In many production configurations, you may not want react-server-cli
to
serve up your static JavaScript and CSS files. Typically, this is because you
have a more performant static file server already set up or because you upload
all your static files to a CDN server.
To use react-server-cli
in this sort of production setup, use react-server compile
to generate static assets.
$ NODE_ENV=production react-server compile
$ # Upload `__clientTemp/build` to static file server
$ NODE_ENV=production react-server start
In this case you'll want to specify a jsUrl
key in your production config:
{
...
"env": {
"production": {
...
"jsUrl": "http://mystaticfileserver.com/somedirectory/"
}
}
}
Generate:
routes.json
.reactserverrc
.babelrc
Install:
react-server
Add a stub of a new page class.
Start the server. If running with local client assets, build those.
Compile the client JavaScript only, and don't start any servers. This is what you want to do if you are building the client JavaScript to be hosted on a CDN or separate server. Unless you have a very specific reason, it's almost always a good idea to only do this in production mode.
The following options are available. Note that options on the command-line
are dash-separated (e.g. --js-port
), but options in config files are
camel-cased (e.g. jsPort
). (TODO: Support dash-separated options in config)
The routes file to load.
Defaults to "./routes.json".
The hostname to use when starting up the server. If jsUrl
is set, then this
argument is ignored, and any host name can be used.
Defaults to localhost.
The port to start up the main server, which will serve the pre-rendered HTML files.
Defaults to 3000.
The port to use when react-server-cli
is serving up the client JavaScript.
Defaults to 3001.
Use hot reloading of client JavaScript. Modules that export React components will reload without refreshing the browser. This option is incompatible with --long-term-caching.
Defaults to true in development mode and false in production mode.
Minify client JavaScript and CSS.
Defaults to false in development mode and true in production.
Path to the custom middleware function file. If it is not defined the default setup will be applied which include body-parser, compression and cookie-parser.
Defaults to undefined.
Path to your webpack options callback function file.
Defaults to undefined.
Adds hashes to all JavaScript and CSS file names output by the build, allowing for the static files to be served with far-future expires headers. This option is incompatible with --hot.
Defaults to false in development mode and true in production.
Tells react-server
to compile the client code during the startup procedure.
In many cases, such as in production, the code has already been compiled and
the server shouldn't take the time to compile it again.
This option is incompatible with --hot and will be ignored if hot is true
.
Defaults to true.
A URL base for the pre-compiled client JavaScript; usually this is a base URL on a CDN or separate server. Setting a value for js-url means that react-server-cli will not compile the client JavaScript at all, and it will not serve up any of the client JavaScript. Obviously, this means that --js-url overrides and ignores all of the options related to JavaScript compilation and serving: --hot, --js-port, and --minify.
Defaults to null.
If true, the server will start up using https with a self-signed certificate. Note that browsers do not trust self-signed certificates by default, so you will have to click through some warning screens. This is a quick and dirty way to test HTTPS, but it has some limitations and should never be used in production. Requires OpenSSL to be installed.
Defaults to false.
Start the server using HTTPS with this private key file in PEM format.
Requires https-cert
to be set as well.
Default is none.
Start the server using HTTPS with this cert file in PEM format. Requires
https-key
to be set as well.
Default is none.
Start the server using HTTPS with this certificate authority file in PEM
format. Also requires https-key
and https-cert
to start the server.
Default is none.
Start the server using HTTPS with this file containing the private key,
certificate and CA certs of the server in PFX or PKCS12 format. Mutually
exclusive with https-key
, https-cert
, and https-ca
.
Default is none.
A passphrase for the private key or pfx file. Requires https-key
or
https-pfx
to be set.
Default is none.
Sets the severity level for the logs being reported. Values are, in ascending order of severity: 'debug', 'info', 'notice', 'warning', 'error', 'critical', 'alert', 'emergency'.
Default is 'debug' in development mode and 'notice' in production.
Shows command line options.
You can also call react-server-cli
programmatically. The module has a
named export, run
, which takes has the following signature:
import {run} from "react-server-cli"
run({
command : "start",
routes : "./routes.json",
port : 3000,
jsPort : 3001,
hot : true,
minify : false,
jsUrl : null,
longTermCaching : true,
});
The module also exports a parseCliArgs
function that will let you implement
your own CLI:
import {run, parseCliArgs} from "react-server-cli"
run(parseCliArgs());