Cree un compilador de código en línea usando React.js y Node.js

En este artículo, aprenderemos cómo crear un compilador de código en línea usando React.js como frontend y Express.js como backend. Los usuarios podrán escribir código C, C++, Python y Java con el resaltado de sintaxis adecuado, así como compilarlo y ejecutarlo en línea. El principal objetivo de construir un compilador en línea es facilitar a cualquier usuario que los programas de cualquier idioma puedan compilarse y ejecutarse sin descargar ningún IDE (Entorno de desarrollo integrado) o compilador.

Requisitos previos: Los requisitos previos para este proyecto son:

Enfoque: Antes de construir toda la aplicación, dividamos la aplicación en dos partes. La primera parte se trata de construir el front-end usando React.js y la segunda parte está construyendo el back-end usando Express.js. En el front-end, tenemos tres secciones, un editor de texto, un cuadro de entrada y un cuadro de salida. En el back-end, creamos una API e implementamos la lógica para compilar el código fuente proporcionado desde el front-end.

Comencemos a construir el Front-end primero.

Creando una aplicación React:

Paso 1: Cree una aplicación React escribiendo el siguiente comando en la terminal:

npx create-react-app code-compiler

Paso 2: ahora, vaya a la carpeta del proyecto, es decir, al compilador de código, ejecutando el siguiente comando:

cd code-compiler

Estructura del proyecto: Se verá así:

Paso 3: Construyamos el editor de texto donde los usuarios escribirán su código. Para esto, usaremos el Editor de Mónaco, que es exactamente el editor de código que usa Microsoft VS Code IDE. Así que usaremos un paquete npm llamado ‘ @monaco-editor/react ‘ para este propósito. Instale algunos paquetes npm:

npm install @monaco-editor/react
npm install axios
npm install react-select

Paso 4: en el archivo App.js, importaremos el editor de texto y crearemos la sección de entrada y la sección de salida. Además, implementaremos dos botones, uno llamado ‘Ejecutar’ y el otro ‘Borrar’. Cada vez que el usuario haga clic en el botón Ejecutar, llamará a una API que compilará nuestro código fuente y mostrará el resultado en la pantalla de salida. El botón Borrar se utilizará para borrar la pantalla de salida cuando se haga clic.

Nombre de archivo: App.js

Javascript

import { useState } from 'react';
import './App.css';
import Editor from "@monaco-editor/react";
import Navbar from './Components/Navbar';
import Axios from 'axios';
import spinner from './spinner.svg';
 
