<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Webpack - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Descubre miles de cursos de programación escritos por expertos. Aprende Desarrollo Web, Ciencia de Datos, DevOps, Seguridad y obtén asesoramiento profesional para desarrolladores. ]]>
        </description>
        <link>https://www.freecodecamp.org/espanol/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Webpack - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/espanol/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Mon, 15 Jun 2026 05:22:27 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/espanol/news/tag/webpack/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Cómo usar Webpack con React: un tutorial a profundidad ]]>
                </title>
                <description>
                    <![CDATA[ Actualizado a Babel 7 En este tutorial veremos las bases de Webpack para React para ayudarte a empezar, incluyendo React Router [https://github.com/ReactTraining/react-router] , Reemplazo de Módulo Caliente [https://github.com/gaearon/react-hot-loader]  (HMR), Separación de Código por Route [https://github.com/theKashey/react-imported-component] y Proveedor [https://webpack.js.org/plugins/commons-chunk-plugin/], configuración de producción y más. Antes de que empecemos, aquí hay ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/como-usar-webpack-con-react-un-tutorial-a-profundidad/</link>
                <guid isPermaLink="false">64199f4455e3ad15a8936738</guid>
                
                    <category>
                        <![CDATA[ Webpack ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Elias Ezequiel Pereyra Gomez ]]>
                </dc:creator>
                <pubDate>Fri, 14 Apr 2023 20:20:31 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2023/03/1_6PbJ291MHulQWCmPW9fzDg.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/learn-webpack-for-react-a36d4cac5060/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to use Webpack with React: an in-depth tutorial</a>
      </p><p><em>Actualizado a<em> Babel 7</em></em></p><p>En este tutorial veremos las bases de Webpack para React para ayudarte a empezar, incluyendo <a href="https://github.com/ReactTraining/react-router">React Router</a>, <a href="https://github.com/gaearon/react-hot-loader">Reemplazo de Módulo Caliente</a> (HMR), Separación de Código por <a href="https://github.com/theKashey/react-imported-component">Route</a> y <a href="https://webpack.js.org/plugins/commons-chunk-plugin/">Proveedor</a>, configuración de producción y más.</p><p>Antes de que empecemos, aquí hay una lista completa de las características que estaremos configurando juntos en este tutorial:</p><ul><li>React 16</li><li>React Router 5</li><li>Semantic UI como el Framework de CSS</li><li>Reemplazo de Módulo Caliente (HMR)</li><li>Autoprefijo de CSS</li><li>Módulos de CSS</li><li>@babel/plugin-proposal-class-properties</li><li>@babel/plugin-syntax-dynamic-import</li><li>Webpack 4</li><li>Separación de Código por Ruta y Proveedor</li><li>Analizador de Paquetes de Webpack</li></ul><h4 id="pre-requisitos"><strong>Pre-requisitos</strong></h4><p>Tener lo siguiente pre-instalado:</p><ul><li><a href="https://yarnpkg.com/" rel="noopener">Yarn</a> — Gestor de paquetes, similar a <a href="https://www.npmjs.com/" rel="noopener">npm</a></li><li><a href="https://nodejs.org/en/" rel="noopener">Node</a></li></ul><p>Y deberías tener al menos algún conocimiento básico de React y React Router.</p><p><strong><strong><em><em>Not</em></em></strong><em>a</em><strong><em><em>:</em></em></strong></strong><em><em> </em>Puedes usar<em> npm </em>si lo deseas<em>, </em>aunque los comandos variarán ligeramente<em>.</em></em></p><h4 id="dependencias-iniciales"><strong>Dependencias Iniciales</strong></h4><p>Empecemos creando nuestro directorio y <code>package.json</code>.</p><p>En tu terminal escribe lo siguiente:</p><pre><code class="language-bash">mkdir webpack-para-react &amp;&amp; cd $_
yarn init -y</code></pre><p>Este primer comando creará nuestro directorio y nos metemos dentro, luego inicializamos un <code>package.json</code> aceptando las configuraciones por defecto.</p><p>Si lo inspeccionas verás las configuraciones básicas:</p><pre><code class="language-json">{
  "name": "webpack-para-react",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT"
}</code></pre><p>Ahora instalamos nuestras dependencias iniciales (producción) y dependencias de desarrollo.</p><p>En tu terminal escribe lo siguiente:</p><pre><code class="language-bash">yarn add react react-dom prop-types react-router-dom semantic-ui-react
yarn add @babel/core babel-loader @babel/preset-env @babel/preset-react @babel/plugin-proposal-class-properties @babel/plugin-syntax-dynamic-import css-loader style-loader html-webpack-plugin webpack webpack-dev-server webpack-cli -D</code></pre><p>Las dependencias de desarrollo serán usadas solamente, como su nombre lo dice, durante la fase de desarrollo, y las dependencias (producción) es lo que nuestra aplicación necesita en producción.</p><pre><code class="language-json">{
  "name": "webpack-para-react",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "react": "^16.2.0",
    "react-dom": "^16.2.0",
    "prop-types": "^15.6.2",
    "react-router-dom": "^4.2.2",
    "semantic-ui-react": "^0.77.1"
  },
  "devDependencies": {
    "@babel/core": "^7.0.0",
    "@babel/plugin-proposal-class-properties": "^7.0.0",
    "@babel/plugin-syntax-dynamic-import": "^7.0.0",
    "@babel/preset-env": "^7.0.0",
    "@babel/preset-react": "^7.0.0", 
    "babel-loader": "^8.0.1",
    "css-loader": "^0.28.10",
    "html-webpack-plugin": "^3.0.4",
    "style-loader": "^0.19.1",
    "webpack": "^4.0.0",
    "webpack-cli": "^2.0.14",
    "webpack-dev-server": "^3.0.0"
  }
}</code></pre><p><strong><strong><em><em>Not</em></em></strong><em>a</em><strong><em><em>:</em></em></strong><em> </em></strong><em>Cambios a los archivos creados previamente serán puestos en negrita.<em> </em></em></p><p><strong><strong><em><em>Not</em></em></strong><em>a</em><strong><em><em>:</em></em></strong></strong><em><em> </em>Las versiones de Dependencias podrían ser distintos a los tuyos desde el momento de éste escrito.</em></p><ul><li><a href="https://react.dev/">react</a> — Estoy seguro que sabes qué es React</li><li><a href="https://es.reactjs.org/docs/react-dom.html#gatsby-focus-wrapper">react-dom</a> — Provee métodos específicos del DOM para el navegador </li><li><a href="https://github.com/facebook/prop-types" rel="noopener">prop-types</a> — Verificación de tipo de tiempo de ejecución para las propiedades de React</li><li><a href="https://github.com/ReactTraining/react-router" rel="noopener">react-router-dom</a> — Provee las capacidades de enrutamiento a React para el navegador</li><li><a href="https://react.semantic-ui.com/">semantic-ui-react</a> — Framework de CSS </li><li><a href="https://babeljs.io/docs/en/babel-core/" rel="noopener">@babel/core</a> — Dependencias principales para Babel</li><li><a href="https://babeljs.io/" rel="noopener">Babel</a> es un transpilador que compila JavaScript ES6 a JavaScript ES5 permitiéndote escribir JavaScript "del futuro" de manera que los navegadores actuales lo entenderán</li><li><a href="https://webpack.js.org/loaders/babel-loader/" rel="noopener">babel-loader</a> — Este paquete permite transpilar archivos de JavaScript usando Babel y webpack</li><li><a href="https://babeljs.io/docs/en/next/babel-preset-env.html" rel="noopener">@babel/preset-env</a> — Con este no tienes que especificar si estarás escribiendo ES2015, ES2016 o ES2017. Babel automáticamente lo detecterá y lo transpilará respectivamente</li><li><a href="https://babeljs.io/docs/en/babel-preset-react/" rel="noopener">@babel/preset-react</a> — Le dice a Babel que estaremos usando React</li><li><a href="https://babeljs.io/docs/en/babel-plugin-proposal-class-properties" rel="noopener">@babel/plugin-proposal-class-properties </a>— Usa propiedades de clase. No usamos Propiedades de Clase en este proyecto, pero muy probablemente tú los utilizarás en tu proyecto</li><li><a href="https://babeljs.io/docs/en/babel-plugin-syntax-dynamic-import" rel="noopener">@babel/plugin-syntax-dynamic-import</a> — Ser capaz de usar imports dinámicos</li><li><a href="https://webpack.js.org/loaders/css-loader/" rel="noopener">css-loader</a> — Interpreta <code>@import </code> y <code>url()</code> como <code>import/require()</code> y los resolverá</li><li><a href="https://webpack.js.org/plugins/html-webpack-plugin/" rel="noopener">html-webpack-plugin</a> — Puede generar un archivo HTML para tu aplicación, o puedes proveer una plantilla</li><li><a href="https://webpack.js.org/loaders/style-loader/" rel="noopener">style-loader</a> — Agrega CSS al DOM inyectando una etiqueta <code>&lt;style&gt;</code></li><li><a href="https://webpack.js.org/" rel="noopener">webpack</a> — Empaquetador de Módulos</li><li><a href="https://github.com/webpack/webpack-cli" rel="noopener">webpack-cli</a> — Interfaz de Línea de Comando, necesario para Webpack 4.0.1 y y los últimos</li><li><a href="https://webpack.js.org/configuration/dev-server/" rel="noopener">webpack-dev-server</a> — Provee un servidor de desarrollo para tu aplicación</li></ul><h3 id="configurar-babel"><strong>Configurar Babel</strong></h3><p>En el directorio raíz (<code>webpack-para-react</code>) creamos el archivo de configuración de Babel.</p><pre><code class="language-bash">touch .babelrc</code></pre><p>En este punto puedes abrir tu editor favorito (el mío es VS CODE por cierto), luego apunta el editor a la ruta de este proyecto y abre el archivo <code>.babelrc</code> y copia lo siguiente:</p><pre><code class="language-json">{
  "presets": ["@babel/preset-env", "@babel/preset-react"],
  "plugins": [
    "@babel/plugin-syntax-dynamic-import",
    "@babel/plugin-proposal-class-properties"
  ]
}</code></pre><p>Esto le dice a Babel para usar los preajustes (plugins) que anteriormente instalamos. Luego cuando llamamos <code>babel-loader</code> de Webpack, aquí es donde verá qué hacer.</p><h3 id="configurar-webpack"><strong>Configurar Webpack</strong></h3><p>¡Ahora la diversión comienza! Vamos a crear el archivo de configuración de Webpack.</p><p>En tu terminal escribe lo siguiente:</p><pre><code class="language-bash">touch webpack.config.js</code></pre><p>Abre <code>webpack.config.js</code> y copia lo siguiente:</p><pre><code class="language-js">const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const port = process.env.PORT || 3000;

module.exports = {
  // La configuracion de Webpack va aquí
};</code></pre><p>Este es el shell básico para Webpack. Requerimos <code>webpack</code> y <code>html-wepback-plugin</code>. Provee un puerto por defecto si la variable de entorno PORT no existe y exporta el módulo.</p><p>Lo siguiente serán adiciones para <code>weback.config.js</code> (uno después del otro)</p><pre><code class="language-js">...
module.exports = {
  mode: 'development',
};</code></pre><p><code>mode</code> le dice a Webpack que esta configuración será o para <code>development</code> o para <code>production</code>. "Modo de Desarrollo [está] optimizado para la velocidad y la experiencia del desarrollador... Las configuraciones de Producción por defecto te darán un conjunto de configuraciones preestablecidas útiles para desplegar tu aplicación".</p><pre><code class="language-js">...
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.[hash].js'
  },
};</code></pre><p>Para tener una instancia de Webpack ejecutando necesitamos: </p><ul><li><code>entry</code> — Especifica el punto de entrada de tu aplicación; aquí es donde tu app de React vive y donde el proceso de empaquetamiento comenzará (<a href="https://webpack.js.org/concepts/entry-points/" rel="noopener">Docs</a>)</li></ul><p><em>Webpack 4 introdujo algunas configuraciones por defecto, así que si no incluyes <code>entry</code> en tu configuración, entonces Webpack asumirá que tu punto de entrada está localizado en el directorio <code>./src</code>, haciendo <code>entry</code> opcional en contraposición a Webpack 3. Para este tutorial he decidido dejar <code>entry</code> ya que hace obvio donde estará nuestro punto de entrada, pero eres más que bienvenido en removerlo si así lo deseas. </em></p><ul><li><code>output</code> — Le dice a Webpack cómo escribir los archivos compilados al disco (<a href="https://webpack.js.org/concepts/output/" rel="noopener">Docs</a>)</li><li><code>filename</code> — Éste será el nombre de archivo de la aplicación empaquetada. La porción <code>[hash]</code> del nombre de archivo será reemplazado por un hash generado por Webpack cada vez que tu aplicación cambie y es recompilado (ayuda con caching).</li></ul><pre><code class="language-js">...
module.exports = {
  ...
  devtool: 'inline-source-map',
};</code></pre><p><code>devtool</code> creará <a href="https://firefox-source-docs.mozilla.org/devtools-user/debugger/how_to/use_a_source_map/index.html">mapas de fuente</a> para ayudarte en debuguear tu aplicación. Hay muchos tipos de mapas de fuente y este mapa particular (<code>inline-source-map</code>) es para ser usado solamente en desarrollo. (<a href="https://webpack.js.org/configuration/devtool/">Docs</a> para más opciones). </p><pre><code class="language-js">...
module.exports = {
  ...
  module: {
    // Reglas
    rules: [

      // Primer Regla
      {
        test: /\.(js)$/,
        exclude: /node_modules/,
        use: ['babel-loader']
      },

      // segunda Regla
      {
        test: /\.css$/,
        use: [
          {
            loader: 'style-loader'
          },
          {
            loader: 'css-loader',
            options: {
              modules: true,
              localsConvention: 'camelCase',
              sourceMap: true
            }
          }
        ]
      }
    ]
  },
};</code></pre><ul><li><a href="https://webpack.js.org/configuration/module/" rel="noopener">module</a> — Qué tipos de módulos incluirá tu aplicación, en nuestro caso soportaremos ESNext (Babel) y Módulos de CSS</li><li><a href="https://webpack.js.org/configuration/module/#module-rules" rel="noopener">rules</a> — Cómo manejamos cada distinto tipo de módulo</li></ul><h4 id="primer-regla"><strong>Primer<strong><strong> </strong></strong>Regla</strong></h4><p>Probamos archivos con una extensión <code>.js</code> excluyendo el directorio <code>node_modules</code> y usamos Babel, mediante <code>babel-loader</code>, transpilarlos a vanilla JavaScript (básicamente, buscando nuestros archivos de React).</p><p>¿Recuerdas nuestra configuración en <code>.babelrc</code>? Aquí es donde Babel mira ese archivo.</p><h4 id="segunda-regla"><strong><strong><strong>Se</strong></strong>gunda<strong><strong> </strong></strong>Regla</strong></h4><p>Testeamos archivos CSS con una extensión <code>.css</code>. Aquí usamos dos cargadores, <code>style-loader</code> y <code>css-loader</code>, para manejar nuestros archivos CSS. Luego instruimos a <code>css-loader</code> para usar <em>Módulos de CSS</em>, camel case y crear mapeos de fuente.</p><p><strong>Módulos de <strong>CSS</strong> y<strong> Camel Case</strong></strong></p><p>Esto nos da la habilidad de usar la sintaxis &nbsp;<code>import Styles from './styles.css'</code> (o destructurar así <code>import { style1, style2 } from './styles.css'</code>).</p><p>Después podemos usarlo de esta manera en una app de React:</p><pre><code class="language-js">...
&lt;div className={Style.style1}&gt;Hola Mundo&lt;/div&gt;
// o con la sintaxis de destructuración
&lt;div className={style1}&gt;Hola Mundo&lt;/div&gt;
...</code></pre><p>Camel case nos da la habilidad de escribir nuestras reglas de CSS así:</p><pre><code class="language-css">.home-button {...}</code></pre><p>Y usarlo en nuestros archivos de React de esta forma:</p><pre><code class="language-js">...
import { homeButton } from './styles.css'
...
...
module.exports = {
  ...
  plugins: [
    new HtmlWebpackPlugin({
      template: 'public/index.html',
      favicon: 'public/favicon.ico'
    })
  ],
};</code></pre><p>En esta sección es donde configuramos (como el nombre implica) plugins. </p><p><code>html-webpack-plugin</code> acepta un objeto con diferentes opciones. En nuestro caso especificamos la plantilla de HTML que estaremos usando y el favicon. (Referirse a la <a href="https://github.com/jantimon/html-webpack-plugin#configuration">docs</a> para más opciones).</p><p>Luego estaremos agregando otros plugin para el analizador de Empaquetamientos y HMR.</p><pre><code class="language-js">...
module.exports = {
  ...
  devServer: {
    host: 'localhost',
    port: port,
    historyApiFallback: true,
    open: true
  }
};</code></pre><p>Finalmente, configuramos el servidor de desarrollo. Especificamos <code>localhost</code> como el alojamiento y asignamos la variable <code>port</code> como el puerto (si recuerdas, asignamos el puerto 3000 a esta variable). Ponemos <code>historyApiFallback</code> a true y <code>open</code> a true. Esto abrirá el navegador automáticamente y lanzará tu aplicación en <a href="http://localhost:3000/">http://localhost:3000</a>. (<a href="https://webpack.js.org/configuration/dev-server/">Docs</a>).</p><p>Ahora, debajo está la configuración de Webpack completa (<code>webpack.config.js</code>):</p><pre><code class="language-js">const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const port = process.env.PORT || 3000;

