“This is the fifth day of my participation in the November Gwen Challenge. See details of the event: The Last Gwen Challenge 2021”.

preface

We all know React is great and awesome, so we can use create-React-app to quickly build a front-end application. However, React builds only front-end static resources (such as HTML, CSS, JS, etc.), which cannot be deployed independently. We also need a WEB server and API calls. In this article, I’ll create a full-stack project using React and NodeJS. This section describes how to use Node.js as a Web server to load static resources created by React and how to use the React application to call the NodeJS API directly.

The preparatory work

Before you start, make sure you have Node and NPM installed on your computer.

Create a project directory

First we use the command line to create a directory of my-app and enter my-app

$ mkdir my-app
$ cd my-app
Copy the code

Initialize the React program

Then create a React program using create-react-app. This is the client code, so we call it client

$ npx create-react-app client
Copy the code

Use NodeJS to implement our API

Create API directory

$ mkdir api
$ cd api
Copy the code

Initialize the nodeJS project

npm init -y
Copy the code

Express.js is a very lightweight Node.js framework that installs Express.

npm i --save express
Copy the code

In the API folder, create server.js

// api/server.js

const express = require("express")
const app = express()
app.use(express.json());

app.get("/".function(req, res) {
  res.send("It's working!")
})

app.listen(3000.() = > {
  console.log("app listening on port 3000")})Copy the code

Start the API service on port 3000

Add the startup script in the scripts section of package.json

"scripts": {"start": "node ./api/server.js"
}
Copy the code

Then run it, visit http://localhost:3000, and you can see the following in your browser.

npm start
Copy the code

React access the API

The data returned in the./ API /server interface is JSON

app.get("/".function(req, res) {
  res.json({"name": "Zhang"})})Copy the code

Change. / client/SRC/app. Js

import React, { useEffect, useState } from "react";

export default function App() {
  const [name, setName] = useState("");

  useEffect(() = > {
    fetch("http://localhost:3000")
      .then((res) = > res.json())
      .then((data) = >setName(data.name)); } []);return <div>Hello {name}</div>;
}
Copy the code

This will not be visible on the page. If you look at the Chrome console, you will see the following prompt.

This is because a cross-origin request occurs when the Fetch request is made. To solve this problem:

Plan a

To change the interface to allow cross-domain, we need to install this package before cORS:

npm install --save cors
Copy the code

Change./client/ SRC /app.js to reference this function via middleware.

const cors = require("cors")

app.use(cors())
Copy the code

Then stop the service, NPM start restarts, and you can see the effect.

Scheme 2

Create-react-app supports interface proxy Settings

The development environment

Set in the client/package. Json


proxy:localhost:3000

Copy the code

You can then use relative path requests in JSX

useEffect(() = > {
    fetch("/api")
      .then((res) = > res.json())
      .then((data) = >setName(data.name)); } []);Copy the code

The production environment

Add the following code to serve.js:

if(process.env.NODE_ENV==='production') {// Point the static resource to 'client/build'
    app.use(express.static(path.resolve(__dirname, '.. /client/build')));

    // The interface is prefixed with API
    app.get("/api".(req, res) = > {
      res.json({ message: "Hello from server!" });
    });


    // Any other unprocessed interface returns index.html
    app.get(The '*'.(req, res) = > {
      res.sendFile(path.resolve(__dirname, '.. /client/build'.'index.html'));
    });
}
Copy the code

NPM installs the cross-env package to differentiate between development and production environments.

Change Settings in API /package.json

{
  "scripts": {
    "dev": "cross-env NODE_ENV=development node ./api/server.js",
    "start": "cross-env NODE_ENV=production node ./api/server.js"
  }
}
Copy the code

Plan 3

Development environment or use proxy proxy, production environment using nGINx reverse proxy.

I use Docker-compose locally

Use the following docker-comedy.yml

web:
  image: nginx
  volumes:
    - ./nginx.conf:/etc/nginx/nginx.conf:ro
  ports:
   - "8080:80"
Copy the code

Create nginx.config in the root directory

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush on;keepalive_timeout 65; gzip on; upstream server { server server:3001; } upstream web { server web:3000; } server { listen 80; server_name localhost; location / { proxy_pass http://web/; } location ^~ /api/ { proxy_pass http://server/api/; }}}Copy the code

Start the container service

docker-compose up -d
Copy the code

Then go to http://localhost:8080 and you can see it in your browser.

The last

Guys, which solution would you use? Leave a comment in the comments section.

I hope this article was helpful to you, and you can also refer to my previous articles or share your thoughts and insights in the comments section.