4

Crea tu blog con ReactJS, GitHub y Surge

106Puntos

hace 4 años

¿Se podrá crear un blog de nuestra propia autoría sin usar servicios ya construidos como Jekyll o WordPress? Es lo que me preguntaba antes de empezar este proceso, porque muchas veces estos servicios son complicados de configurar y en algunos casos no te brindan la flexibilidad para todo lo que necesitas. Por esto me vino la idea de crear un blog usando ReactJS para construir una aplicación web que se encargue de cargar y mostrar los posts ya escritos, como te voy a enseñar en este post. ¡Comencemos!

Arquitectura del blog

Como desarrollador siempre busco separar los datos de la vista, entonces decidí tener dos sitios: el primero con GitHub Pagesque se encargara de guardar y servir los posts que hallan para el blog y el segundo alojado usando Surge.sh que se encargara de mostrar la página web. Arquitectura del blog

GitHub Pages - Datos del blog

GitHub permite crear páginas estáticas; para este proyecto lo usé para guardar los posts de una manera organizada y por el hecho de que permite modificar tus posts directamente en su interfaz web. Esta página es guardada en un rama llamada gh-pages en nuestro repositorio. Por ejemplo, puedes ver la rama de mi blog en: https://github.com/alexsotocx/alexsotocx.co/tree/gh-pages. interfaz GitHub El punto de entrada de la página es un archivo JSON (Notación de Objetos de JavaScript)que contiene los posts que están disponibles para mostrar, y para cada post una información específica que se utilizará para mostrar y unir las páginas. Veamos un ejemplo del archivo JSON:
{
  "posts": [
    {
      "title": "Ruby starting guide",
      "folder": "ruby-guide",
      "cover_image": "ruby.png",
      "author": {
        "name": "Alexander Soto Cardona",
        "email": "[email protected]"
      },
      "tags": ["ruby", "syntax", "guide"],
      "description": "Ruby starting syntax, basic commands to make your ruby programs run",
      "date": "2016-04-01"
    }
  ]
}
Pasemos a explicar que es cada dato:
  • title: Es el título del post;
  • folder: Indica la ruta a seguir para llegar a la carpeta donde están almacenados los archivos para este post;
  • cover_image: Es el nombre del archivo que guarda la imagen del post;
  • author: Es un objeto JSON que guarda toda la información acerca del autor;
  • tags: Son las palabras claves del post y se almacenan como un arreglo;
  • description: Es un texto que contiene la descripción del post;
  • date: Es la fecha de publicación.

Surge - página web

Surge es un servicio que te permite cargar páginas estáticas a servidores y ellos se encargan de servir los archivos usando un CDN (Content Delivery Network). Con Surge ejecutas el comando surge y tendrás disponible un sitio en Internet. Te permite además usar la API de HTML5 para hacer el enrutamiento desde el cliente. Para más detalles puedes consultar este post (en inglés). surge Para el blog, Surge tendrá una aplicación web que funciona con ReactJS para añadir todo la reactividad a nuestra página, React Router para enrutar desde el cliente, Markdown-it para convertir los posts que están escritos en markdown a HTML y Superagent para realizar las peticiones.

Implementación usando ReactJS

Para comenzar necesitaremos una versión de Node.js actualizada. Cuando realicé este experimento utilicé la versión de node 4.2.3. Instala la versión que desees usando NVM.

Estructurando el blog

Para crear la estructura de carpetas, la configuración inicial y poder comenzar con la creación del código recomiendo usar Yeoman. Este estructura toda la aplicación tomando como base el generador que escojamos. Para instalarlo utilizamos NPM:
npm install -g yo
Luego de instalar Yeoman, procedemos a instalar el generador y crear nuestro proyecto:
npm install -g generator-react-webpack
mkdir blog && cd blog
yo react-webpack
Cuando finalice la configuración de nuestro proyecto procedemos a instalar las dependencias (React Router, Markdown-it y Superagent) que necesitamos para que el blog funcione de la manera que hemos mencionado. Para esto procedemos a ejecutar los siguientes comandos:
npm install
npm install --save react-router
npm install --save markdown-it
npm install --save superagent

Creando el enrutador

Para crear el enrutador utilizaremos React Router;este nos permite crear las rutas para la aplicación utilizando un componente llamado Route. Este componente tiene dos propiedades, path component que se va a mostrar en esa ruta. En el blog necesitamos tres rutas:
  • La ruta raiz "/": Donde los usuarios van a llegar;
  • El index del blog "/blog": Donde todos los posts se van a mostrar;
  • El visualizador de posts "/blog/:post_name": Donde se va a mostrar el post.
//Archivo src/components/App.js
import { Router, Route, browserHistory, IndexRedirect } from 'react-router';
import React from 'react';
import Main from './Template/Template'; //Solo el template

import BlogIndex from './Blog/BlogIndex'
import Post from './Blog/Post'

class App extends React.Component {

  constructor(props) {
    super(props);
  }