module.exports = {
  mode: 'development',  
  entry: './src/index.js',
  output: {
    filename: 'bundle.[hash].js'
  },
  devtool: 'inline-source-map',
  module: {
    rules: [
      {
        test: /\.(js)$/,
        exclude: /node_modules/,
        use: ['babel-loader']
      },
      {
        test: /\.css$/,
        use: [
          {
            loader: 'style-loader'
          },
          {
            loader: 'css-loader',
            options: {
              modules: true,
              localsConvention: 'camelCase',
              sourceMap: true
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: 'public/index.html',
      favicon: 'public/favicon.ico'
    })
  ],
  devServer: {
    host: 'localhost',
    port: port,
    historyApiFallback: true,
    open: true
  }
};</code></pre><h3 id="creando-la-app-de-react"><strong>Creando la App de React</strong></h3><p>Estaremos creando una app de Hola Mundo sencilla con tres rutas: un <em>inicio</em>, una <em>página no encontrada</em> y una <em>página dinámica</em> que estaremos cargando de manera asíncrona cuando implementemos separación de código después. </p><p><strong><strong><em><em>Not</em></em></strong><em>a</em><strong><em><em>:</em></em></strong></strong><em><em> </em>Asumiendo que tienes un conocimiento básico de React y React Router, no iré en muchos detalles y solamente resaltaré lo que es más relevante para este tutorial. </em></p><p>Actualmente tenemos la siguiente estructura de proyecto:</p><pre><code>|-- node_modules
|-- .babelrc
|-- package.json
|-- webpack.config.js
|-- yarn.lock</code></pre><p>En tu terminal escribe lo siguiente:</p><pre><code class="language-bash">mkdir public &amp;&amp; cd $_
touch index.html</code></pre><p>Creamos un directorio <code>public</code>, lo movemos dentro y también creamos un archivo <code>index.html</code>. Aquí es donde también tenemos el <code>favicon</code>. Puedes tomarlo desde <a href="https://github.com/esausilva/react-starter-boilerplate-hmr/blob/master/public/favicon.ico">aquí</a> y copiarlo dentro del directorio public.</p><p>Abrimos el archivo <code>index.html</code> y copiamos lo siguiente:</p><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="es"&gt;

&lt;head&gt;
  &lt;meta charset="UTF-8"&gt;
  &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
  &lt;meta http-equiv="X-UA-Compatible" content="ie=edge"&gt;
  &lt;link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.13/semantic.min.css"&gt;&lt;/link&gt;
  &lt;title&gt;webpack-para-react&lt;/title&gt;
&lt;/head&gt;

&lt;body&gt;
  &lt;div id="root"&gt;&lt;/div&gt;
&lt;/body&gt;

&lt;/html&gt;</code></pre><p>No hay mucho aquí (solo una plantilla de HTML estándar), estamos agregando la hoja de estilos de Semantic UI y también creamos un <code>div</code> con un ID de <code>root</code>. Aquí es donde nuestra app de React renderizará.</p><p>De nuevo en tu terminal escribe lo siguiente:</p><pre><code class="language-bash">cd ..
mkdir src &amp;&amp; cd $_
touch index.js</code></pre><p>Abre <code>index.js</code> y copia lo siguiente:</p><pre><code>import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';

ReactDOM.render(&lt;App /&gt;, document.getElementById('root'));</code></pre><p>En tu terminal escribe lo siguiente:</p><pre><code class="language-bash">mkdir components &amp;&amp; cd $_
touch App.js Layout.js Layout.css Home.js DynamicPage.js NoMatch.js
</code></pre><p>Después de crear los archivos componentes de React, tenemos la siguiente estructura del proyecto: </p><pre><code>|-- node_modules
|-- public
    |-- index.html
    |-- favicon.ico
|-- src
    |-- components
        |-- App.js
        |-- DynamicPage.js
        |-- Home.js
        |-- Layout.css
        |-- Layout.js
        |-- NoMatch.js
    |-- index.js
|-- .babelrc
|-- package.json
|-- webpack.config.js
|-- yarn.lock</code></pre><p>Abre <code>App.js</code> y copia lo siguiente:</p><pre><code class="language-js">import React from 'react';
import { Switch, BrowserRouter as Router, Route } from 'react-router-dom';

import Home from './Home';
import DynamicPage from './DynamicPage';
import NoMatch from './NoMatch';

const App = () =&gt; {
  return (
    &lt;Router&gt;
      &lt;div&gt;
        &lt;Switch&gt;
          &lt;Route exact path="/" component={Home} /&gt;
          &lt;Route exact path="/dynamic" component={DynamicPage} /&gt;
          &lt;Route component={NoMatch} /&gt;
        &lt;/Switch&gt;
      &lt;/div&gt;
    &lt;/Router&gt;
  );
};

export default App;</code></pre><p>Creamos nuestro "shell" básico con React Router y tiene una <em>página</em> <em>inicio</em>, una <em>página dinámica </em>y una <em>página no encontrada</em></p><p>Abre <code>Layout.css</code> y copia lo siguiente:</p><pre><code class="language-css">.pull-right {
  display: flex;
  justify-content: flex-end;
}

.h1 {
  margin-top: 10px !important;
  margin-bottom: 20px !important;
}</code></pre><p>Abre <code>Layout.js</code> y copia lo siguiente:</p><pre><code class="language-js">import React from 'react';
import { Link } from 'react-router-dom';
import { Header, Container, Divider, Icon } from 'semantic-ui-react';

import { pullRight, h1 } from './layout.css';

const Layout = ({ children }) =&gt; {
  return (
    &lt;Container&gt;
      &lt;Link to="/"&gt;
        &lt;Header as="h1" className={h1}&gt;
          webpack-para-react
        &lt;/Header&gt;
      &lt;/Link&gt;
      {children}
      &lt;Divider /&gt;
      &lt;p className={pullRight}&gt;
        Made with &lt;Icon name="heart" color="red" /&gt; by Esau Silva
      &lt;/p&gt;
    &lt;/Container&gt;
  );
};

export default Layout;</code></pre><p>Este es nuestro componente contenedor donde definimos el diseño del sitio. Haciendo uso de los Módulos de CSS, estamos importando dos reglas de CSS desde <code>layout.css</code>. También nota cómo estamos usando <em>camel case</em> para <code>pullRight</code>.</p><p>Abre <code>Home.js</code> y copia lo siguiente:</p><pre><code class="language-js">import React from 'react';
import { Link } from 'react-router-dom';

import Layout from './Layout';

const Home = () =&gt; {
  return (
    &lt;Layout&gt;
      &lt;p&gt;Hola Mundo de React y Webpack!&lt;/p&gt;
      &lt;p&gt;
        &lt;Link to="/dynamic"&gt;Navegar a Página Dinámica&lt;/Link&gt;
      &lt;/p&gt;
    &lt;/Layout&gt;
  );
};

export default Home;</code></pre><p>Abre <code>DynamicPage.js</code> y copia lo siguiente:</p><pre><code class="language-js">import React from 'react';
import { Header } from 'semantic-ui-react';

import Layout from './Layout';

const DynamicPage = () =&gt; {
  return (
    &lt;Layout&gt;
      &lt;Header as="h2"&gt;Página Dinámica&lt;/Header&gt;
      &lt;p&gt;Esta página fue cargada asincrónicamente!!!&lt;/p&gt;
    &lt;/Layout&gt;
  );
};

export default DynamicPage;</code></pre><p>Abre <code>NoMatch.js</code> y copia lo siguiente:</p><pre><code class="language-js">import React from 'react';
import { Icon, Header } from 'semantic-ui-react';

import Layout from './Layout';

const NoMatch = () =&gt; {
  return (
    &lt;Layout&gt;
      &lt;Icon name="minus circle" size="big" /&gt;
      &lt;strong&gt;Página No Encontrada!&lt;/strong&gt;
    &lt;/Layout&gt;
  );
};

export default NoMatch;</code></pre><p>Ya terminamos de crear los componentes de React. Para un paso final antes de correr nuestra aplicación, abre <code>package.json</code> y agrega las líneas en negritas:</p><pre><code class="language-js">{
  "name": "webpack-for-react",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "start": "webpack-dev-server"
  },
  "dependencies": {
    "react": "^16.2.0",
    "react-dom": "^16.2.0",
    "prop-types": "^0.4.0",
    "react-router-dom": "^4.2.2",
    "semantic-ui-react": "^0.77.1"
  },
  "devDependencies": {
    "@babel/core": "^7.0.0",
    "@babel/plugin-proposal-class-properties": "^7.0.0",
    "@babel/plugin-syntax-dynamic-import": "^7.0.0",
    "@babel/preset-env": "^7.0.0",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.1",
    "css-loader": "^0.28.10",
    "html-webpack-plugin": "^3.0.4",
    "style-loader": "^0.19.1",
    "webpack": "^4.0.0",
    "webpack-cli": "^2.0.14",
    "webpack-dev-server": "^3.0.0"
  }
}</code></pre><p>Agregamos la clave <code>scripts</code> y también la clave <code>start</code>. Esto nos permitirá correr React con el Servidor de Desarrollo de Webpack. Si no especificas un archivo de configuración, <code>webpack-dev-server</code> buscará por el archivo <code>webpack.config.js</code> como la entrada de configuración por defecto dentro del directorio raíz. </p><p>¡Ahora el momento de la verdad! Escribe lo siguiente en tu terminal (recuerda estar en el directorio raíz) y Yarn llamará nuestro script <code>start</code>.</p><pre><code class="language-bash">yarn start</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/iHJNOlQ4O11i7ONPbmXDRkbKF7WAGqZRFcCY" class="kg-image" alt="iHJNOlQ4O11i7ONPbmXDRkbKF7WAGqZRFcCY" width="698" height="508" loading="lazy"><figcaption>Corriendo React</figcaption></figure><p>Ahora tenemos una app de React funcionando impulsado por nuestra propia configuración de Webpack. Nota que al final del GIF resalto el archivo de JavaScript empaquetado que Webpack nos generó, y como indicamos en la configuración, el nombre de archivo tiene un hash único, <code>bundle.d505bbab002262a9bc07.js</code>.</p><h3 id="configurando-el-hot-module-replacement-hmr-"><strong>Configurando el Hot Module Replacement (HMR)</strong></h3><p>De vuelta a tu terminal, instala <a href="https://github.com/gaearon/react-hot-loader">React Hot Loader</a> como una dependencia de desarrollo.</p><pre><code class="language-bash">yarn add react-hot-loader @hot-loader/react-dom -D</code></pre><p>Abre <code>.babelrc</code> y agregar líneas 3 y 9. No te olvides de incluir la coma (,) al final de la línea 3: &nbsp;</p><pre><code class="language-json">{
  "presets": [
    ["@babel/preset-env", { "modules": false }],
    "@babel/preset-react"
  ],
  "plugins": [
    "@babel/plugin-syntax-dynamic-import",
    "@babel/plugin-proposal-class-properties",
    "react-hot-loader/babel"
  ]
}</code></pre><p>Abre <code>webpack.config.js</code> y modíficalo como abajo.</p><p><em>Estoy incluyendo solamente el código relevante y omitiendo código que permaneció igual por la brevedad.</em></p><pre><code class="language-js">...
module.exports = {
  entry: './src/index.js',
  output: {
    ...
    publicPath: '/'
  },
  resolve: {
    alias: {
      "react-dom": "@hot-loader/react-dom",
    },
  },
  ...
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    ...
  ],
  devServer: {
    ...
    hot: true
  }
};</code></pre><ul><li><code>publicPath: ‘/’</code> — La Recarga rápida &nbsp;no funcionará como se espera para las rutas anidadas sin él</li><li><code>webpack.HotModuleReplacementPlugin</code> — Imprime más nombres de módulo legibles en la terminal del navegador en las actualizaciones de HMR</li><li><code>hot: true</code> — Permite HMR en el servidor</li><li><code>resolve: alias</code> — reemplaza <code>react-dom</code> con el <code>react-dom</code> personalizado de <code>hot-loader</code></li></ul><p>Abre <code>index.js</code> y cámbialo a lo siguiente.</p><pre><code class="language-js">import { hot } from "react-hot-loader/root";
import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";