function App() {
 
  // State variable to set users source code
  const [userCode, setUserCode] = useState(``);
 
  // State variable to set editors default language
  const [userLang, setUserLang] = useState("python");
 
  // State variable to set editors default theme
  const [userTheme, setUserTheme] = useState("vs-dark");
 
  // State variable to set editors default font size
  const [fontSize, setFontSize] = useState(20);
 
  // State variable to set users input
  const [userInput, setUserInput] = useState("");
 
  // State variable to set users output
  const [userOutput, setUserOutput] = useState("");
 
  // Loading state variable to show spinner
  // while fetching data
  const [loading, setLoading] = useState(false);
   
  const options = {
    fontSize: fontSize
  }
 
  // Function to call the compile endpoint
  function compile() {
    setLoading(true);
    if (userCode === ``) {
      return
    }
 
    // Post request to compile endpoint
    Axios.post(`http://localhost:8000/compile`, {
      code: userCode,
      language: userLang,
      input: userInput }).then((res) => {
      setUserOutput(res.data.output);
    }).then(() => {
      setLoading(false);
    })
  }
 
  // Function to clear the output screen
  function clearOutput() {
    setUserOutput("");
  }
 
  return (
    <div className="App">
      <Navbar
        userLang={userLang} setUserLang={setUserLang}
        userTheme={userTheme} setUserTheme={setUserTheme}
        fontSize={fontSize} setFontSize={setFontSize}
      />
      <div className="main">
        <div className="left-container">
          <Editor
            options={options}
            height="calc(100vh - 50px)"
            width="100%"
            theme={userTheme}
            language={userLang}
            defaultLanguage="python"
            defaultValue="# Enter your code here"
            onChange={(value) => { setUserCode(value) }}
          />
          <button className="run-btn" onClick={() => compile()}>
             Run
          </button>
        </div>
        <div className="right-container">
          <h4>Input:</h4>
          <div className="input-box">
            <textarea id="code-inp" onChange=
              {(e) => setUserInput(e.target.value)}>
            </textarea>
          </div>
          <h4>Output:</h4>
          {loading ? (
            <div className="spinner-box">
              <img src={spinner} alt="Loading..." />
            </div>
          ) : (
            <div className="output-box">
              <pre>{userOutput}</pre>
              <button onClick={() => { clearOutput() }}
                 className="clear-btn">
                 Clear
              </button>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
 
export default App;

Hemos importado un control giratorio para indicar la carga cuando el usuario presiona el botón Ejecutar. Descargue cualquier spinner de su elección de Internet y colóquelo dentro de la carpeta  ‘ src ‘.

Paso 5: Démosle un poco de estilo a nuestra aplicación.

Nombre de archivo: App.css

CSS

.App{
  max-height: 100vh;
  width: 100%;
  overflow-y: hidden;
  background-color: #474747;
}
.main{
  display: flex;
  height: calc(100vh - 50px);
}
.left-container{
  position: relative;
  flex: 60%;
  height: calc(100vh - 50px);
}
.right-container{
  flex: 40%;
  height: calc(100vh - 50px);
  display: flex;
  flex-direction: column;
  background-color: #242424;
  border-left: 3px solid #1f65e6;
  padding: 5px;
}
.input-box{
  flex: 50%;
}
.input-box textarea{
  font-size: 16px;
}
.spinner-box{
  flex: 50%;
  background-color: #242424;
  overflow-y: auto;
  display: flex;
  justify-content: center;
  align-items: center;
}
.spinner-box img{
  width: 200px;
}
.output-box{
  flex: 50%;
  background-color: #242424;
  overflow-y: auto;
  color: white;
  position: relative;
}
.clear-btn{
  position: absolute;
  bottom: 14px;
  right: 18px;
  width: 80px;
  height: 40px;
  font-size: 22px;
  font-weight: bold;
  color: white;
  background-color: #1f65e6;
  border: none;
  border-radius: 4px;
  transition: 0.3s;
  cursor: pointer;
}
.output-box pre{
  font-size: 15px;
  white-space: pre-wrap;
}
h4{
  color: #afec3f;
}
#code-inp{
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  resize: none;
  background-color: #242424;
  color: whitesmoke;
  padding: 5px;
}
#code-inp:focus{
  outline: none;
}
.run-btn{
  position: absolute;
  bottom: 10px;
  right: 18px;
  width: 80px;
  height: 40px;
  font-size: 22px;
  font-weight: bold;
  background-color: #afec3f;
  border: none;
  border-radius: 4px;
  transition: 0.3s;
  cursor: pointer;
}
.run-btn:active{
  background-color: #6e9427;
}

Paso 6: Construyamos la barra de navegación que ya hemos importado al archivo App.js. En esta barra de navegación, podemos seleccionar el tipo de idioma, elegir un tema y también podemos establecer el tamaño de fuente. Entonces, cree una carpeta llamada ‘ Componentes ‘ debajo de la carpeta src y dentro de ella cree un componente llamado ‘ Navbar.js ‘.

Nombre de archivo: Navbar.js

Javascript

import React from 'react';
import Select from 'react-select';
import '../Styles/Navbar.css';
 
const Navbar = ({userLang, setUserLang, userTheme,
                setUserTheme, fontSize, setFontSize}) => {
    const languages = [
        { value: "c", label: "C" },
        { value: "cpp", label: "C++" },
        { value: "python", label: "Python" },
        { value: "java", label: "Java" },
    ];
    const themes = [
        { value: "vs-dark", label: "Dark" },
        { value: "light", label: "Light" },
    ]
    return (
        <div className="navbar">
            <h1>Geeks Code Compiler</h1>
            <Select options={languages} value={userLang}
                    onChange={(e) => setUserLang(e.value)}
                    placeholder={userLang} />
            <Select options={themes} value={userTheme}
                    onChange={(e) => setUserTheme(e.value)}
                    placeholder={userTheme} />
            <label>Font Size</label>
            <input type="range" min="18" max="30"
                   value={fontSize} step="2"
                   onChange={(e) => { setFontSize(e.target.value)}}/>
        </div>
    )
}
 
export default Navbar

Paso 7: Diseñemos la barra de navegación.

Nombre de archivo: Navbar.css

CSS

.navbar{
    display: flex;
    align-items: center;
    padding-left: 20px;
    height: 50px;
    text-align: center;
    color: #afec3f;
    background-color: #474747;
    gap: 20px;
}
#no{
    height: 36px;
    width: 80px;
    font-size: 16px;
    color: rgb(185, 185, 185);
    border: 1px solid #afec3f;
    border-radius: 4px;
    background-color: #474747;
}
#no:focus{
    outline: none;
}
.css-2b097c-container{
    width: 120px;
    color: black;
    background-color: #474747;
}
.css-yk16xz-control{
    background-color: #474747 !important;
    border-color: #afec3f !important;
}

