React with Any Backend


June 30, 2017

When it comes to your backend server, React starter projects and tutorials tend to focus on a node backend - usually Express or something based on it.

But I get asked pretty often:

“What do I do if my backend is NOT node? How do I use React with <insert language here>?”.

You could be using Python/Flask, Ruby on Rails, Java/Spring, PHP, etc. It doesn’t really matter. If your backend is not JavaScript/node, then your frontend can't be integrated as tightly with it. This is 100% OK. In fact it’s great! You’ll never have to wonder what environment your JavaScript is running in - it all runs in the browser.

Aside 1: This isn’t really a React-specific question. It applies whenever you are using JavaScript bundling tools like Webpack, Rollup, or what-have-you.
Aside 2: This article focuses on non-node backends, but the same principals can be used for a node backend as long as your frontend and backend are separated and you don’t plan to use SSO.

Project Structure

Since your backend and frontend are using different technologies, you’ll likely want them separated. Consider a structure like this:

project
├── backend
│  ├── run-server.sh
│  └── …               # backend code & config files 
└── frontend
├── package.json
├── src
│  ├── index.js
│  └── …               # other JavaScript files 
├── webpack.config.js   # if you are using webpack 
└── …

Another good option is to keep your backend and frontend in totally separate repositories.

Either way, your frontend project should have a package.json file and some JavaScript code.

Development

First of all, if your backend has some type of “asset pipeline” or JS/CSS minification feature: IGNORE IT. You don’t need it. Features like this would be a replacement for your frontend bundler, and your frontend bundler (e.g. Webpack) will always be better.

To develop your site, you’ll want two terminal windows open.

In the first terminal window: run your frontend development server. The command is probably any of:

  • npm start
  • webpack-dev-server
  • node index.js
  • node server.js

That command should host your assets at a URL, for instance: http://localhost:8080/bundle.js.

In the second terminal window: run your backend server.

If you are already familiar with your backend then you know what command to use.

But your backend needs to reference your frontend assets somehow, so add a script tag like this:

<script src="http://localhost:8080/bundle.js" />

Once that’s working, you’ll want to turn that URL into a config variable. But we will cover that later.

You should now be able to run your backend and open up one of the pages and see your JavaScript running.

Deploy to production

Getting your frontend assets to production can be done many many different ways. I’ll just provide one way that works well and is relatively simple:

  1. build your frontend code into a production-ready, minified file or set of files (assets)
  2. upload assets to a storage service like Google Cloud Storage
  3. configure backend to use the URL of your uploaded assets

Let's go through each step in detail.

Deploy Step 1: Build Assets

Your build process will:

  • Convert ES6+ -> ES5
  • Combine multiple files
  • Minify

How exactly this process works depends on your bundler and your configuration. But either way you want to make this happen when you type npm run build.

You might already have a “npm run build” command, for instance if you are using create-react-app or my own minimal-react-starter. If so - just run it.

If you don’t have this command, add it to “scripts” in package.json. If you are using Webpack the command could be as simple as “webpack -p”. That would look like this:

"scripts"{
  "build": "webpack -p"
}

After you run your build script you should see some new .js/.css file(s) somehere. Perhaps in a public, build, or www directory.

Deploy Step 2: Upload Assets

The goal here is to get your assets to the internet somehow.

You’ll want this step to be scripted to something like “npm run upload”, but to get started you could just drag & drop your assets into the user interface for Google Cloud Storage (or a similar service).

Doesn’t really matter how you do it - just get your assets onto the internet!

I won’t go in to more details here because this process varies based on what service you use for storing your files in the cloud.

ASIDE: It is best to save your assets at a unique URL each time so you don't cause problems with your live production server! Instead, save them to a file path based on your version number or commit hash, like this: ce648cb/bundle.js.

Deploy Step 3: Modify Backend Config

Now that your frontend assets are in the cloud, you are ready to deploy your backend.

Remember when we added this script tag for development?

<script src="http://localhost:8080/bundle.js" />

You now need that URL to be configurable. Your backend should have a place for environment-based config variables. For development, you’ll want something like:

asset.url: http://localhost:8080/bundle.js

And for production, something like:

asset.url: https://storage.googleapis.com/vigilant-muse-7533/ce648cb/bundle.js`

Then you’ll change your script tag to look like:

<script src={asset.url} />

All of the above is pseudocode - how you set it up varies based on what language and template library your backend uses.

Now deploy your backend, and check it out! You should have a React frontend on your non-node backend, in production.

Conclusion

Just because you have a non-JavaScript backend doesn’t mean you have to miss out on using React and/or all the latest & greatest JavaScript bundling tools & features. I personally use a technique similar to the one above for a client that has a Java/Spring backend.

I know this process (especially the deployment piece) can be tricky, so hit me up with questions in the comments or over email! And don’t forget to subscribe…

ABOUT THE AUTHOR

Andrew H Farmer
Hey, I'm Andrew. Welcome to my blog on Modern JavaScript with React. I'm constantly searching the web to stay up-to-date on the latest frontend web tools so you don't have to. Got a question? Tweet me @ahfarmer!