import "./index.css";

const render = (Component) =&gt;
  ReactDOM.render(&lt;Component /&gt;, document.getElementById("root"));

render(hot(App));</code></pre><p>Ahora estamos listos para probar HMR! Devuelta en la terminal, ejecuta tu app, haz un cambio, y observa como la app se actualiza sin un refresco de toda la página.</p><pre><code class="language-bash">yarn start</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/tBaz3tT6Vsnxk7ijy1xFl03YFWmktaaktUWH" class="kg-image" alt="tBaz3tT6Vsnxk7ijy1xFl03YFWmktaaktUWH" width="698" height="655" loading="lazy"><figcaption>HMR en acción</figcaption></figure><p>Después de actualizar el archivo, la página cambia sin un refreso completo. Para mostrar este cambio en el navegador selecciono <strong>Rendering</strong> <strong>-&gt;</strong> <strong>Paint flashing</strong> en el DevTools de Chrome, el cual resalta las áreas de la página, en verde, que cambiaron. También resalto en la terminal el cambio que Webpack envió al navegador para que esto suceda.</p><h3 id="separaci-n-de-c-digo"><strong>Separación de Código</strong></h3><p>Con <a href="https://webpack.js.org/guides/code-splitting/">separación de código</a>, en vez de tener tu aplicación en un sólo paquete grande, puedes tener múltiples paquetes cada uno cargando asincrónicamente o en paralelo. También puedes separar código de proveedor del código de tu aplicación que puede decrecer potencialmente el tiempo de carga.</p><h4 id="por-ruta"><strong>Por Ruta</strong></h4><p>Hay muchas maneras que podemos lograr separación de código por ruta, sin embargo en nuestro caso estaremos usando <a href="https://github.com/theKashey/react-imported-component" rel="noopener">react-imported-component</a>.</p><p>También nos gustaría mostrar un <em>carga giratoria</em> cuando el usuario navegue a una ruta diferente. Este es una buena práctica ya que no queremos que el usuario sólo se quede mirando una pantalla en blanco mientras él/ella espera que la nueva página se cargue. Así que, estaremos creando a componente <em>Loading</em>.</p><p>Sin embargo, si la nueva página carga realmente rápido, no queremos que el usuario vea una carga giratoria parpadeante por un par de milisegundos, así que retrasaremos el componente <em>Loading</em> por 300 milisegundos. Para lograr esto, estaremos usando <a href="https://github.com/arnthor3/react-delay-render" rel="noopener">React-Delay-Render</a>.</p><p>Empieza por intsalar las dos dependencias adicionales.</p><p>En tu terminal escribe lo siguiente:</p><pre><code class="language-bash">yarn add react-imported-component react-delay-render</code></pre><p>Ahora vamos a crear el componente <em>Loading</em>.</p><p>En tu terminal escribe lo siguiente:</p><pre><code class="language-bash">touch ./src/components/Loading.js</code></pre><p>Abre <code>Loading.js</code> y copia lo siguiente:</p><pre><code class="language-js">import React from 'react';
import { Loader } from 'semantic-ui-react';
import ReactDelayRender from 'react-delay-render';

const Loading = () =&gt; &lt;Loader active size="massive" /&gt;;

export default ReactDelayRender({ delay: 300 })(Loading);</code></pre><p>Ahora que tenemos el componente <em>Loading</em>, abre <code>App.js</code> y modifícalo como sigue:</p><pre><code class="language-js">import React from 'react';
import { Switch, BrowserRouter as Router, Route } from 'react-router-dom';
import importedComponent from 'react-imported-component';

import Home from './Home';
import Loading from './Loading';

const AsyncDynamicPAge = importedComponent(
  () =&gt; import(/* webpackChunkName:'DynamicPage' */ './DynamicPage'),
  {
    LoadingComponent: Loading
  }
);
const AsyncNoMatch = importedComponent(
  () =&gt; import(/* webpackChunkName:'NoMatch' */ './NoMatch'),
  {
    LoadingComponent: Loading
  }
);

const App = () =&gt; {
  return (
    &lt;Router&gt;
      &lt;div&gt;
        &lt;Switch&gt;
          &lt;Route exact path="/" component={Home} /&gt;
          &lt;Route exact path="/dynamic" component={AsyncDynamicPAge} /&gt;
          &lt;Route component={AsyncNoMatch} /&gt;
        &lt;/Switch&gt;
      &lt;/div&gt;
    &lt;/Router&gt;
  );
};