Ahora comencemos a construir el Back-end

Para el backend, usaremos Express.js. Aquí crearemos un punto final de API para compilar nuestro código. Así que vamos a crear una carpeta llamada ‘ servidor ‘ que contendrá toda la lógica de back-end.

Paso 1: escriba los siguientes comandos en la terminal:

mkdir server
cd server

Paso 2: Inicialicemos un proyecto node.js:

npm init

Paso 3: Instalemos algunas dependencias:

npm install express
npm install cors
npm install axios

Paso 4: Cree un archivo llamado ‘ index.js ‘. Este es el único archivo que contendrá toda la lógica de back-end. En este archivo, crearemos una ruta POST que tomará el código fuente, el idioma y la entrada, si corresponde, desde la interfaz. Después de obtenerlos, llamará a la API de compilación de código (código abierto) cuya respuesta se enviará de vuelta a la interfaz donde se mostrará el resultado en la pantalla de salida. 

Nombre de archivo: index.js

Javascript

const express = require("express");
const cors = require("cors");
const Axios = require("axios");
const app = express();
const PORT = 8000;
 
app.use(cors());
app.use(express.json());
 
app.post("/compile", (req, res) => {
    //getting the required data from the request
    let code = req.body.code;
    let language = req.body.language;
    let input = req.body.input;
 
    if (language === "python") {
        language="py"
    }
 
    let data = ({
        "code": code,
        "language": language,
        "input": input
    });
    let config = {
        method: 'post',
        url: 'https://codexweb.netlify.app/.netlify/functions/enforceCode',
        headers: {
            'Content-Type': 'application/json'
        },
        data: data
    };
    //calling the code compilation API
    Axios(config)
        .then((response)=>{
            res.send(response.data)
            console.log(response.data)
        }).catch((error)=>{
            console.log(error);
        });
})
 
app.listen(process.env.PORT || PORT, () => {
    console.log(`Server listening on port ${PORT}`);
});

Ahora, hemos creado con éxito la ruta de solicitud POST a la que llamaremos desde la interfaz.

Inicie el servidor de fondo:

node index.js

El servidor escuchará en el puerto localhost 8000

Inicie la aplicación frontal:

npm start

Salida: Ahora abra su navegador y vaya a http://localhost:3000/ , verá la siguiente salida:

Publicación traducida automáticamente

Artículo escrito por anomic30 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *