Using create-react-app with React Router, Express.js and Docker

Datetime:2016-08-23 00:09:49          Topic: React           Share

I’m writing this guide because I haven’t found implementations of this setup using the new and cool (and official) create-react-app by Facebook.

This is not about server-side rendering or Redux.

The source code is available here: https://github.com/mrpatiwi/routed-react

Why this is important?

Suppose you want to start a new project with React.js and because you are a good software developer, you want to use npm , babel and webpack .

Where to start?

Before create-react-app you had to search and try a infinite amount of boilerplates and example repositories to finally had a mediocre setup after two days of wasted time.

Now it’s easier :)

Getting started

I assume you already have Node.js and npm installed. So we begin with the cli :

npm install -g create-react-app

And let’s create an app named routed-react:

create-react-app routed-react
cd routed-react

To start or application at http://localhost:3000/ we run:

npm start

Refactor project structure

Considering that the project eventually will grow. Let’s make some changes to the directory structure.

I find a good practice to have reusable components with modificable styles.

Always consider adding style and className props. I recommend using classnames library to do so:

npm install --save classnames

Create a components directory:

# Create 'components' directory and 'App' sub-directory
mkdir -p src/components/App
# Move App component to new directory
mv src/App.js src/components/App/index.js
mv src/App.css src/components/App/style.css
mv src/logo.svg src/components/App/logo.svg

And modify the App component:

Now start an About component that will be shown at /about

mkdir src/components/About
touch src/components/About/index.js
touch src/components/About/style.css

A sample About component:

Reusability FTW!

Finally a NotFound component for all those 404's:

mkdir src/components/NotFound
touch src/components/NotFound/index.js
touch src/components/NotFound/style.css

At this moment the app should be crashing, don’t worry about that. We are fixing it right now.

Router setup

Let’s begin with react-router . We also want to use browserHistory strategy. The official docs will explain what it does better than me:

Browser history is the recommended history for browser application with React Router. It uses the History API built into the browser to manipulate the URL, creating real URLs that look like example.com/some/path.

Just install it:

npm install --save react-router

Now we must define our routes:

And the main index.js now looks like:

So much better :)

If we visit http://localhost:3000/about we should see (any other route will show our 404 view):

Usage with Express.js

So we need to serve our app. Github pages or similar will probably won’t work as expected unless you host the app on the root domain. Even if you do that, will only navigate as expected if the first visited page if the root.

Our option is to use a own hosting and always serve the main index.html for every possible route (that doesn’t override the access to the other static files as .js.css and  .favicon ).

# Install dependencies
npm install --save express morgan helmet
# Create server files
mkdir server
touch server/app.js
touch server/index.js

To see if everything is working well, build the app and start the server:

# Build to 'build' directory (it's ignored by git, see .gitignore)
npm run build
# Start the express.js app
node server

Visit http://localhost:9000/about and everything should be working fine.

Testing

Do you want testing? Ok testing, but focused in unit-testing the serving of assets of our Express.js app.

  • Mocha
  • Chai
  • Supertest
# Install dependencies
npm install --save-dev mocha chai supertest mz
# Create test directory
mkdir test
touch test/server.test.js

mz is a library to modernize some Node.js native functions.

We love promises, right?

Remember to modify the scripts from package.json :

"scripts": {
"start": "react-scripts start",
"start:server": "node server",
"build": "react-scripts build",
"eject": "react-scripts eject",
"test": "mocha test"
},

Basically we expect that:

  • The React.js app builds successfully
  • The Express.js server send us the index.html file for any route
  • The Express.js server send us the assets requested by the browser.

Run the test suite with npm test :coffee:️

$ npm test
> [email protected]

test /Users/patriciolopez/Repositories/routed-react

> mocha test

builds application
✓ builds to "build" directory (9017ms)
express serving
✓ responds to / with the index.html (38ms)
✓ responds to favicon.icon request
✓ responds to any route with the index.html
4 passing (9s)

You can see that building the React.js app takes a lot of time, but this is a expected behavior because behind the scenes some unused code is removed and the rest if transpiled , optimized , uglificated and bundled in a few lightweight files.

Docker

Finally, let’s use the best deployment tool ever :whale:

touch Dockerfile

Write the following (it’s based on the officials Node.js docs ):

Notice that we build our app inside the Docker image build step. Finally, when the container is started it should execute npm run start:server and start the Express.js app at port 9000 .





About List