  render() {
    return (
      <Router history={browserHistory}>{//The browser history is the HTML5 API to client routing}
        <Route path="/" component={Main}>
          <IndexRedirect to="blog"/>
          <Route path="blog" component={BlogIndex}/>
          <Route path="blog/:post_name" component={Post}/>
        </Route>
      </Router>
    );
  }
}

export default App;
El anterior archivo es la entrada de nuestro programa.

Creando el index del blog

El index es la página inicial de nuestro blog. Esta página ayudará a los usuarios a encontrar el post que quieren leer. Cuando un usuario llega a la ruta "/blog", React Router se encarga de montar el componente BlogIndex.  Al montar el componente, este ejecuta una acción que se encarga de lanzar una petición a GitHubPages para cargar el archivo post.json.Con la información que brinda este archivo, podemos pintar y conectar nuestro index con cada post. Nota: Este código es representativo: aunque funciona, no es la manera correcta de realizar esto. Para realizar el intercambio de información se recomienda usar Redux.
import React from 'react';
import PostSummary from './PostSummary';
import request from 'superagent';

let config = require('config').default; //Guarda toda la información de configuración como rutas y variables

class BlogIndex extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      posts: [],
      loading: true
    }
  }

  //Pedido a Githubpages
  componentWillMount() {
    request
      .get(config.blogPostsPath)
      .set('Accept', 'application/json')
      .end((err, res) => {
        let loading = false, posts = [];
        if(!err) {
          posts = res.body.posts;
        }
        this.setState({
          loading: loading,
          posts: posts
        });
      })

  }


  render() {
    if(this.state.loading) {
      return null;
    } else {
      return (
        <div>
          {this.state.posts.map((post, index) => <PostSummary post={post} key={index}/>)}
        </div>
      );
    }

  }
}

export default BlogIndex
En el anterior código hay otro componente llamado PostSummary que se encarga de pintar el resumen del post y conectar la entrada con el post.
import React from 'react';
import {Link} from 'react-router';
let config = require('config').default;

export default class PostSummary extends React.Component {

  constructor(props) {
    super(props);
  }

  render() {
    let post = this.props.post;
    return (
      <article className="post">
        <Link to={`/blog/${post.folder}`} className="full-container-link"></Link>
        <img className="image" src={`${config.blogPostPath}/${post.folder}/${post.cover_image}`}/>
        <section className="details">
          <p className="title">{post.title}</p>
          <p className="description">{post.description}</p>
          <section className="tags">
            {post.tags.map((tag, index) => <span className="tag" key={index}>{tag}</span>)}
          </section>
          <section className="author">
            <p className="name">{post.author.name}</p>
            <p className="name">{post.author.email}</p>
          </section>
          <p className="date">{post.date}</p>
        </section>
      </article>
    );
  }
}
La parte más importante se encuentra en la conexión entre este componente y el componente de visualización. Veamos como se realizó:
<Link to={`/blog/${post.folder}`} className="full-container-link"></Link>

Creando el componente de visualización del post

Este componente se encarga de manejar la ruta "/blog/:post_name". La principal acción de este es cargar el post en formato Markdown y transformarlo en HTML para su respectiva visualización.
import React from 'react';
import request from 'superagent';
import {Link} from 'react-router';
import markdown from 'utilities/markdownWrapper';


let config = require('config').default;

class Post extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      loading: true,
      post: null
    }
  }

  componentDidMount() {
    request
      .get(`${config.blogPostPath}${this.props.params.post_name}/post.md`)
      .end((err, res) => {
        var post = '# Error\n';
        if(!err) {
          post = res.text;
        }
        this.setState({
          loading: false,
          post: post
        });
      })
  }

  render() {
    if(this.state.loading) {
      return <Link to="/blog">Go back</Link>;
    } else {
      return (
        <div className="Entry">
          <Link to="/blog" className="static-link"><i className="fa fa-arrow-left"/> Go back</Link>
          <article className="PostContent" dangerouslySetInnerHTML={{__html: markdown(this.state.post)}}></article>
        </div>
      );
    }
  }
}


export default Post;

¿Cómo publicar una nueva entrada?

  1. Crea tu post en formato Markdown, haz commit y push a tu repositorio;
  2. Edita el archivo post.json y agrega una entrada al arreglo de posts;
  3. Publica tu pagina en Surge si aún no lo está;
  4. Míralo online.

Conclusión

Puedes mirar todo el código completo y funcional en mi repositorio de GitHub. Espero que pueda inspirarte: en este ejemplo hemos creado un blog desde cero, pero también puedes usar el mismo proceso para desarrollar otras ideas que desees concretar. Si quieres profundizar este tema, no te pierdas el curso profesional de React.JS en Platzi:

[maxbutton id="3" url="https://platzi.com/cursos/reactjs/?utm_source=blog&utm_medium=cta_curso&utm_campaign=blog-react-github"]

Alex
Alex
@alexsotocx

106Puntos

hace 4 años

Todas sus entradas
Escribe tu comentario
+ 2