export default App;</code></pre><p>Esto creará tres paquetes, o trozos, uno para el componente <code>DynamicPage</code>, uno para el componente <code>NoMatch</code>, y uno para la app principal.</p><p>También cambiemos el nombre del archivo del paquete. Abre <code>webpack.config.js</code> y cámbialo como sigue:</p><pre><code class="language-js">...
module.exports = {
  ...
  output: {
    filename: '[name].[hash].js',
    ...
  },
}</code></pre><p>Es tiempo de ejecutar la app y ver la separación de código por ruta en acción.</p><pre><code class="language-bash">yarn start</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/dNGa5cqDKitNHQAKtH7ZDce3fvrCCWuE1zYh" class="kg-image" alt="dNGa5cqDKitNHQAKtH7ZDce3fvrCCWuE1zYh" width="698" height="684" loading="lazy"><figcaption>Separación de Código por Ruta</figcaption></figure><p>En el GIF, primero resalto los tres diferentes pedazos creados por Webpack en la terminal. Luego resalto que sobre el lanzamiento de la app, solamente el pedazo principal fue cargado. Finalmente, vemos que sobre clickear <em>Navigate</em> a <em>Dynamic Page</em> el pedazo correspondiente a esta página fue cargada asincrónicamente.</p><p>También vemos que el pedazo correspondiente a la página <em>no encontrada</em> nunca fue cargado, ahorrando el ancho de banda del usuario.</p><h4 id="por-proveedor"><strong>Por proveedor</strong></h4><p>Ahora separemos la aplicación por proveedor. Abre <code>webpack.config.js</code> y haz los siguientes cambios:</p><pre><code class="language-js">...
module.exports = {
  entry: {
    vendor: ['semantic-ui-react'],
    app: './src/index.js'
  },
  ...
  optimization: {
    splitChunks: {
      cacheGroups: {
        styles: {
          name: 'styles',
          test: /\.css$/,
          chunks: 'all',
          enforce: true
        },
        vendor: {
          chunks: 'initial',
          test: 'vendor',
          name: 'vendor',
          enforce: true
        }
      }
    }
  },
  ...
};</code></pre><ul><li><code>entry.vendor: [‘semantic-ui-react’]</code> — Especifica qué librería queremos extraer de nuestra app principal </li><li><code>optimization </code>— si dejas esta entrada en blanco, Webpack aún separará tu aplicación por proveedor (vendor), sin embargo he notado que los tamaños de los empaquetados eran grandes y después de agregar esta entrada, los tamaños de los empaquetados redujeron significativamente. (Lo conseguí de <a href="https://github.com/webpack/webpack/issues/6357" rel="noopener">Webpack 4 migration draft</a> <em><em>CommonsChunkPlugin -&gt; Initial vendor ch</em></em>unk)</li></ul><p><strong><strong><em><em>Not</em></em></strong><em>a</em><strong><em><em>:</em></em></strong></strong><em><em> </em>Previamente Webpack 3 hizo uso de<em> <code>CommonsChunkPlugin</code> </em>para separar el código por vendor y/o comunes, sin embargo quedó obsoleto en Webpack 4 y muchas de sus características ahora están disponibles por defecto. Con el retiro de<em> <code>CommonsChunkPlugin</code> </em>han agregado<em> <code>optimization.splitChunks</code> </em>para aquellos que necesitan control detallado sobre su estrategia de caching <em>(</em>Ver<em> </em><a href="https://gist.github.com/sokra/1522d586b8e5c0f5072d7565c2bee693">esto</a><em> </em>para una explicación en profundidad<em>).</em></em></p><p>En la terminal, lanza la app:</p><pre><code class="language-bash">yarn start</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/L5D5dDH3r5DkNfhN2oilt1BaejnhCYfpdnQw" class="kg-image" alt="L5D5dDH3r5DkNfhN2oilt1BaejnhCYfpdnQw" width="698" height="684" loading="lazy"><figcaption>Separación de Código por Vendor</figcaption></figure><p>En la terminal, resalto los tres pedazos previos mas el nuevo pedazo <em>vendor</em>. Después cuando inspeccionamos el HTML vemos que tanto como los pedazos vendor y app fueron cargados.</p><p>Siendo que hemos hechos varias actualizaciones a nuestra configuración de Webpack, debajo encontrarás el archivo <code>webpack.config.js</code> completo.</p><pre><code class="language-js">const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const port = process.env.PORT || 3000;
module.exports = {
  mode: 'development',
  entry: {
    vendor: ['semantic-ui-react'],
    app: './src/index.js'
  },
  output: {
    filename: '[name].[hash].js'
  },
  resolve: {
    alias: {
      "react-dom": "@hot-loader/react-dom",
    },
  },
  devtool: 'inline-source-map',
  module: {
    rules: [
      {
        test: /\.(js)$/,
        exclude: /node_modules/,
        use: ['babel-loader']
      },
      {
        test: /\.css$/,
        use: [
          {
            loader: 'style-loader'
          },
          {
            loader: 'css-loader',
            options: {
              modules: true,
              localsConvention: 'camelCase',
              sourceMap: true
            }
          }
        ]
      }
    ]
  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        styles: {
          name: 'styles',
          test: /\.css$/,
          chunks: 'all',
          enforce: true
        },
        vendor: {
          chunks: 'initial',
          test: 'vendor',
          name: 'vendor',
          enforce: true
        }
      }
    }
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new HtmlWebpackPlugin({
      template: 'public/index.html',
      favicon: 'public/favicon.ico'
    })
  ],
  devServer: {
    host: 'localhost',
    port: port,
    historyApiFallback: true,
    open: true,
    hot: true
  }
};</code></pre><h3 id="configuraci-n-de-producci-n"><strong>Configuración de Producción</strong></h3><p>Renombrar la configuración de Webpack de <code>webpack.config.js</code> a <code>webpack.config.<strong>development</strong>.js</code>. Luego haz una copia y nómbralo <code>webpack.config.<strong>production</strong>.js</code>.</p><p>En tu terminal escribe lo siguiente:</p><pre><code class="language-bash">mv webpack.config.js webpack.config.development.js
cp webpack.config.development.js webpack.config.production.js</code></pre><p>Necesitaremos una dependencia de desarrollo, el <a href="https://github.com/webpack-contrib/extract-text-webpack-plugin">Plugin de Extracción de Texto</a>. De su documentación: "Mueve todos los módulos <code>*.css</code> requeridos en pedazos de entrada en un archivo de CSS aparte. Así que, tus estilos ya no están alineados en el empaquetado de JS, sino que están en un archivo de CSS aparte (<code>styles.css</code>). Si el volumen de tu hoja de estilos es grande, será más rápido porque el empaquetado de CSS se carga en paralelo junto al empaquetado de JS."</p><p>En tu terminal escribe lo siguiente:</p><pre><code class="language-bash">yarn add mini-css-extract-plugin -D</code></pre><p>Abre <code>webpack.config.production.js</code> y haz los siguientes cambios en negrita:</p><p><em>Haciendo algo diferente acá<em>…</em> Agregaré explicaciones<em> </em>con comentarios en línea<em>.</em></em></p><pre><code class="language-js">const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
  mode: 'production',
  entry: {
    vendor: ['semantic-ui-react'],
    app: './src/index.js'
  },
  output: {
    // Queremos crear los empaquetados de JavaScript en un 
    // directorio 'static'
    filename: 'static/[name].[hash].js',
    // El Absolute path al directorio de salida deseado. En nuestro 
    // caso un directorio llamado 'dist'
    // '__dirname' es una variable de Node que nos da el camino
    // absoluto a nuestro directorio actual. Luego con 'path.resolve'
    // unimos los directorios
    // Webpack 4 asume que tu camino de salida será './dist' así que
    // puedes dejar esta entrada como está.
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/'
  },
  // Cambia a mapeos de fuente de producción
  devtool: 'source-map',
  module: {
    rules: [
      {
        test: /\.(js)$/,
        exclude: /node_modules/,
        use: ['babel-loader']
      },
      {
        test: /\.css$/,
          use: [
            {
              // Configuramos 'MiniCssExtractPlugin'              
              loader: MiniCssExtractPlugin.loader,
            }, 
            {
              loader: 'css-loader',
              options: {
                modules: true,
                // Permite configurar cuántos loaders 
                // deberían ser aplicados antes de css-loader
                // a los recursos @import(ados)
                importLoaders: 1,
                localsConvention: 'camelCase',
                // Crear los mapeos de fuente para los archivos de CSS
                sourceMap: true
              }
            },
            {
              // PostCSS se ejecutará antes del css-loader y
              // minificará y autoprefijará nuestras reglas de CSS.
              loader: 'postcss-loader',
            }
          ]
      }
    ]
  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        styles: {
          name: 'styles',
          test: /\.css$/,
          chunks: 'all',
          enforce: true
        },
        vendor: {
          chunks: 'initial',
          test: 'vendor',
          name: 'vendor',
          enforce: true
        }
      }
    }
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: 'public/index.html',
      favicon: 'public/favicon.ico'
    }),
    
    // Crea la hoja de estilo en el directorio 'styles'
    new MiniCssExtractPlugin({
      filename: 'styles/styles.[hash].css'
    })
  ]
};</code></pre><p>Nota que removimos la variable <code>port</code>, los plugins relacionados a HMR y la entrada <code>devServer</code>.</p><p>También, desde que agregamos PostCSS a la configuración de producción, necesitamos instalarlo y crearle un archivo de configuración.</p><p>En tu terminal escribe lo siguiente:</p><pre><code class="language-bash">yarn add postcss-loader autoprefixer cssnano postcss-preset-env -D
touch postcss.config.js</code></pre><p>Abre <code>postcss.config.js</code> y copia lo siguiente:</p><pre><code class="language-js">const postcssPresetEnv = require('postcss-preset-env');
module.exports = {
  plugins: [
    postcssPresetEnv({
      browsers: ['&gt;0.25%', 'not ie 11', 'not op_mini all']
    }),
    require('cssnano')
  ]
};</code></pre><p>Aquí estamos especificando qué navegadores queremos que <code>autoprefixer</code> (referirse a las <a href="https://webpack.js.org/loaders/postcss-loader/">docs</a> para más opciones) soporte y minificar la salida de CSS.</p><p>Ahora, para el último paso, antes de crear nuestra construcción de producción, necesitamos crear un script <em>build</em> en el <code>package.json</code>.</p><p>Abre el archivo y haz los siguientes cambios a la sección <code>scripts</code>:</p><pre><code class="language-json">...
"scripts": {
  "dev":"webpack-dev-server --config webpack.config.development.js",
  "prebuild": "rimraf dist",
  "build": "cross-env NODE_ENV=production webpack -p --config webpack.config.production.js"
},
...</code></pre><p>Lo primero en notar aquí es que cambiamos el script de <code>start</code> a <code>dev</code>, luego agregamos dos scripts adicionales, <code>prebuild</code> y <code>build</code>.</p><p>Finalmente, estamos indicando qué configuración usar cuando esté en desarrollo o en producción. </p><ul><li><code>prebuild</code> — se ejecutará antes del script build y eliminará la carpeta <code>dist</code> creado por nuestra última construcción de producción. Usamos la librería <a href="https://github.com/isaacs/rimraf" rel="noopener">rimraf</a> para esto.</li><li><code>build</code> — Primero usamos la librería <a href="https://github.com/kentcdodds/cross-env" rel="noopener">cross-env</a> sólo en caso de que alguien esté usando Windows. De esta manera, configurar variables de entorno con <code>NODE_ENV</code> funcionará. Después llamamos a Webpack con la bandera <code>-p</code> para decirle que optimice ésta construcción para producción, y finalmente especificamos la configuración de producción.</li></ul><p>En tu terminal instala las dos nuevas dependencias que incluimos en el <code>package.json</code>:</p><pre><code class="language-bash">yarn add rimraf cross-env -D</code></pre><p>Antes de crear la construcción de producción, miremos nuestra nueva estructura del proyecto:</p><pre><code>|-- node_modules
|-- public
    |-- index.html
    |-- favicon.ico
