Deshazte de la aplicación create-react-app y crea tu propia plantilla para aplicaciones React

El autor del artículo, cuya traducción publicamos hoy, invita a los desarrolladores de React a dejar de usar create-react-app(CRA) y crear su propia plantilla para las aplicaciones de React. Aquí hablaremos de las ventajas y desventajas de CRA, así como también se propondrá una solución que puede reemplazar create-react-app.







¿Qué es CRA?



La aplicación Create React es un conjunto de herramientas creado y mantenido por los desarrolladores de Facebook. CRA es para crear rápidamente aplicaciones React basadas en plantillas. Con CRA, se crea una base de proyecto React con un solo comando.



Fortalezas de CRA



  • CRA le permite crear una base para un proyecto de React con un comando:



    npx create-react-app my-app
    
  • El uso de una CRA ahorra al desarrollador la necesidad de un estudio en profundidad de las herramientas auxiliares. El desarrollador puede concentrarse en React y no preocuparse por configurar Webpack, Babel y otros mecanismos de utilidad.
  • Al aplicar la CRA, el desarrollador solo necesita una dependencia que sea relevante para construir el proyecto. Esto es react-scripts. Esta dependencia incluye todas las demás dependencias de ensamblado, como resultado, resulta que, por ejemplo, un comando es suficiente para instalar y actualizar las dependencias:



    npm install react-scripts@latest
    


CRA



  • CRA . eject, CRA- . customize-cra react-app-rewired, .
  • CRA . React- , React- . CRA « », , react-scripts — , React-. , , , react-scripts — , , «» (Babel) (Webpack), React- . , , , .
  • CRA, me parece, está sobrecargada de oportunidades que, en algún proyecto, pueden resultar no reclamadas. Por ejemplo, los talones de aplicaciones creados con CRA admiten SASS. Es decir, si su proyecto utiliza CSS regular o Less, la compatibilidad con SASS será completamente innecesaria. Aquí , si está interesado, está el archivo de la package.jsonaplicación CRA después del comando eject. Este archivo "desenrolló" las dependencias presentadas anteriormente react-scripts.


Una alternativa a CRA es desarrollar su propia plantilla para crear rápidamente proyectos básicos de React.



Alternativa a CRA



Al desarrollar una alternativa a CRA, la equiparemos con la capacidad de crear rápidamente proyectos básicos de React usando un solo comando. Esto repite una de las funciones útiles create-react-app. Y nosotros, por supuesto, no transferiremos las desventajas de CRA a nuestro sistema, instalando dependencias de forma independiente y configurando el proyecto. Nuestro proyecto no incluirá otras dos características útiles de CRA (liberando al desarrollador de la necesidad de estudiar los mecanismos auxiliares y el esquema de "una dependencia"), ya que también conllevan desventajas (ocultando los mecanismos internos de los subsistemas auxiliares al desarrollador y la complejidad de personalizar sus propias configuraciones de construcción del proyecto) ...



Aquí está el repositorio que contiene todo el código que discutiremos en este artículo.



Comencemos por inicializar el proyecto con herramientas npme inicializar su repositorio git:



npm init
git init


Creemos un archivo con el .gitignoresiguiente contenido:



node_modules
build


Esto nos permitirá no incluir en el repositorio las carpetas cuyos nombres están presentes en el archivo.



Ahora pensemos en las dependencias básicas que necesitamos para construir y ejecutar una aplicación React.



Bibliotecas React y react-dom



Estas son las únicas dependencias de tiempo de ejecución que necesitamos:



npm install react react-dom --save


Transpiler (Babel)



El transpilador de Babel convierte el código compatible con ECMAScript 2015+ en código que funcionará tanto en navegadores nuevos como antiguos. Babel, gracias al uso de presets, también se usa para procesar código JSX:



npm install @babel/core @babel/preset-env @babel/preset-react --save-dev


Así es como se ve una configuración simple de Babel para que sus aplicaciones React estén en funcionamiento. Esta configuración se puede agregar a un archivo .babelrco a package.json:



{
    "presets": [
        "@babel/preset-env",
        "@babel/preset-react"
    ]
}


Babel admite muchos ajustes preestablecidos y complementos . Se pueden agregar al proyecto cuando surja la necesidad.



Bandler (paquete web)



El paquete Webpack es responsable de construir el proyecto, formando un solo archivo de aplicación (paquete) basado en el código del proyecto y el código de sus dependencias. Cuando se utilizan técnicas de optimización de proyectos, como la división de código, un paquete de aplicaciones puede incluir varios archivos.



