Original article: How to Deploy a Routed React App to GitHub Pages

Cuando construimos proyectos, queremos mostrarlos en línea. En lugar de comprar un dominio y tomarse el tiempo para configurarlo, es más fácil hospedarlo usando GitHub Pages.

Un proyecto que solo usa JavaScript, HTML y CSS es fácil de alojar en GitHub Pages. Sin embargo, los proyectos creados en React, Vue o Angular requieren algunas configuraciones. Esto le brinda a cualquier persona que visite tu aplicación en línea la misma experiencia que tiene cuando crea la aplicación localmente.

En este artículo, te mostraré cómo crear una aplicación React simple que use enrutamiento y luego aprenderemos cómo cargarla en GitHub Pages. Daremos especial atención a la parte de enrutamiento, ya que es importante entender e implementar.

⚠️ Este artículo asume que tienes algún conocimiento de React y Git.

Requisitos previos

Debes tener Node, yarn y npm instalados en tu máquina. Para verificar si están instalados, abre una ventana de terminal y escribe lo siguiente:

npm -v
yarn -v
node -v

Si estos comandos imprimen un número de versión en la terminal, está listo para comenzar. De lo contrario, debes continuar e instalar lo que falta.

También necesitaremos crear un repositorio en GitHub. Dirígete a tu cuenta y crea un nuevo repositorio. Elige el nombre que consideres adecuado para este proyecto, pero me quedo con starter-project para el resto de este artículo.

Para crear nuestro proyecto, usaremos create-react-app. Es un paquete que te permite crear una aplicación de una sola página con facilidad. Para crear un proyecto, debes escribir lo siguiente en la terminal:

npx create-react-app starter-project

Una vez que finalice la operación, tendrás un proyecto React repetitivo, listo para funcionar. Para ver si funciona correctamente, dirígete al directorio del proyecto (en nuestro ejemplo sería starter-project) y ejecuta el comando:

yarn start

Si todo funciona correctamente, verás un mensaje en la terminal que dice que tu aplicación se está ejecutando en un servidor local en esta dirección: http://localhost:3000

Si te diriges allí en tu navegador, verás esto:

IB8uRE3cjN

Cómo implementar tu proyecto en GitHub

Es posible que hayas notado que no hemos creado ningún repositorio en GitHub. Entonces, antes de continuar, debemos tener nuestro proyecto cargado allí. Dirígete a tu cuenta de GitHub y crea un repositorio con el mismo nombre que el proyecto React: starter-project.

☝️ Asegúrate de marcar tu repositorio como público. Si lo marca como privado, no podrá usar las GitHub Pages.

Vamos a añadir este repositorio como remoto a nuestro proyecto. Para hacer eso, en la terminal, escriba:

git remote add <name-of-remote> <url-of-repository>

Entonces, en nuestro caso, el comando se ve así:

git remote add origin https://github.com/TomerPacific/starter-project
Es importante llamar al control remoto origin es como se utilizará en nuestro proceso de implementación.

Después de ejecutar el comando anterior, aún no podemos enviar nuestro código. Primero, necesitamos configurar una rama ascendente y establecer el control remoto como origen.

 git push --set-upstream origin master

Ahora, podemos enviar todos los archivos de nuestro proyecto a nuestro repositorio.

Para que podamos cargar nuestra aplicación creada en GitHub Pages, primero debemos instalar el paquete gh-pages.

yarn add gh-pages

Este paquete nos ayudará a implementar nuestro código en la rama gh-pages que se usará para alojar nuestra aplicación en GitHub Pages.

Para permitirnos usar el paquete gh-pages correctamente, necesitamos agregar dos claves al valor de nuestros scripts en el archivo package.json:

"scripts": {
    "start": "react-scripts start",
    "predeploy": "npm run build", <----------- #1
    "deploy": "gh-pages -d build", <---------- #2
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },

A continuación, debemos modificar nuestro archivo package.json agregando el campo de la página de inicio. React utiliza este campo para averiguar la URL raíz en el archivo HTML creado. En él pondremos la URL de nuestro repositorio de GitHub.

{
  "name": "starter-project",
  "homepage": "https://tomerpacific.github.io/starter-project/", <----
  "version": "0.1.0",
  /....
}

Para desplegar nuestra aplicación, escribe lo siguiente en la terminal:

npm run deploy

Ejecutar el comando anterior se encarga de compilar tu aplicación y enviarla a una rama llamada gh-pages, que GitHub usa para vincularse con las páginas de GitHub.

? Si no nombraste tu control remoto origin, obtendrás un error durante esta fase que indica que: Failed to get remote.origin.url (task must either be run in a git repository with a configured origin remote or must be configured with the "repo" option).

Sabrás que el proceso fue exitoso si al final del mismo ves la palabra Publicado. Ahora podemos dirigirnos a nuestro repositorio de GitHub en Configuración y desplazarnos hacia abajo hasta la sección Páginas de GitHub.

chrome_egdTtIso1X

Si ves un mensaje similar al anterior, significa que tu aplicación ahora está alojada correctamente en las GitHub Pages.

Enrutamiento en React

Hasta ahora:

  1. Tenemos una aplicación básica de React que está alojada en GitHub Pages
  2. También tenemos un proceso simplificado para implementarlo cuando queremos hacer cambios.

Pero dado que el propósito de este artículo es mostrar una aplicación más compleja que la que creamos inicialmente, analizaremos el enrutamiento.