|-- src
    |-- components
        |-- App.js
        |-- DynamicPage.js
        |-- Home.js
        |-- Layout.css
        |-- Layout.js
        |-- Loading.js
        |-- NoMatch.js
    |-- index.js
|-- .babelrc
|-- package.json
|-- postcss.config.js
|-- webpack.config.development.js
|-- webpack.config.production.js
|-- yarn.lock</code></pre><p>Ahora sí podemos crear nuestro empaquetado de producción.</p><p>En tu terminal escribe lo siguiente:</p><pre><code class="language-bash">yarn build</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/T81PYokNYP1m76WiEbGipkFrmGYKee46P4IR" class="kg-image" alt="T81PYokNYP1m76WiEbGipkFrmGYKee46P4IR" width="698" height="238" loading="lazy"><figcaption>Empaquetado de la construcción a producción</figcaption></figure><p>Como haz notado, después que ejecutamos el script <code>build</code>, Webpack creó una carpeta <code>dist</code> conteniendo nuestra app lista para producción. Ahora inspecciona los archivos que fueron creados y nota que están minificados y cada uno tiene un mapeo de fuente correspondiente. También notarás que PostCSS ha agregado autoprefijado al archivo de CSS. </p><p>Ahora tomamos nuestros archivos de producción y encendemos un servidor de Node para servir nuestro sitio, y este es el resultado:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/A44vaXq-Jc68ClNMgWe5O0o4a3XjIfj3XLrU" class="kg-image" alt="A44vaXq-Jc68ClNMgWe5O0o4a3XjIfj3XLrU" width="698" height="481" loading="lazy"><figcaption>Ejecutando la construcción de producción</figcaption></figure><p><strong><strong><em><em>Not</em></em></strong><em>a</em><strong><em><em>:</em></em></strong></strong><em><em> </em>Estoy usando<em> </em><a href="https://github.com/esausilva/quick-node-server">este servidor</a><em> </em>en el<em> GIF </em>de arriba<em> </em>para servir<em> </em>nuestros archivos de producción<em>.</em></em></p><p>En este punto tenemos dos configuraciones de Webpack funcionando, uno para desarrollo y uno para producción. Sin embargo, ya que ambas configuraciones son muy similares, comparten muchas de las mismas configuraciones. Si queremos agregar algo más, tendríamos que agregarlo a ambos archivos de configuración.</p><h3 id="composici-n-de-webpack"><strong>Composición de Webpack</strong></h3><p>Empecemos instalando <a href="https://github.com/survivejs/webpack-merge" rel="noopener">webpack-merge</a> y <a href="https://github.com/chalk/chalk" rel="noopener">Chalk</a> como dependencias de desarrollo.</p><p>En tu terminal escribe lo siguiente:</p><pre><code class="language-bash">yarn add webpack-merge chalk -D</code></pre><p>También necesitaremos un par de nuevas carpetas y unos pocos archivos nuevos.</p><p>En tu terminal escribe lo siguiente:</p><pre><code class="language-bash">mkdir -p build-utils/addons
cd build-utils
touch build-validations.js common-paths.js webpack.common.js webpack.dev.js webpack.prod.js</code></pre><p>Ahora miremos nuestra nueva estructura de proyecto:</p><pre><code class="language-js">|-- build-utils
    |-- addons
    |-- build-validations.js
    |-- common-paths.js
    |-- webpack.common.js
    |-- webpack.dev.js
    |-- webpack.prod.js
|-- node_modules
|-- public
    |-- index.html
    |-- favicon.ico
|-- src
    |-- components
        |-- App.js
        |-- DynamicPage.js
        |-- Home.js
        |-- Layout.css
        |-- Layout.js
        |-- Loading.js
        |-- NoMatch.js
    |-- index.js
|-- .babelrc
|-- package.json
|-- postcss.config.js
|-- webpack.config.development.js
|-- webpack.config.production.js
|-- yarn.lock</code></pre><p>Abre <code>common-paths.js</code> y copia lo siguiente:</p><pre><code>const path = require('path');
const PROJECT_ROOT = path.resolve(__dirname, '../');

module.exports = {
  projectRoot: PROJECT_ROOT,
  outputPath: path.join(PROJECT_ROOT, 'dist'),
  appEntry: path.join(PROJECT_ROOT, 'src')
};</code></pre><p>Aquí definimos, como el nombre lo implica, los caminos comúnes para nuestras configuraciones de Webpack. <code>PROJECT_ROOT</code> necesita buscar una carpeta ya que estamos trabajando en la carpeta <code>build-utils</code> (un nivel menos del camino raíz actual de nuestro proyecto).</p><p>Abre <code>build-validations.js</code> y copia lo siguiente:</p><pre><code class="language-js">const chalk = require('chalk');
const ERR_NO_ENV_FLAG = chalk.red(
  `Debes pasar una bandera --env.env en tu construcción a webpack para que funcione!`
);