npm install webpack webpack-cli webpack-dev-server babel-loader css-loader style-loader html-webpack-plugin --save-dev


Una configuración simple de Webpack para crear paquetes de aplicaciones React tiene el siguiente aspecto:



const path = require('path');
const HtmlWebPackPlugin = require('html-webpack-plugin');

module.exports = {
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'bundle.js',
  },
  resolve: {
    modules: [path.join(__dirname, 'src'), 'node_modules'],
    alias: {
      react: path.join(__dirname, 'node_modules', 'react'),
    },
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
        },
      },
      {
        test: /\.css$/,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
          },
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebPackPlugin({
      template: './src/index.html',
    }),
  ],
};


Aquí se pueden agregar varios cargadores de arranque , de acuerdo con las necesidades de una aplicación en particular . Si está interesado en este tema, eche un vistazo a mi artículo , donde hablo sobre las configuraciones de Webpack que puede usar para preparar aplicaciones React para su uso en producción.



Estas son todas las dependencias que necesitamos. Ahora agreguemos un archivo HTML de plantilla y un componente React stub al proyecto.



Cree una carpeta en el directorio del proyecto srcy agréguele un archivo index.html:



<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>React Boilerplate</title>
</head>
<body>
  <div id="root"></div>
</body>
</html>


Cree un componente React en la misma carpeta HelloWorld:



import React from 'react';

const HelloWorld = () => {
  return (
      <h3>Hello World</h3>
  );
};

export default HelloWorld;


Agregue el archivo a la misma carpeta index.js:



import React from 'react';
import { render } from 'react-dom';

import HelloWorld from './HelloWorld';

render(<HelloWorld />, document.getElementById('root'));


Y finalmente, agregue a las package.jsondescripciones de los scripts para lanzar ( start) y construir ( build) el proyecto:



"scripts": {
    "start": "webpack-dev-server --mode=development --open --hot",
    "build": "webpack --mode=production"
  }


Eso es todo. Ahora tenemos una aplicación React stub viable a nuestra disposición. Puede verificar esto ejecutando los comandos npm starty npm run build.



Ahora equipemos nuestro sistema con la capacidad de preparar una plantilla de proyecto con un solo comando. Es decir, recrearemos uno de los puntos fuertes de la CRA. Vamos a utilizar un archivo JS ejecutable que se llamará cuando ingrese el comando apropiado en la línea de comandos. Por ejemplo, un comando como este podría verse así:



reactjs-boilerplate new-project


Para implementar esta idea, usaremos la sección bin del archivo package.json.



Primero, instale el paquete fs-extra :



npm i fs-extra


Ahora creemos un archivo JS ejecutable start.js, que se ubicará en binla carpeta de nuestro proyecto. Pongamos el siguiente código en este archivo:



#!/usr/bin/env node
const fs = require("fs-extra");
const path = require("path");
const https = require("https");
const { exec } = require("child_process");

const packageJson = require("../package.json");

const scripts = `"start": "webpack-dev-server --mode=development --open --hot",
"build": "webpack --mode=production"`;

const babel = `"babel": ${JSON.stringify(packageJson.babel)}`;

const getDeps = (deps) =>
  Object.entries(deps)
    .map((dep) => `${dep[0]}@${dep[1]}`)
    .toString()
    .replace(/,/g, " ")
    .replace(/^/g, "")
    //  ,     ,    
    .replace(/fs-extra[^\s]+/g, "");

console.log("Initializing project..");

