Skip to content

Commit

Permalink
Hook for custom middleware (#708)
Browse files Browse the repository at this point in the history
* Provide hook for custom middleware setup

* change documentation a little

* More documentation...

* Small edits to describe

* Fix up documentation after pr feedback
  • Loading branch information
sresant authored and doug-wade committed Nov 17, 2016
1 parent 8778d0e commit c431cfc
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 6 deletions.
18 changes: 18 additions & 0 deletions docs/guides/react-server-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,22 @@ export default (webpackConfig) => {

In the `.reactserverrc` file add an option for `webpack-config` 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.

### Use Custom Express Middleware
Currently the default Express Middlewares used are compression, body-parser, cookie-parser. If you need to setup custom express middleware you can do it with a setup function.

```javascript
export default (server, reactServerMiddleware) => {
server.use(compression());
server.use(bodyParser.urlencoded({ extended: false }));
server.use(bodyParser.json());
server.use(session(options));
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: making a great DX

Development mode is the default, and its goals are rapid startup and code-test
Expand Down Expand Up @@ -237,6 +250,11 @@ Minify client JavaScript and CSS.

Defaults to **false** in development mode and **true** in production.

#### --custom-middleware-path
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**.

#### --long-term-caching
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
Expand Down
36 changes: 30 additions & 6 deletions packages/react-server-cli/src/commands/start.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import http from "http"
import https from "https"
import path from "path"
import express from "express"
import compression from "compression"
import bodyParser from "body-parser"
Expand Down Expand Up @@ -28,6 +29,7 @@ export default function start(options){
jsUrl,
httpsOptions,
longTermCaching,
customMiddlewarePath,
} = options;

const {serverRoutes, compiler} = compileClient(options);
Expand All @@ -46,7 +48,7 @@ export default function start(options){
logger.notice("Starting servers...")

const jsServer = startJsServer(compiler, jsPort, host, longTermCaching, httpsOptions);
const htmlServerPromise = serverRoutes.then(serverRoutesFile => startHtmlServer(serverRoutesFile, port, host, httpsOptions));
const htmlServerPromise = serverRoutes.then(serverRoutesFile => startHtmlServer(serverRoutesFile, port, host, httpsOptions, customMiddlewarePath));

return {
stop: () => Promise.all([jsServer.stop(), htmlServerPromise.then(server => server.stop())]),
Expand All @@ -59,21 +61,43 @@ export default function start(options){
return startServers();
}


// given the server routes file and a port, start a react-server HTML server at
// http://host:port/. returns an object with two properties, started and stop;
// see the default function doc for explanation.
const startHtmlServer = (serverRoutes, port, host, httpsOptions) => {
const startHtmlServer = (serverRoutes, port, host, httpsOptions, customMiddlewarePath) => {
const server = express();
const httpServer = httpsOptions ? https.createServer(httpsOptions, server) : http.createServer(server);
let middlewareSetup = (server, rsMiddleware) => {
server.use(compression());
server.use(bodyParser.urlencoded({ extended: false }));
server.use(bodyParser.json());
rsMiddleware();
}

return {
stop: serverToStopPromise(httpServer),
started: new Promise((resolve, reject) => {
logger.info("Starting HTML server...");

server.use(compression());
server.use(bodyParser.urlencoded({ extended: false }))
server.use(bodyParser.json())
reactServer.middleware(server, require(serverRoutes));
let rsMiddlewareCalled = false;
const rsMiddleware = () => {
rsMiddlewareCalled = true;
reactServer.middleware(server, require(serverRoutes));
}

if (customMiddlewarePath) {
const customMiddlewareDirAb = path.resolve(process.cwd(), customMiddlewarePath);
middlewareSetup = require(customMiddlewareDirAb).default;
}

middlewareSetup(server, rsMiddleware);

if (!rsMiddlewareCalled) {
console.error("Error react-server middleware was never setup in custom middleware function");
reject("Custom middleware did not setup react-server middleware");
return;
}

httpServer.on('error', (e) => {
console.error("Error starting up HTML server");
Expand Down
5 changes: 5 additions & 0 deletions packages/react-server-cli/src/parseCliArgs.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ export default (args = process.argv) => {
default: undefined,
type: "boolean",
})
.option("custom-middleware-path", {
describe: "Path to custom middleware function file. If it is not defined default setup will be applied.",
default: undefined,
type: "string",
})
.option("long-term-caching", {
describe: "Use long-term cache headers for the static JS & CSS files. Default is true in production mode, false otherwise.",
default: undefined,
Expand Down

0 comments on commit c431cfc

Please sign in to comment.