module.exports = {
  ERR_NO_ENV_FLAG
};</code></pre><p>Luego, cuando modifiquemos nuestro <code>package.json</code> estaremos requiriendo la bandera <code>--env.env</code> en los scripts. Estas validaciones están para verificar que la bandera esté presente; si no, lanzará un error. &nbsp;</p><p>En los tres archivos próximos, estaremos separando las configuraciones de Webpack en configuraciones que son compartidas entre desarrollo y producción, configuraciones que son solamente para desarrollo y configuraciones solamente para producción. </p><p>Abre <code>webpack.common.js</code> y copia lo siguiente:</p><pre><code class="language-js">const commonPaths = require('./common-paths');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const config = {
  entry: {
    vendor: ['semantic-ui-react']
  },
  output: {
    path: commonPaths.outputPath,
    publicPath: '/'
  },
  module: {
    rules: [
      {
        test: /\.(js)$/,
        exclude: /node_modules/,
        use: ['babel-loader']
      }
    ]
  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        styles: {
          name: 'styles',
          test: /\.css$/,
          chunks: 'all',
          enforce: true
        },
        vendor: {
          chunks: 'initial',
          test: 'vendor',
          name: 'vendor',
          enforce: true
        }
      }
    }
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: 'public/index.html',
      favicon: 'public/favicon.ico'
    })
  ]
};
module.exports = config;</code></pre><p>Básicamente extraímos lo que fue compartido entre <code>webpack.config.development.js</code> y <code>webpack.config.production.js</code> y lo transferimos a este archivo. En la parte de arriba requerimos <code>common-paths.js</code> para establecer el <code>output.path</code>.</p><p>Abre <code>webpack.dev.js</code> y copia lo siguiente:</p><pre><code class="language-js">const commonPaths = require('./common-paths');
const webpack = require('webpack');
const port = process.env.PORT || 3000;
const config = {
  mode: 'development',
  entry: {
    app: `${commonPaths.appEntry}/index.js`
  },
  output: {
    filename: '[name].[hash].js'
  },
  resolve: {
    alias: {
      "react-dom": "@hot-loader/react-dom",
    },
  },
  devtool: 'inline-source-map',
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: 'style-loader'
          },
          {
            loader: 'css-loader',
            options: {
              modules: true,
              localsConvention: 'camelCase',
              sourceMap: true
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ],
  devServer: {
    host: 'localhost',
    port: port,
    historyApiFallback: true,
    hot: true,
    open: true
  }
};
module.exports = config;</code></pre><p>Este es el mismo concepto como en el archivo previo. Aquí extrajimos configuraciones de desarrollo solamente.</p><p>Abre <code>webpack.prod.js</code> y copia lo siguiente:</p><pre><code class="language-js">const commonPaths = require('./common-paths');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const config = {
  mode: 'production',
  entry: {
    app: [`${commonPaths.appEntry}/index.js`]
  },
  output: {
    filename: 'static/[name].[hash].js'
  },
  devtool: 'source-map',
  module: {
    rules: [
      {
        test: /\.css$/,
          use: [
            {
              // Configuramos 'MiniCssExtractPlugin'              
              loader: MiniCssExtractPlugin.loader,
            }, 
            {
              loader: 'css-loader',
              options: {
                modules: true,
                importLoaders: 1,
                localsConvention: 'camelCase',
                sourceMap: true
              }
            },
            {
              loader: 'postcss-loader'
            }
          ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'styles/styles.[hash].css'
    })
  ]
};
module.exports = config;</code></pre><p>Extrajimos las configuraciones de producción solamente.</p><p>Ahora que tenemos las configuraciones compartidas y las que son específicas para desarrollo y producción en archivos separados, es tiempo de poner todo junto.</p><p>En la terminal, si estás todavía en la carpeta <code>build-utils</code>, ve un nivel arriba a la raíz del proyecto, luego elimina las configuraciones de Webpack previas y crea una nueva configuración de Webpack. Llámalo <code>webpack.config.js</code>.</p><p>En tu terminal escribe lo siguiente:</p><pre><code class="language-bash">cd ..
rm webpack.config.development.js webpack.config.production.js
touch webpack.config.js</code></pre><p>Antes de configurar <code>webpack.config.js</code>, abramos <code>package.json</code> y actualicemos la sección de <code>scripts</code>.</p><p>Modificar la sección de la siguiente manera:</p><pre><code class="language-js">...
"scripts": {
  "dev": "webpack-dev-server --env.env=dev",
  "prebuild": "rimraf dist",
  "build": "cross-env NODE_ENV=production webpack -p --env.env=prod"
},
...</code></pre><p>Ya que removimos la bandera <code>--config</code>, Webpack ahora estará buscando la configuración por defecto, el cual es <code>webpack.config.js</code>. Ahora usamos la bandera &nbsp;<a href="https://webpack.js.org/guides/environment-variables/" rel="noopener">–env</a> para pasar una variable de entorno a Webpack, <code>env=dev</code> para desarrollo y<code>env=prod</code> para producción.</p><p>Abre <code>webpack.config.js</code> y copia lo siguiente:</p><p><em>Explicaciones<em> </em>con comentarios en línea<em>.</em></em></p><pre><code class="language-js">const buildValidations = require('./build-utils/build-validations');
const commonConfig = require('./build-utils/webpack.common');

const webpackMerge = require('webpack-merge');

// Podemos incluir plugins de Webpack, a través de complementos, que
// no necesitan ejecutarse cada vez que estemos desarrollando.
// Veremos un ejemplo cuando configuremos 'Analizador de Paquetes'
const addons = (/* string | string[] */ addonsArg) =&gt; {
  
  // Normalizar el arreglo addons (flatten)
  let addons = [...[addonsArg]] 
    .filter(Boolean); // Si los complementos son undefined, los filtramos

  return addons.map(addonName =&gt;
    require(`./build-utils/addons/webpack.${addonName}.js`)
  );
};

// 'env' contendrá la variable de entorno de la sección 'scripts' 
// en el 'package.json'.
// console.log(env); =&gt; { env: 'dev' }
module.exports = env =&gt; {

  // Usamos 'buildValidations' para verificar la bandera 'env'
  if (!env) {
    throw new Error(buildValidations.ERR_NO_ENV_FLAG);
  }

  // Seleccionar qué configuración de Webpack usar: desarrollo
  // o producción
  // console.log(env.env); =&gt; dev
  const envConfig = require(`./build-utils/webpack.${env.env}.js`);
  
  // 'webpack-merge' combinará nuestras configuraciones compartidas, 
  // las configuraciones específicas de entorno y cualquier complemento
  // que estemos incluyendo
  const mergedConfig = webpackMerge(
    commonConfig,
    envConfig,
    ...addons(env.addons)
  );

  // Luego devolver la configuración final para Webpack
  return mergedConfig;
};</code></pre><p>Ahora, esto podría parecer un montón de configuraciones, pero a la larga, se volverá práctico.</p><p>En este momento, puedes lanzar la aplicación o construir los archivos para producción, y todo funcionará como se espera (disculpa, no hay GIF esta vez).</p><pre><code class="language-bash">yarn dev
yarn build</code></pre><p><strong><strong><em><em>Not</em></em></strong><em>a</em><strong><em><em>:</em></em></strong></strong><em><em> </em>Esta técnica de<em> “Composi</em>ción de <em>Webpack” </em>fue tomado de<em> <a href="https://webpack.academy/" rel="noopener">Webpack Academy</a>, </em>un curso gratis<em> </em>por<em> Sean Larkin </em>el cual recomiendo para aprender más sobre<em> Webpack, </em>no específico a React<em>.</em></em></p><h3 id="bonus-configurar-el-analizador-de-paquetes-de-webpack"><strong>BONUS: Configurar el Analizador de Paquetes de Webpack </strong></h3><p>No necesitas necesariamente <a href="https://github.com/webpack-contrib/webpack-bundle-analyzer">Analizador de Paquetes de Webpack</a>, pero viene muy bien cuando intentas optimizar tus construcciones.</p><p>Empieza instalando la dependencia y crea el archivo de configuración.</p><p>En tu terminal escribe lo siguiente:</p><pre><code class="language-bash">yarn add webpack-bundle-analyzer -D
touch build-utils/addons/webpack.bundleanalyzer.js</code></pre><p>Abre <code>webpack.bundleanalyzer.js</code> y copia lo siguiente:</p><pre><code class="language-js">const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
  .BundleAnalyzerPlugin;

module.exports = {
  plugins: [
    new BundleAnalyzerPlugin({
      analyzerMode: 'server'
    })
  ]
};</code></pre><p>Estamos sólo exportando la sección de plugins, el cual incluye el Analizador de Paquetes, para Webpack. Luego <code>webpack-merge</code> lo combinará en la configuración de Webpack final. ¿Recuerdas los<em> complementos</em> en <code>webpack.config.js</code>? Bueno, aquí es donde entra en acción.</p><p>Para el paso final, abramos <code>package.json</code> e incluyamos los nuevos scripts de la siguiente manera:</p><pre><code class="language-json">"scripts": {
  "dev": "webpack-dev-server --env.env=dev",
  "dev:bundleanalyzer": "yarn dev --env.addons=bundleanalyzer",
  "prebuild": "rimraf dist",
  "build": "cross-env NODE_ENV=production webpack -p --env.env=prod",
  "build:bundleanalyzer": "yarn build --env.addons=bundleanalyzer"
},</code></pre><ul><li><code>dev:bundleanalyzer</code> — Llama el script <code>dev</code> y pasa una nueva variable de entorno <code>addons=bundleanalyzer</code></li><li><code>build:bundleanalyzer</code> — Llama el script <code>build</code> y pasa una nueva variable de entorno <code>addons=bundleanalyzer</code></li></ul><p>Es tiempo de correr la app con el complemento de Analizador de Paquetes.</p><p>En tu terminal escribe lo siguiente:</p><pre><code class="language-bash">yarn dev:bundleanalyzer</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/EFwowawQtLlHdJQGL9gwuz77O2wfhz784xW2" class="kg-image" alt="EFwowawQtLlHdJQGL9gwuz77O2wfhz784xW2" width="698" height="481" loading="lazy"><figcaption>Analizador de Paquetes de Webpack</figcaption></figure><p>La aplicación se lanza junto al Analizador de Paquetes de Webpack. </p><p>Incluir complementos con la Composición de Webpack pude ser muy útil, ya que hay muchos plugins que querrías usar solamente en ciertas ocasiones.</p><h3 id="conclusi-n"><strong>Conclusión</strong></h3><p>Primero de todo, puedes obtener el código completo en el <a href="https://github.com/esausilva/react-starter-boilerplate-hmr">repositorio de Github</a>.</p><p>Bueno, llegaste al final. ¡Felicidades! Ahora que sabes las bases (y un poquito más) de Webpack para React, puedes continuar y seguir explorando y aprendiendo características y técnicas más avanzadas.</p><p>Gracias por leer y espero que lo hayas disfrutado. Si tienes cualquier pregunta, sugerencia o correcciones, házmelos saber en los comentarios abajo. No te olvides de compartir este artículo y ¿dar algunos aplausos??</p><p>Me puedes seguir aquí en <a href="https://medium.com/@_esausilva" rel="noopener">Medium</a>, <a href="https://twitter.com/_esausilva" rel="noopener">Twitter</a>, <a href="https://github.com/esausilva/" rel="noopener">GitHub</a>, <a href="https://www.linkedin.com/in/esausilva/" rel="noopener">LinkedIn</a> o todos ellos.</p><p>Este artículo fue publicado originalmente en mi sitio web de <a href="https://esausilva.com/2018/01/13/learn-webpack-for-react/">blog personal</a>.</p><hr><p><strong><u>Actualización</u><strong><u> 8/25/19:</u></strong></strong> He estado construyendo una aplicación web de oraciones llamado "<strong>Mi Tiempo Tranquilo<strong> - </strong>Una Oración Diara</strong>". Si te gustaría estar al tanto por favor regístrate a través del siguiente link: <a href="http://b.link/mqt" rel="noopener noreferrer">http://b.link/mqt</a></p><p>Mis Mensajes Directos en <a href="https://twitter.com/_esausilva" rel="noopener">Twitter</a> están abiertos si tienes alguna pregunta respecto a la app.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Cómo compartir variables en HTML, CSS, y JavaScript usando Webpack ]]>
                </title>
                <description>
                    <![CDATA[ A principios de esta semana, leí un artículo que explica cómo CSS-in-JS ralentiza la representación de algunas aplicaciones React y cómo el CSS estático es más rápido. Pero CSS-in-JS es muy popular porque, entre otras características, puede diseñar dinámicamente usando variables de JavaScript. En este tutorial, te mostraré cómo recrear ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/como-compartir-variables-en-html-y-javascript-usando-webpack/</link>
                <guid isPermaLink="false">5fff7d2ea4e0700982a9d673</guid>
                
                    <category>
                        <![CDATA[ Webpack ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Andrea Carvajal López ]]>
                </dc:creator>
                <pubDate>Wed, 14 Apr 2021 05:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2021/04/4kzz7px14mtv34rcfp73-1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A principios de esta semana, leí un artículo que explica cómo CSS-in-JS ralentiza la representación de algunas aplicaciones React y cómo el CSS estático es más rápido. Pero CSS-in-JS es muy popular porque, entre otras características, puede diseñar dinámicamente usando variables de JavaScript.</p><p>En este tutorial, te mostraré cómo recrear este beneficio en cualquiera de tus proyectos web gracias a Webpack (y supongo que sabes cómo usarlo). Para empezar, queremos que Webpack agrupe nuestros archivos fuente en una carpeta <code>dist/</code> estática.</p><p><a href="https://glitch.com/~shared-variables-webpack"></a><a href="https://glitch.com/~shared-variables-webpack">P</a>uedes revisar el código fuente aquí.</p><h2 id="1-configura-nuestra-aplicaci-n"><strong>1. Configura nuestra aplicación</strong></h2><h3 id="la-parte-aburrida"><strong>La parte aburrida</strong></h3><p>Crea una carpeta para este tutorial, abre tu terminal, e inicia un proyecto:</p><pre><code>npm init -y
</code></pre><p>Lo primero es lo primero, si aún no está hecho, instala <a href="https://nodejs.org/en/">node.js</a> y <a href="https://webpack.js.org/">Webpack</a>:</p><pre><code>npm install webpack webpack-cli --save-dev
</code></pre><p>Vamos a crear un script en nuestro <code>package.json</code> que le dice a Webpack que use nuestro archivo de configuración:</p><pre><code class="language-json">  "scripts": {
    "build": "webpack --config webpack.config.js"
  }
</code></pre><p>En la root de tu carpeta, cree un archivo <code>globals.js</code>, donde nuestras variables serán guardadas:</p><pre><code class="language-javascript">module.exports = {
  myTitle: 'Hello freeCodeCamp!',
  myColor: '#42ff87',
};
</code></pre><p>El archivo de configuración de Webpack se ve así (<code>webpack.config.js</code>). Créelo en el root de tu carpeta:</p><pre><code class="language-javascript">module.exports = {
  entry: __dirname + '/app/index.js',
  output: {
    path: __dirname + '/dist',
    filename: 'index_bundle.js'
  },
};
</code></pre><p>Nuestro código fuente estará ubicado en una carpeta <code>app</code>. Créelo de esta forma:</p><pre><code>mkdir app &amp;&amp; cd app
</code></pre><p>Necesitarás <code>index.html</code> y <code>index.js</code> archivos en este punto. Crea estos archivos en la carpeta <code>app</code>:</p><pre><code>touch index.html index.js
</code></pre><p>¡Perfecto! ¿Ya está todo listo?</p><p>Tu carpeta debería verse así:</p><pre><code>|-- node_modules/
|-- package.json
|-- webpack.config.js
|-- globals.js
|-- app/
	|-- index.html
	|-- index.js
</code></pre><h2 id="2-renderiza-nuestros-archivos-html-con-el-html-webpack-plugin"><strong>2. Renderiza nuestros archivos HTML con el <code>html-webpack-plugin</code></strong></h2><p>Esta <code>app/index.html</code> está vacía. Vamos a añadir algo de marcado en él y luego agregue una variable personalizada:</p><pre><code class="language-html">&lt;html lang="en"&gt;
&lt;head&gt;
  &lt;title&gt;Webpack shared variables!&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;h1&gt;&lt;%= myTitle %&gt;&lt;/h1&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p>Como puedes ver, estamos tratando de imprimir una variable en nuestro HTML... ¡Lo cual es imposible! Para hacer que funciones usaremos el <a href="https://github.com/jantimon/html-webpack-plugin">html-webpack-plugin</a> que nos brinda la habilidad de usar la sintaxis <a href="https://ejs.co/">EJS</a> e <strong><strong>i</strong>nyectar datos en el</strong>.</p><p>El complemento generará un archivo HTML válido. Mientras tanto, debes cambiar el nombre de tu archivo <code>app/index.html</code> a <code>app/index.ejs</code>.</p><pre><code>npm install --save-dev html-webpack-plugin
</code></pre><p>Volvamos a nuestro archivo de configuración. <code>html-webpack-plugin</code> tiene una interesante opción <code>templateParameters</code> que nos permite pasar un objeto como parámetro. Habilita el complemento de la siguiente manera en <code>webpack.config.js</code>:</p><pre><code class="language-javascript">const HtmlWebpackPlugin = require('html-webpack-plugin');
const globals = require('./globals.js')

module.exports = {
	// ... previous config, entry, output...
  plugins: [
    new HtmlWebpackPlugin({
      template: 'app/index.ejs',
      templateParameters: globals,
    })
  ]
};
</code></pre><p>Corre <code>npm run build</code> y <em><em>ta-daaaaa</em></em> « &lt;%= myTitle %&gt; » se convirtió « Hello freeCodeCamp » ! El trabajo está hecho por Webpack durante la compilación cuando corre el &nbsp;<code>html-webpack-plugin</code>.</p><p>¿Ves? Esto fue bastante sencillo con la herramienta correcta: HTML ✅</p><h2 id="3-usa-nuestras-variables-en-javascript"><strong>3. &nbsp;Usa nuestras variables en JavaScript</strong></h2><p>¡Uf, tantas líneas solo para imprimir una variable! ? Con Webpack, las cosas a menudo se complican. Bueno, esta es muy simple: en JavaScript simplemente importa tu archivo. En tu <code>app/index.js</code>:</p><pre><code class="language-javascript">import globals from '../globals.js'

document.write(
'&lt;pre&gt;' +
  JSON.stringify(globals, null, 2) +
'&lt;/pre&gt;'
);
</code></pre><p>Esta imprimirá nuestros objetos globales en la página. Ahora pasemos al CSS.</p><h2 id="4-usa-variables-compartidas-en-nuestro-css"><strong>4. Usa variables compartidas en nuestro CSS</strong></h2><p>¿Aquí es nuestro final jefe?</p><p>De acuerdo, chicos, me atraparon… Mentí. No podemos usar nuestros globales en CSS &nbsp;– Tenemos que usar un preprocesador. En este ejemplo, usaremos <a href="https://sass-lang.com/">SASS</a>.</p><p>En lado de Webpack, un complemento no será suficiente. Tenemos que usar un <a href="https://webpack.js.org/loaders/">cargado</a><a href="https://webpack.js.org/loaders/">r</a> para convertir SASS en CSS. En este caso necesitamos el paquete de <a href="https://github.com/webpack-contrib/sass-loader">sass-loader</a>, así que instálalo de acuerdo con los documentos: </p><pre><code>npm install sass-loader node-sass css-loader style-loader --save-dev
</code></pre><p>De vuelta a la codificación. Ahora que tenemos SASS, crea tu archivo de hoja de estilo, <code>app/style.scss</code>:</p><pre><code class="language-scss">h1 {
  color: $myColor;
}
</code></pre><p>Nuestro SASS está configurado – ahora, cómo podemos inyectarle datos? ¡El paquete <code>sass-loader</code> tiene una opción <a href="https://github.com/webpack-contrib/sass-loader#prependdata">anteponer datos</a>! Pero toma una cadena como parámetro, lo cual significa que tus datos deberían verse así: <code>"$myColor: red; myTitle: '...'";</code>.</p><p>Teneos que automatizar eso y convertir un objeto de JavaScript en una cadena. No encontré un paquete en &nbsp;<code>npm</code> que me satisficiera, entonces escribí <a href="https://gist.github.com/adrienZ/0257e37bf4788b903ba76fa82dac1ed1">mi propio convertidor</a>. Descarga el archivo y agrégalo en tu proyecto (en mi ejemplo es <code>utils/jsToScss.js</code>).</p><p>Tu final <code>webpack.config.js</code> debería verse así:</p><pre><code class="language-javascript">const globals = require("./globals.js");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const jsToScss = require("./utils/jsToScss.js");

module.exports = {
  entry: __dirname + "/app/index.js",
  output: {
    path: __dirname + "/dist",
    filename: "index_bundle.js"
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "app/index.ejs",
      templateParameters: globals
    })
  ],
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          // Creates `style` nodes from JS strings
          "style-loader",
          // Translates CSS into CommonJS
          "css-loader",
          // Compiles Sass to CSS
          {
            loader: "sass-loader",
            options: {
              prependData: jsToScss(globals)
            }
          }
        ]
      }
    ]
  }
};
</code></pre><p>Esto es lo que debería ver:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2019/12/Capture-d-e-cran-2019-12-23-23.44.11.png" class="kg-image" alt="Capture-d-e-cran-2019-12-23-23.44.11" width="600" height="400" loading="lazy"><figcaption><a href="https://glitch.com/edit/#!/shared-variables-webpack?path=webpack.config.js" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 15.2px; vertical-align: baseline; background-color: transparent; color: var(--gray90); text-decoration: underline; cursor: pointer; word-break: break-word;">https://glitch.com/edit/#!/shared-variables-webpack?path=webpack.config.js</a></figcaption></figure><p>Si todavía estás leyendo este tutorial, gracias por tu atención. ¡Espero que te ayude! Webpack es una poderosa herramienta que deberías profundizar. </p><p>NB: en tu carpeta <code>dist/</code> puedes ver que no se genera ningún CSS. Eso es porque uso el <code>style-loader</code> para mantener este demo simple. Para generar el archivo CSS, echa un vistazo a la <a href="https://webpack.js.org/plugins/mini-css-extract-plugin/">mini-css-extract-plugin</a>.</p><p>Traducido del artículo de: <strong><a href="https://www.freecodecamp.org/news/author/adri_zag/">Adrien Zaganelli</a> -</strong> <strong><a href="https://www.freecodecamp.org/news/how-to-share-variables-across-html-css-and-javascript-using-webpack/">How to share variables across HTML, CSS, and JavaScript using Webpack</a></strong></p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
