Webpack Dev Server: Setting up proxy

sanamumtaz

Sana Mumtaz

Posted on October 5, 2021

Webpack Dev Server: Setting up proxy

In this article, I'll show you how to configure webpack-dev-server for proxying requests from React frontend to Node/Express backend.

Getting Started

I won't go into much details on how to set up React, Webpack and Babel. You can either create the project from scratch or you can do the following:

Configure Frontend

1- Use Create React App

Run create-react-app to create React frontend for your web app.



npx create-react-app my-app-name


Enter fullscreen mode Exit fullscreen mode

2- Configure Webpack

Add webpack and its relevant packages to your project.



yarn add webpack webpack-cli webpack-dev-server --dev
yarn add html-webpack-plugin --dev


Enter fullscreen mode Exit fullscreen mode

I'll be using yarn throughout this article
At the root of project folder, create file webpack.config.js. I won't go into details of the configuration as its very basic.



const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    entry: {
        basicApp: {
            import: './src/index.js',
            filename: 'basicApp.js'
        }
    },
    output: {
        path: path.resolve(__dirname, 'build/static')
    },
    devServer: {
        port: 3000,
        hot: true,
        open: true,
    },
    resolve: {
        extensions: ['.jsx', '.js', '.json']
    },
    module: {
        rules: [
            {
                test: /\.(js)x?$/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: 'babel-loader'
                    }
                ]
            },
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
            {
                test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
                type: 'asset/resource'
            },
            {
                test: /\.(woff(2)?|eot|ttf|otf|svg|)$/,
                type: 'asset/inline'
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './public/index.html'
        })
    ]
}


Enter fullscreen mode Exit fullscreen mode

And make the following change in the package.json:



"scripts": {
        "start": "webpack serve --mode development",
        "build": "webpack --mode production",
        ...
}


Enter fullscreen mode Exit fullscreen mode

3- Configure Babel

Now before you try to run the app, configure Babel compiler. Install babel and relevant packages.



yarn add @babel/core @babel/preset-env @babel/preset-react babel-loader --dev
yarn add css-loader style-loader --dev


Enter fullscreen mode Exit fullscreen mode

At root of project, create file .babelrc:



{
  "presets": [
    "@babel/preset-env",
    [
      "@babel/preset-react",
      {
        "runtime": "automatic"
      }
    ]
  ]
}


Enter fullscreen mode Exit fullscreen mode

You have successfully configured the frontend of your app.

Configure Backend

Add Express to the project:



yarn add express


Enter fullscreen mode Exit fullscreen mode

It's your choice whether you set up the backend separately or in the same directory. I set it up in the same dir. Create file backend/server.js at the root.



const express = require("express")
const path = require("path")
const app = express()

const DIST_DIR = path.join(__dirname, 'build/static')
const HTML_FILE = path.join(DIST_DIR, 'index.html')
app.use(express.static(DIST_DIR))
app.get('/', (req, res) => {
        res.sendFile(HTML_FILE)
})
app.get('/api/ping', (req, res) => {
        res.send('pong')
})

app.listen(5000)


Enter fullscreen mode Exit fullscreen mode

In dev mode of this set up, frontend runs at localhost:3000 and backend runs at localhost:5000. Hence, you need to connect frontend to backend so that querying on locahost:3000/api/ping hits the backend localhost:5000/api/ping. For this you can configure proxy in webpack.config.js:



devServer: {
        ...
        proxy: {
           '/api': {
                target: 'http://localhost:3000',
                router: () => 'http://localhost:5000',
                logLevel: 'debug' /*optional*/
           }
        }
}


Enter fullscreen mode Exit fullscreen mode

Now any request of form /api/** will be directed to port 5000.

Run the project

To view output of ping API call, you can make small edit to App.js:



import { useState } from "react";
import logo from "./logo.svg";
import "./App.css";

function App() {
  const [pingResponse, setPingResponse] = useState("");

  const pingBackend = () => {
    fetch("/api/ping", {
      method: "GET",
    })
      .then((response) =>
        response.text().then(function (text) {
          setPingResponse(text);
        })
      )
      .catch((err) => console.log(err));
  };

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <button onClick={pingBackend}>Ping Backend</button>
        {pingResponse && <p>Backend Responded with '{pingResponse}'</p>}
      </header>
    </div>
  );
}
export default App;


Enter fullscreen mode Exit fullscreen mode

You can run the frontend and backend from two terminals. (Recommended: concurrently)



//in one terminal
yarn start
//in other terminal
yarn build //optional
node backend/server.js


Enter fullscreen mode Exit fullscreen mode

App Output
We've successfully connected the frontend to backend. You can get the code from my GitHub.

GitHub logo sanamumtaz / react-webpack-backend-proxy

Configuring Webpack Dev Server to proxy request from React frontend to Node.js/Express backend.



Share your thoughts. Feedback's always welcome :)

💖 💪 🙅 🚩
sanamumtaz
Sana Mumtaz

Posted on October 5, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related