66

I have a React + Webpack/Babel + Node/Express application and I want to deploy it on AWS.

Would I have to deploy React and Node/Express separately? Or could they be deployed together at once?

GG.
  • 21,083
  • 14
  • 84
  • 130
Dan Me
  • 2,143
  • 4
  • 19
  • 19

3 Answers3

106

1. If you have two distinct projects

e.g. a React single-page app and a Node/Express API.

a. You can deploy both separately

Another option is to deploy both parts together at once on Elastic Beanstalk or EC2. However, you'll miss out on the benefits of hosting on S3 and CloudFront, i.e. faster delivery for your users and cheaper costs. In my opinion, it's also more convenient and less prone to unexpected errors to update and deploy separately the client-side and the server-side of a web application.

Another benefit of deploying separately: For organizations with different teams for the frontend and backend, it's easier for each team to be able to deploy their side of the application on their own without depending on the other team.

b. Why S3 + CloudFront instead of S3 alone?

  • all the benefits of using a CDN
  • your own domain name and a free SSL certificate in 1-click
  • redirection on 4xx errors (necessary if your app uses a HTML5 History-based router)
  • the caching system
  • http2 and http to https redirection

c. How to handle CORS?

You can use different subdomains, e.g.

  • api.domain.com for the Node/Express API
  • app.domain.com for the React app

Then enable CORS in the API:

app.get('/api', cors({ origin: 'https://app.domain.com' }), ...)

2. If you have a single project

e.g. a Node app including some React views.

You have to deploy the whole app on Elastic Beanstalk or EC2.

Note: If you have a single project including two sub-projects (i.e. a folder for the React app and another one for the Node API), and if both sub-projects still work when they are separated, then you can deploy the sub-projects separately (see first part of the answer).

3. In both cases

Run your Webpack build before deploying the React part. You can do it manually (before deploying on AWS) or automatically (in your CI/CD system). If you bootstrapped your app with create-react-app (CRA), just run yarn build or npm run build at the root of the project and upload the content of the "build" folder to your S3 bucket.

4. Tools

5. If not restricted to AWS

I answered a related question not restricted to AWS.

