DEV Community

Cover image for Why you should use a proxy server with Create React App
Matt Angelosanto for LogRocket

Posted on • Originally published at blog.logrocket.com

Why you should use a proxy server with Create React App

Written by Joel Adewole✏️

Introduction

There are many cases in which developers need to consume APIs from the backend while using Create React App (CRA) to build an application. Because most client apps are hosted on different servers than the backend application, there are complications that arise as a result of requests being sent across both servers. CRA supports proxying to mitigate or entirely eliminate these issues.

In this article, we will discuss what a proxy server is, why you should use a proxy server in development, and uses cases for proxying requests in a React application. Then, we will implement a real life example of setting up a proxy server in React.

Contents

What is a proxy server?

A proxy server is a system or application that acts as a conduit between a client application and the server when it requests resources.

Diagram of a proxy server

The diagram above illustrates how proxy servers work. When you make a request to a server, it is routed through the proxy, which receives the response from the server and transmits the information back to the client.

Why you should use a proxy server in development

You might be asking why it's necessary to route some requests through a proxy before sending them to the server. The following scenarios need the use of a proxy server:

Need to protect your client from cross-site attacks? Proxy servers add an extra degree of protection by allowing server responses to be validated before being delivered to the client. They can be used as web filters and firewalls.

To avoid crashes, bandwidth must be conserved and server traffic must be regulated. Proxy servers can cache requests and server responses so that not all queries are transmitted to the server at the same time. This is typically done when dealing with static information and huge files.

Proxy servers are useful when client data must be protected or a request must be made anonymously. Proxy servers do not provide information to the server, such as the client's location or IP address. Because the requests are not sent on a known network, this helps clients keep their data private by preventing hackers from intercepting important information.

Additionally, proxy servers can specify which requests are allowed and which are not. And finally, proxy servers can be used to log requests and the clients that make them within organizations that require it.

Use cases for proxying requests in a React application

After understanding why proxy servers are required, it is critical to understand real-life scenarios in which proxy servers can be implemented. Some examples of proxying requests in React applications are listed below.