Un componente que falta en nuestra aplicación es la navegación. Nuestra aplicación no será solo una página, probablemente tendrá muchas páginas. Entonces, ¿cómo podrán los usuarios navegar entre ellos?

React es una biblioteca y no contiene todo lo que necesitas para su aplicación lista para usar (en nuestro caso, enrutamiento). Por lo tanto, necesitaremos instalar react router.

React router tiene diferentes componentes para aplicaciones web y para aplicaciones nativas. Como estamos construyendo una aplicación web, usaremos react-router-dom.

yarn add react-router-dom

Para hacer uso del enrutamiento en nuestra aplicación, creemos un elemento de navegación que estará visible en la parte superior de la aplicación. Agregaremos esto dentro de nuestro archivo App.js y reemplazaremos el marcado HTML actual que está allí.

 <div>
     <nav>
         <ul id="navigation">
             <li>
                 <Link to="/">Home</Link>
             </li>
             <li>
                 <Link to="/about">About</Link>
             </li>
             <li>
                 <Link to="/contact">Contact</Link>
             </li>
         </ul>
     </nav>
</div>

Por lo general, en un proyecto que no sea de React, colocaríamos una ruta relativa a nuestras páginas HTML para cada sección. De esa forma, el navegador sabe desde dónde cargar los datos.

Pero en nuestro proyecto, no tendremos diferentes páginas HTML para cada sección. Simplemente, cargaremos un componente diferente. El marcado que solía estar dentro de App.js ahora se encontrará dentro de un componente llamado Home.

import './App.css';
import React from 'react';
import logo from './logo.svg';

class Home extends React.Component {
    render() {
        return (
            <div className="App">
                <header className="App-header">
                <img src={logo} className="App-logo" alt="logo" />
                <p>
                    Edit <code>src/App.js</code> and save to reload.
                </p>
                <a
                    className="App-link"
                    href="https://reactjs.org"
                    target="_blank"
                    rel="noopener noreferrer"
                >
                    Learn React
                </a>
                </header>
            </div>
            
        );
    }

}

export default Home;
Home.jsx

Como hemos creado tres secciones en nuestra navegación y nos hemos ocupado de la sección de inicio, vamos a dar otro ejemplo con la sección Acerca de.

Crearemos un nuevo archivo llamado About.jsx que contendrá nuestra plantilla y código para la sección acerca de.

import React from 'react';

const divStyle = {
    color:'white'
};

class About extends React.Component {
    
    render() {
        return (
            <div style={divStyle}>
                <h2>About Page</h2>
                <main>
                    <p>This section contains information about...</p>
                </main>
            </div>
        )
    }
}



export default About;

Puede que te preguntes, ¿cómo sabrá la aplicación que debe redirigir al usuario una vez que haga clic en el enlace Acerca de? Para eso usaremos un componente llamado Route.

La ruta es uno de los componentes más importantes en react-router porque te permite representar diferentes componentes según la ruta de la URL. Para nuestro proyecto, usaremos el siguiente código dentro de App.js justo debajo del marcado de navegación.

<Switch>
    <Route exact path="/">
    <Home />
    </Route>
    <Route path="/about">
    <About />
    </Route>
</Switch>

Puedes ver que creamos dos rutas para Home y About. El componente Switch nos permite agrupar los componentes de la ruta y solo coincidirá con uno de ellos.

Nuestro archivo App.js combinado se ve así:

import './App.css';
import React from 'react';
import { Route, Switch, Link } from "react-router-dom";
import About from './About';
import Home from './Home';

class App extends React.Component {
  render() {
      return (
        <div className="App">
          <div>
            <nav>
              <ul id="navigation">
                <li>
                  <Link to="/">Home</Link>
                </li>
                <li>
                <Link to="/about">About</Link>
                </li>
                <li>
                <Link to="/contact">Contact</Link>
                </li>
              </ul>
            </nav>
          </div>
            <Switch>
            <Route exact path="/">
              <Home />
            </Route>
            <Route path="/about">
              <About />
            </Route>
          </Switch>
          </div>
            );
  }
}

export default App;

Una última cosa que debemos hacer es envolver todo nuestro proyecto en un componente de enrutador. Necesitamos hacer esto porque nos permite usar el enrutamiento en nuestra aplicación. Usaremos el componente BrowserRouter, ya que usa la API de historial de HTML5.

ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>,
  document.getElementById('root')
);
index.js

Si ejecutamos las cosas localmente, todo parece funcionar. Implementemos nuestro proyecto en GitHub Pages y veamos cuál es el resultado.

Cómo manejar el enrutamiento usando HashRouter

A primera vista, todo parece funcionar bien. Pero cuando intente actualizar la página o navegar a través del navegador, seguirá recibiendo errores 404.

¿Por qué pasó esto? Porque las Páginas de GitHub no admiten el historial del navegador como lo hace su navegador. En nuestro caso, la ruta https://tomerpacific.github.io/starter-project/about no ayuda a las páginas de GitHub a comprender dónde apuntar al usuario (ya que es una ruta de interfaz).

Para superar este problema, necesitamos usar un Hash Router en lugar de un Browser Router en nuestra aplicación. Este tipo de enrutador usa la parte hash de la URL para mantener la interfaz de usuario sincronizada con la URL.

ReactDOM.render(
  <React.StrictMode>
    <HashRouter>
      <App />
    </HashRouter>
  </React.StrictMode>,
  document.getElementById('root')
);
index.js

Puedes leer más sobre esto aquí.

Vuelve a implementar tu aplicación y estarás satisfecho con el resultado. No más errores 404.