Cómo implementar una aplicación create-react con un backend Express para Heroku

Usó la herramienta cli create-react-app para crear su aplicación React, y ahora desea agregar un back-end como Express. ¿Cómo lo haces?

Hay varias formas de hacerlo:

Hospédelos por separado: implemente la aplicación Express en una máquina y la aplicación React en otra máquina.

Use un proxy: ambas aplicaciones están alojadas juntas, pero son servidas por diferentes servidores.

Mantenerlos juntos: haga que sus archivos frontales React y back-end Express existan en un servidor, y haga que Express sirva sus archivos React además de las solicitudes de API.

Aquí, nos centraremos en la tercera opción. Juntos, crearemos una aplicación simple que use Express para crear una API de back-end y también sirva archivos React. Luego lo implementaremos en Heroku. Si no tienes una cuenta Heroku, ¡regístrate gratis! Además, instale las herramientas Heroku cli. (Alternativamente, solo $ brew install heroku)

¡Vamos a crear nuestra aplicación!

La aplicación Backend Express

Primero crearemos nuestro directorio raíz. He nombrado el ejemplo mío, pero siéntete libre de ser creativo. Luego, inicialícelo con NPM o Yarn.

$ mkdir crae-example
$ cd crae-example
$ npm init

Instale paquetes con NPM o Yarn, luego cree nuestro archivo de índice.

$ npm expreso cors cowsay
$ touch index.js

Queremos crear nuestro servidor Express para servir dos rutas. Una ruta básica que devolverá una vaca que dice "¡Hola Mundo!", Y una que acepte entradas personalizadas. Dado que es una aplicación simple, guardaremos todo en un archivo, aunque en la práctica es mucho mejor modularizarlo.

const express = require ('express')
const cowsay = require ('cowsay')
const cors = require ('cors')
// Crea el servidor
aplicación const = express ()
// Sirve nuestra ruta / vaca api que devuelve una vaca de texto parlante personalizada
app.get ('/ api / cow /: say', cors (), async (req, res, next) => {
  tratar {
    texto const = req.params.say
    const moo = cowsay.say ({texto})
    res.json ({moo})
  } catch (err) {
    siguiente (err)
  }
})
// Sirve nuestra ruta base que devuelve una vaca Hello World
app.get ('/ api / cow /', cors (), async (req, res, next) => {
  tratar {
    const moo = cowsay.say ({texto: '¡Hola Mundo!'})
    res.json ({moo})
  } catch (err) {
    siguiente (err)
  }
})
// Elija el puerto e inicie el servidor
const PORT = process.env.PORT || 5000
app.listen (PORT, () => {
  console.log (`Mezclarlo en el puerto $ {PORT}`)
})

Eso es todo para nuestro index.js. Agreguemos un script de inicio a nuestro paquete.json y pruebe nuestra ruta única.

"guiones": {
    "prueba": "echo \" Error: no se especificó ninguna prueba \ "&& salida 1",
    "start": "nodo index.js"
  },

Alternativamente, puede usar nodemon index.js para escuchar cualquier cambio. Comencemos nuestra aplicación:

$ npm start

Debería ver el registro de la consola en su terminal.

¡Nuestra aplicación está funcionando en el puerto 5000!

Luego navegue a http: // localhost: 5000 / api / cow. ¡Es un galimatías, pero es nuestra vaca de texto!

Realmente no parece una vaca ...

Despliegue a Heroku

Es una buena práctica implementarlo al principio, asegúrese de que todo funcione y luego continúe agregando. Inicialicemos un repositorio git para que podamos implementarlo en Heroku.

$ git init
$ echo node_modules> .gitignore
$ git add -A
$ git commit -m "Primera confirmación"

Suponiendo que haya instalado las herramientas CLI de Heroku, ahora podemos usarlo para la implementación. Si aún no lo has hecho, inicia sesión en Heroku.

$ heroku login // ingrese sus credenciales
$ heroku create crae-example
Eso fue fácil, ¿no?

Ahora solo necesitamos enviar nuestro código a Heroku.

$ git push heroku master
Siempre es agradable verlo hecho en la consola.

Si vamos a https://crae-example.herokuapp.com/api/cow deberíamos ver la misma salida de galimatías que el anterior. ¡Nuestra vaca (aplicación) ahora está en vivo en Internet!

La aplicación Frontend React

Necesitamos una interfaz para mostrar nuestra vaca, ¿no? Instalemos la herramienta cli create-react-app.

$ npm i -g create-react-app

Dentro de nuestro directorio raíz que alberga nuestra aplicación Express, creemos nuestra aplicación frontend:

$ crear-reaccionar-cliente de la aplicación

Dado que eso en sí mismo es una aplicación, necesitamos proxy de las solicitudes de API desde la aplicación de interfaz a nuestra aplicación de back-end Express. Afortunadamente, eso se hace fácilmente agregando lo siguiente en client / package.json.

"proxy": "http: // localhost: 5000"