First is requesting HTTPS APIs in development (https://localhost). Browsers have cross-origin limitations that block HTTPS API requests from HTTP sites running on localhost. Proxy servers can assist in redirecting requests to APIs without having to go via the browser's default request options, which helps to evade several cross-origin limitations.

Second is fetching data from cross-origin APIs that don't support CORs in web browsers. Certain APIs, regardless of the Hypertext Transfer Protocol, don't support CORs for security concerns, and browsers impose same-origin policy to protect users from cross-site scripting (XSS). Proxy servers can be used to make API calls and then transmit the results to the web browser.

Finally, there is obtaining media resources from the server. A proxy server can be used to cache media files from the server, eliminating the need to send requests for such files to the server every time they are needed.

How to set up a proxy server in React

There are two common approaches of setting up proxy servers in React applications developed using CRA. We have the default CRA proxy option as well as the npm package http-proxy-middleware.

Please note that these methods are only effective in the development. I recommend following these guides to implement proxies in production:

First, we will set up the application with CRA so we can set up the proxy servers.

Create React App setup

Make sure you have Node installed on your computer to use CRA. Then, in a new directory, start a terminal and run the following command:

npx create-react-app proxyclient && cd proxyclient
Enter fullscreen mode Exit fullscreen mode

The command above will create a new directory called proxyclient and set the terminal directory to /proxyclient. The following folders and files should be present in the folder:

Proxyclient folder structure

The package.json file should also have a similar structure:

{
  "name": "proxyclient",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.2",
    "@testing-library/react": "^12.1.3",
    "@testing-library/user-event": "^13.5.0",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "5.0.0",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

Edit the App.js file in the src folder to include the following code:

import React, { useEffect } from 'react'
const App = () => {
  useEffect(() => {
    fetch('https://google.com/search?q=javascript')
      .then(resp => {
        console.log(resp);
        console.log('======success=======');
      })
      .catch(err => {
        console.log('======failure=======');
        console.log(err);
      });
  }, [])
  return (
    <div>App</div>
  )
}
export default App
Enter fullscreen mode Exit fullscreen mode

Above, the fetch function is used to make a request to the cross-origin URL https://google.com/search?q=javascript.

The application server should then be started so that we can view the response. Run the following command in the project directory's terminal to start the application server:

npm start

By default, the above command will start listening on port 3000 on localhost or 127.0.0.1. If you open a browser and type “localhost:3000,” you should see something like this in the console:

error message

Using a CRA default proxy

To avoid this problem, we'll define our CRA's default proxy by including a proxy field in the package.json file like to this:

{
  ...,
  "proxy": "https://www.google.com",
  ...
}
Enter fullscreen mode Exit fullscreen mode

Then, in the App.js file, change the fetch request like so:

fetch('/search?q=proxy')
Enter fullscreen mode Exit fullscreen mode

Above, we removed the origin and structure the request URL as if it were a same-origin request. The request should be successful, as shown in the browser console. It should output something like this:

success message

Take notice of the URL in the response; it was transmitted to the browser as a same-origin, which resulted in http://localhost:3000/search?q=proxy, and the CORs error was gone. The browser receives the request and transmits it to the proxy server, which then redirects the request to the actual API server specified in the package.json file.

We may also make requests to several servers by specifying the routes that should be used to target a specific domain. To accomplish this, we'll structure our proxy field in the package.json file like so:

{
  ...,
  "proxy": {
    "/search" : {
      "target" : "https://www.google.com",
      "changeOrigin" : true
    },
    "/jobs" : {
      "target" : "https://stackoverflow.com",
      "changeOrigin" : true
    }
  }
  ...
}
Enter fullscreen mode Exit fullscreen mode

Above, we defined two paths: /search and /jobs, which target two separate domains.

When we execute a fetch request on /jobs, the browser sends the request as http://localhost:3000/jobs, but the proxy server forwards it as https://stackoverflow.com/jobs.

Using a manually created proxy in Create React App

If you don't want to use the default CRA proxy, you may use the http-proxy-middleware npm package. Just note that this feature is available in react-scripts@2.0.0 or higher.

This package must be installed as a project dependency before it can be used. To do so, open a terminal and execute the following command in the project directory:

npm i http-proxy-middleware --save
Enter fullscreen mode Exit fullscreen mode

Ensure you don’t have proxy defined in the package.json file, then create a new file named setupProxy.js in the src directory. Add the following code snippet to the setupProxy.js file:

const { createProxyMiddleware } = require('http-proxy-middleware');
const proxy = {
    target: 'https://www.google.com',
    changeOrigin: true
}
module.exports = function(app) {
  app.use(
    '/search',
    createProxyMiddleware(proxy)
  );
};
Enter fullscreen mode Exit fullscreen mode

The code snippet above exports a function to the application so that the proxy middleware is registered to the application as soon as the development server starts up, without the need to import it into any file. Once the application is launched, it will start automatically.

We used createProxyMiddleware from http-proxy-middleware that we installed previously to register a proxy target for /search.

In cases when there are several proxy targets, we simply call the app.use function as follows:

const { createProxyMiddleware } = require('http-proxy-middleware');
const proxy = {
    target: 'https://www.google.com',
    changeOrigin: true
}
const proxy2 = {
    target: 'https://www.stackoverflow.com',
    changeOrigin: true,
}
module.exports = function(app) {
  app.use(
    '/search',
    createProxyMiddleware(proxy)
  );

  app.use(
    '/jobs',
    createProxyMiddleware(proxy2)
  );
};
Enter fullscreen mode Exit fullscreen mode

Above, we called the app.use method after creating another object named proxy2 that included the proxy parameters of the other target domain in order to construct a proxy middleware.

Conclusion

You may expect better security, confidential requests, regulated requests, and other benefits when you use proxy servers in your client applications. Now that you know why and how to use a dev proxy server with CRA, I encourage you to put it to use in your next project.

Please feel free to ask questions or make suggestions in the comments section below.


Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket signup

LogRocket is like a DVR for web and mobile apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — start monitoring for free.

Latest comments (0)