//     npm-
exec(
  `mkdir ${process.argv[2]} && cd ${process.argv[2]} && npm init -f`,
  (initErr, initStdout, initStderr) => {
    if (initErr) {
      console.error(`Everything was fine, then it wasn't:
    ${initErr}`);
      return;
    }
    const packageJSON = `${process.argv[2]}/package.json`;
    //  ,   
    fs.readFile(packageJSON, (err, file) => {
      if (err) throw err;
      const data = file
        .toString()
        .replace(
          '"test": "echo \\"Error: no test specified\\" && exit 1"',
          scripts
        )
        .replace('"keywords": []', babel);
      fs.writeFile(packageJSON, data, (err2) => err2 || true);
    });

    const filesToCopy = ["webpack.config.js"];

    for (let i = 0; i < filesToCopy.length; i += 1) {
      fs.createReadStream(path.join(__dirname, `../${filesToCopy[i]}`)).pipe(
        fs.createWriteStream(`${process.argv[2]}/${filesToCopy[i]}`)
      );
    }
    // npm,   ,   .gitignore,        ;    .     GitHub-  raw- .gitignore
    https.get(
      "https://raw.githubusercontent.com/Nikhil-Kumaran/reactjs-boilerplate/master/.gitignore",
      (res) => {
        res.setEncoding("utf8");
        let body = "";
        res.on("data", (data) => {
          body += data;
        });
        res.on("end", () => {
          fs.writeFile(
            `${process.argv[2]}/.gitignore`,
            body,
            { encoding: "utf-8" },
            (err) => {
              if (err) throw err;
            }
          );
        });
      }
    );

    console.log("npm init -- done\n");

    //  
    console.log("Installing deps -- it might take a few minutes..");
    const devDeps = getDeps(packageJson.devDependencies);
    const deps = getDeps(packageJson.dependencies);
    exec(
      `cd ${process.argv[2]} && git init && node -v && npm -v && npm i -D ${devDeps} && npm i -S ${deps}`,
      (npmErr, npmStdout, npmStderr) => {
        if (npmErr) {
          console.error(`Some error while installing dependencies
      ${npmErr}`);
          return;
        }
        console.log(npmStdout);
        console.log("Dependencies installed");

        console.log("Copying additional files..");
        //     
        fs.copy(path.join(__dirname, "../src"), `${process.argv[2]}/src`)
          .then(() =>
            console.log(
              `All done!\n\nYour project is now ready\n\nUse the below command to run the app.\n\ncd ${process.argv[2]}\nnpm start`
            )
          )
          .catch((err) => console.error(err));
      }
    );
  }
);


Ahora, vinculemos este ejecutable JS con el comando de package.json:



"bin": {
    "your-boilerplate-name": "./bin/start.js"
  }


Creemos un enlace local para el paquete:



npm link


Ahora, luego de ejecutar este comando, si ejecutamos un comando del formulario en la terminal your-boilerplate-name my-app, se llamará a nuestro archivo ejecutable start.js. Se va a crear una nueva carpeta con un nombre my-app, copiar los archivos package.json, webpack.config.jsy .gitignore, al igual que la carpeta src, e instalar las dependencias del nuevo proyecto my-app.



Maravilloso. Ahora todo se ejecuta en su computadora y le permite crear proyectos básicos de React con su propia configuración de compilación con un solo comando.



Puede continuar y publicar su plantilla en el registro de npm . Para hacer esto, primero debe enviar el proyecto al repositorio de GitHub. Luego siga estas instrucciones.



¡Felicidades! Acabamos de crear una alternativa en tan solo unos minutos create-react-app. Nuestra solución no está sobrecargada con características innecesarias (las dependencias se pueden agregar a proyectos basados ​​en ella cuando surja la necesidad). Al usarlo, puede ajustar fácilmente la configuración de construcción del proyecto para que se adapte a sus necesidades.



Por supuesto, nuestra solución es minimalista. Los proyectos creados sobre esta base no pueden considerarse listos para su uso en producción. Para prepararlos para el trabajo real, necesitamos equipar nuestra plantilla con algunas configuraciones de Webpack responsables de optimizar las compilaciones del proyecto.



He preparado la plantilla reactjs-boilerplatepermitiéndole crear proyectos listos para la producción. Utiliza la configuración de compilación adecuada, linting y hooks responsables de verificar el proyecto antes de crear confirmaciones. Prueba esta plantilla. Si tienes alguna idea para mejorarlo, o si decides contribuir a su desarrollo, únete al trabajo en él.



Salir



Esto es de lo que hablamos en este artículo:



  • Hemos cubierto los pros y los contras create-react-app.
  • Hemos implementado en nuestro proyecto una función CRA útil para crear aplicaciones React en blanco con un solo comando. Y nos deshicimos de las deficiencias de CRA.
  • Hemos equipado nuestro proyecto con las configuraciones mínimas de Webpack y Babel necesarias para crear y ejecutar aplicaciones React.
  • Creamos un componente React HelloWorld.js, proporcionamos la capacidad de construir un proyecto y ejecutarlo usando el servidor de desarrollo.
  • Creamos un archivo JS ejecutable y lo vinculamos al comando apropiado usando la sección de binarchivos package.json.
  • Usamos el equipo npm linkpara crear un enlace local para nuestro proyecto y poder crear nuevos proyectos de línea base a partir de él con un solo equipo.


Espero que este material te ayude a desarrollar proyectos basados ​​en React.



¿Usas create-react-app al crear nuevos proyectos de React?






All Articles