Crear nuestro primer proyecto

  1. Instalamos nodejs
  2. A partir de aquí, tenemos dos opciones:
    • Usar create-react-app
    • Configurar el proyecto manualmente

Usar create-react-app

npx create-react-app mi-aplicacion

Configurar el proyecto manualmente

Es buena idea partir del siguiente proyecto que ya tiene una configuración con únicamente las cosas que necesitamos habitualmente. Para ejecutar el primer comando necesitaremos tener git instalado.

git clone https://github.com/monteserin/react-template.git
Si no queremos descargar la carpeta .git:
npx degit monteserin/react-template

El código relevante que está dentro de esta plantilla es:

package.json
{
  "name": "template",
  "version": "1.0.0",
  "description": "",
  "main": "./dist",
  "scripts": {
    "build": "cross-env NODE_ENV=production webpack",
    "start": "cross-env NODE_ENV=development webpack serve",
    "upload": "node ./bin/upload.js",
    "remove-node_modules": "npx rimraf ./node_modules"
  },
  "author": "Pablo Monteserín",
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "7.12.7",
    "@babel/core": "7.12.7",
    "@babel/plugin-proposal-optional-chaining": "7.12.7",
    "@babel/plugin-transform-runtime": "7.12.1",
    "@babel/preset-env": "7.12.7",
    "@babel/preset-react": "7.12.7",
    "@babel/runtime": "7.12.5",
    "babel-loader": "8.2.1",
    "babel-plugin-import-directory": "1.1.0",
    "babel-plugin-inline-import": "3.0.0",
    "babel-plugin-module-resolver": "4.0.0",
    "babel-plugin-wildcard": "6.0.0",
    "babel-preset-react": "6.24.1",
    "cross-env": "7.0.2",
    "file-loader": "6.2.0",
    "html-webpack-plugin": "4.5.0",
    "react-styleguidist": "11.1.3",
    "url-loader": "4.1.1",
    "webpack": "5.6.0",
    "webpack-cli": "4.2.0",
    "webpack-dev-server": "3.11.0"
  },
  "dependencies": {
    "axios": "0.21.0",
    "easy-ftp": "0.4.1",
    "react": "17.0.1",
    "react-dom": "17.0.1",
    "react-router": "5.2.0",
    "react-router-dom": "5.2.0",
    "styled-components": "5.2.1"
  }
}

El webpack.config.js se encarga de configurar el empaquetado (bundle) de la aplicación que vamos a generar:

/webpack.config.js
// Cargamos un módulo nativo de node que nos gestiona rutas
const path = require('path');

// Cargamos webpack para definir plugins propios
const webpack = require('webpack');

// Este módulo inyecta el bundle en el HTML
const HtmlWebpackPlugin = require('html-webpack-plugin');

// Constantes con los paths de la aplicación
const paths = {
  ROOT: path.resolve(__dirname),
  DIST: path.resolve(__dirname, 'dist'),
  SRC: path.resolve(__dirname, 'src'),
};

//process.env nos permite acceder a las variables de entorno del sistema operativo
//Accedemos a las variables definidas de entorno que hemos definido en el package.json
const development = process.env.NODE_ENV === 'development';
// Si usamos react-router y subimos nuestra aplicación a producción, habrá que asignar a la variable publicPath la ruta donde se va a alojar el proyecto
const publicPath = './';

// Set plugins
const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
  template: './src/index.html',
  hash: !development,
});

const processEnvPlugin = new webpack.DefinePlugin({
  'process.env': {
    PUBLIC_PATH: JSON.stringify(publicPath),
  },
});

module.exports = {
  entry: path.join(paths.SRC, 'index.js'),
  output: {
    path: paths.DIST,
    filename: 'bundle.js',
    publicPath: publicPath || '/',
  },
  module: {
    rules: [
      {
        test: /\.(js)$/,
        exclude: /node_modules/,
        use: 'babel-loader',
      },
      {
        test: /\.(jpg|jpeg|gif|png)$/,
        loader: 'file-loader',
        options: {
          publicPath: `${publicPath}/statics/images/`,
          outputPath: './statics/images/',
          name: '[name].[ext]',
        },
      },
      {
        test: /\.(wav|mp3)$/,
        loader: 'file-loader',
        options: {
          publicPath: `${publicPath}/statics/audio/`,
          outputPath: './statics/audio/',
          name: '[name].[ext]',
        },
      },
      {
        test: /\.(mp4)$/,
        loader: 'file-loader',
        options: {
          publicPath: `${publicPath}/statics/video/`,
          outputPath: './statics/video/',
          name: '[name].[ext]',
        },
      },
      {
        test: /\.(eot|svg|ttf|woff|woff2|otf)$/,
        loader: 'file-loader',
        options: {
          publicPath: `${publicPath}/statics/vectors/`,
          outputPath: './statics/vectors/',
          name: '[name].[ext]',
        },
      },
    ],
  },
  resolve: {
    extensions: ['.js'],
  },
  devServer: {
    historyApiFallback: true,
    disableHostCheck: true,
    hot: false,
    port: 8085,
    open: true,
  },
  optimization: {
    minimize: !development,
  },
  mode: process.env.NODE_ENV,
  devtool: development && 'source-map',
  plugins: [
    HtmlWebpackPluginConfig,
    processEnvPlugin,
  ],
};

Babel se encarga de transpilar nuestro código Javascript EcmaScript 6+ ( preset-env ) y nuestro código JSX ( preset-react ) a versiones más antiguas y por tanto más aceptadas por la mayoría de los nacegadores.

Un preset es una agrupación de plugins. Los plugins definirán como se hará la transpilación en babel.

Cómo ves, primero ponemos las agrupaciones de plugins (presets) y luego los plugins sueltos.

/.babelrc
{
  "presets": [
    "@babel/preset-env",
     ["@babel/preset-react", {
      "runtime": "automatic"
    }]
  ],
  "plugins": [
    "@babel/plugin-transform-runtime"
  ]
}
/src/index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>React App</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>
/src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <App />,
  document.getElementById('root')
);
/src/App.js
import React from 'react';

export default () => (
    <div>
        hola
    </div>
);
/bin/upload.js
const EasyFtp = require('easy-ftp');
const ftp = new EasyFtp();
const config = {
    "name": "pablomonteserin.com",
    "host": "example.com",
    "port": 21,
    "type": "ftp",
    "username": "usuario",
    "password": "password",
};

//(connect)
ftp.connect(config);
ftp.upload("./dist/**", "/www/termine", function(err) {
    if(err) {
        return console.error(err);
    }
    console.info('Deployed!');
});

Arrancar una aplicación

npm start
← Configuración del Visual Studio Code para React
Código JSX en nuestro proyecto de React →

Aviso Legal | Política de privacidad