GG.
  • 21,083
  • 14
  • 84
  • 130
  • Appreciate the response! Before I accept the answer, a few questions. Couldn't React App be deployed just on S3? Just curious as to why CloudFront is suggested. Also could you elaborate on what you mean by running webpack/babel production build before deploying on S3? Lastly, NodeJS and ReactJS they do in fact have to be deployed separately? Currently they are under just one project, but in two different subfolders. – Dan Me Dec 20 '16 at 20:38
  • Sorry but what does Node app with React parts mean compared to React app + Node API? – Dan Me Dec 20 '16 at 20:39
  • Hello! I updated my answer to include some answers for your questions. – GG. Dec 20 '16 at 21:47
  • thank you for the elaboration. For running the build before deploying, do you mean building the bundle.js before deploying? Also, is there any good guides as how to deploy in a single project, with two subfolders: folder for React app and another for Node? – Dan Me Dec 21 '16 at 02:05
  • @DanMe Your welcome! **"do you mean building the bundle.js before deploying?"** Yes, sorry if wasn't clear. **"Also, is there any good guides as how to deploy"** Hmm I don't know. Depending on where you want to deploy your project, you can probably find several guides on Google with something like "how to deploy react node express app on [EC2 or BeanStalk or S3 or something else]". Hope it helps! – GG. Dec 21 '16 at 04:39
  • I tried to find it but still couldn't find any react node express app. If you can provide me with one would really help. Thank you in advance! – Dan Me Dec 21 '16 at 18:40
  • before I accept the answer/upvote, just checking in to see if you've seen my previous comment. Please let me know. – Dan Me Dec 28 '16 at 20:14
  • How would CORS be handled in this case ? How do you make API calls from the s3 served website to the nodejs app running on a different domain ? – ddewaele Feb 18 '17 at 11:32
  • 1
    @ddewaele You can use the same domain with different subdomains (`api.domain.com` for the nodejs app, `*.domain.com` for the s3 bucket) and [enable CORS](https://github.com/expressjs/cors) in the nodejs app for these subdomains: `cors({ origin: IS_DEV ? true : /^https:\/\/[^.\s]+\.domain\.com$/ })` – GG. Feb 18 '17 at 16:14
  • React application uses nodejs inside itself as for package management ans rest of the stuff. How can it be treated separately? Shouldn't it be treated as reactjs node application? I also want to deploy my application and stuck on this. – EdG Dec 04 '17 at 05:24
  • Do I need two webpack files? One for production and one for development. Currently I only have a webpack.config.js file. And just be extra clear, do you mean run webpack -w on a shell to build the bundle.js before deploying to Elastic Beanstalk? – henhen Jul 04 '18 at 04:25
  • @henhen It's recommended but not mandatory. Recommended because you want the most optimized build for your production, and the fastest build process for your development (since it should rebuild each time you change a file). So having a single config that guarantees both conditions is impossible. For the second question, you can run webpack in the shell, but it's easier to add an entry in the "scripts" of your package.json, i.e. `"scripts": { "build": "webpack" }`. It allows you to append options or other commands to your build process and keep it as simple as `npm run build`. – GG. Jul 04 '18 at 15:36
  • @GG thank you for the tip, but where exactly and when do I run the command `npm run build`? – henhen Jul 04 '18 at 20:19
  • @henhen in your shell, before deploying. – GG. Jul 04 '18 at 21:43
  • @GG okay I tried, but did not work still. I made both a script for webpack with what you suggested and also gulp {"build-gulp": "gulp build"} and then compressed all files to a zip. Then I uploaded the zipped file to "upload and deploy" but I still don't see that the js file is being downloaded and its still a blank page. – henhen Jul 04 '18 at 23:34
  • Turns out it was deployed correctly afterall, i was just not hitting the correct url. – henhen Jul 05 '18 at 04:24
  • Can you explain why you chose to use Elastic Beanstalk for the backend APIs for 1a, Instead of CodeDeploy or Lambda? – David Liao May 14 '19 at 20:56
  • @GG - I am trying the same as you answered, can you please answer my query here - https://stackoverflow.com/questions/57310937/aws-cloudfront-how-to-serve-s3-and-ec2-using-single-cloudfront?noredirect=1#comment101116926_57310937 – Sachin Vairagi Aug 02 '19 at 11:15
15

Basic Concepts

To deploy your app hassle free, you need to learn about three concepts: Microservices, containers, and process managers. I will discuss them with a bit more details and few links to get you started:

Microservices

Microservices is an architecture that allows you to divide your app into smaller services. This has multiple benefits: 1- The services are easily testable. 2- The services are replaceable. 3- The services can scale separately.

Monolith vs Microservices design

Containerization

Almost every useful app has at least dozens of dependencies. You can install dependencies on the target machines, but most certainly you'll face few challenges. Programs like Docker allow you to create a container for your app and deploy that container on the cloud. (Regardless of the cloud provider) Learn more...

Process Managers

Process managers ensure that your app is running smoothly and all parts are healthy. If your app crashes, it can easily restart the app.

1. Deploying a serverless NodeJS / React Application

Note: This approach does not work if you are doing server-rendering with ReactJS. Go to the next option.

You can simply build your app and deploy it to a static S3 website. This option works if you use microservices architecture to separate your API from your react app.

Creating a static website in S3 is really simple:

  1. Create a bucket in S3 with the exact name of the website. Example: blog.stackoverflow.com.
  2. Enable static hosting
  3. Create an A record in Route 53 and connect it to the bucket you created.

For more information check AWS handy documentation.

2. Deploying a NodeJS application into EC2

You can launch different EC2 instances for every microservice. (API, React app, etc.) You need to use a process manager such as PM2 to ensure your app is running smoothly.

Continuous Delivery (Automating deployment)

To create an automatic deployment, I prefer to use Terraform in combination with Ansible. Terraform is very declarative. You describe how the cloud infrastructure should look like and Terraform build it for you.

Ansible, on the other hand, is very procedural and is perfect for provisioning a new server.

Error handling and reporting: Sentry

Ideally, you should have unit tests to prevent shipping buggy code to the production. (Use Jest with supertest, Enzyme for shallow rendering). But the world is imperfect, and it is good to receive any potential bugs that happen on the client. Enter Sentry

bman
  • 5,016
  • 4
  • 36
  • 69
  • Really appreciate all the insights! In need of a few clarifications if you don't mind. What does it mean to server-render, and how can I check if mine does? And what is a sever less NodeJS/React app? Isn't NodeJS a server? Also, my one project has both React and NodeJS/ExpressJS, in two separate subfolders, so would like to just deploy them as a whole. – Dan Me Dec 21 '16 at 18:50
  • Just checking in to see if you've seen my previous message before I accepted the answer and up vote. – Dan Me Dec 28 '16 at 20:14
  • How to automate this deploy to EC2? There's some tool to do that? – Francis Rodrigues Nov 03 '18 at 16:06
  • @FrancisRodrigues I added a section to my answer about CD – bman Nov 05 '18 at 11:13
0

Both react and node code can be combined and deployed at once

you can more information here: How to deploy reactjs and node typescript on elastic beanstalk using eb cli