Lo que hace es cuando llamamos a / api / cow desde el lado del cliente, en lugar de ir a http: // localhost: 3000 / api / cow, nos enviará a http: // localhost: 5000 / api / cow.

A continuación, reemplazaremos src / App.js con lo siguiente:

import React, {Component} desde 'react'
importar './App.css'
La aplicación de clase amplía el componente {
  estado = {
    vaca: '',
    texto: ''
  }
componentDidMount () {
    this.fetchCow ()
  }
fetchCow = async () => {
    respuesta constante = espera buscar (`/ api / cow`)
    const initialCow = esperar respuesta.json ()
    const cow = initialCow.moo
    this.setState ({vaca})
  }
customCow = async evt => {
    evt.preventDefault ()
    const text = this.state.text
    const response = await fetch (`/ api / cow / $ {text}`)
    const personalizado = espera respuesta.json ()
    const cow = custom.moo
    this.setState ({vaca, texto: ''})
  }
handleChange = evt => {
    this.setState ({[evt.target.name]: evt.target.value})
    console.log (this.state.text)
  }
render () {
    regreso (
      
        

Texto vaca. Moo

         {this.state.cow}         
                                                
    )   } }
Exportar aplicación predeterminada

Parece mucho, ¡pero no lo es! Simplemente llamamos fetchCow en nuestro componenteDidMount, que nos dará nuestra vaca "Hello World" y la configuraremos en estado para que podamos mostrarla en el render. También representamos un formulario de entrada que permite a los usuarios escribir su texto de cadena personalizado para la salida de vaca.

Opcional: actualice src / App.css. Recomiendo al menos agregar white-space: pre, que mantendrá todos los espacios en blanco en lugar de comprimir múltiples espacios en blanco en uno. ¡Es muy importante para la vaca!

.App {
  pantalla: flex;
  dirección flexible: columna;
  alinear elementos: centro;
  margen: 2em;
  espacio en blanco: pre
}
Código de la aplicación {
  margen: 2em;
  margen superior: 0;
  relleno: 0;
  alinear texto: izquierda;
  tamaño de fuente: 2em;
}
h3 {
  tamaño de fuente: 2.5em;
  margen: 1em;
  relleno: 0;
  borde: 0
}
botón {
  tamaño de fuente: 1em;
  font-family: "Courier New", monoespacio;
  borde: 2px sólido # 000;
  acolchado: 10px 25px;
}
botón: desplazar {
  color de fondo: rgb (255, 235, 59);
}
botón: activo {
  color de fondo: rgb (255, 244, 142);
}
formulario {
  pantalla: flex;
  dirección flexible: columna;
  font-family: "Courier New", monoespacio;
}
entrada {
  tamaño de fuente: 1.5em;
  margen superior: 1em;
  margen inferior: 1em;
  borde: 1px gris sólido
}

Como se trata de una aplicación simple, definimos los atributos css directamente en los elementos en lugar de especificar clases (no recomendado). Para probar que todo funciona, debemos iniciar nuestras dos aplicaciones (desde el directorio raíz):

$ npm inicio de ejecución
cliente de $ cd
$ npm inicio de ejecución

Vaya a http: // localhost: 3000 y debería ver esto:

¡Funciona! Hola Mundo!

Una última cosa: necesitamos actualizar nuestro index.js en nuestro directorio raíz para servir nuestros archivos React una vez que esté en producción:

const path = require ('ruta')
// Servir archivos estáticos desde la aplicación frontend React
app.use (express.static (path.join (__ dirname, 'client / build')))
// Cualquier cosa que no coincida con lo anterior, devuelva index.html
app.get ('*', (req, res) => {
  res.sendFile (path.join (__ dirname + '/client/build/index.html'))
})

Despegue final

Antes de que podamos implementar nuevamente, primero debemos configurar Heroku para construir la aplicación React frontend después de que empujemos todo nuestro código. Esto se debe a que especificamos explícitamente arriba para servir archivos estáticos del cliente / compilación. Configuremos el paquete.json de nuestro directorio raíz por última vez:

"guiones": {
    "prueba": "echo \" Error: no se especificó ninguna prueba \ "&& salida 1",
    "start": "nodo index.js",
    "heroku-postbuild": "cliente de CD && npm install && npm run build"
  },

Agregamos un script heroku-postbuild para que sepa cómo ejecutar el método de compilación incorporado que create-react-app nos proporciona después de que Heroku termina de hacer su propia compilación. ¡Ahora podemos desplegar!

$ git add -A
$ git commit -m 'Implementar despegue!'
$ git push heroku master

Sucederán un montón de cosas en la terminal. pero al final deberías ver la misma URL que antes. ¡Ve a tu URL de Heroku y mira cómo se ejecuta tu aplicación! Puedes jugar con el mío en https://crae-example.herokuapp.com/. ¡Felicidades! ¡Tienes una aplicación React and Express en producción!

Mira el código aquí en Github. ¡Feliz codificación! :)