Tutorial de introducción a Webpack 5

Javascript

En este tutorial aprenderás a configurar Webpack desde cero. Verás cómo agregar módulos JavaScript, estilos, fuentes y textos tanto en tu servidor local como en producción. Aprenderás a usa Webpack desde cero, aunque este tutorial también será útil en caso de que sepas usar Webpack 4 pero nunca hayas usado Webpack 5, ya que también veremos las diferencias entre ambas versiones.

Si eres un desarrollador Full Stack o Frontend puede que estés acostumbrado a usar la herramienta create-react-app de React o el comando vue create de Vue, evitando así el uso directo de Webpack y la complejidad que conlleva configurarlo. Si es tu caso, este artículo está especialmente pensado para ti, ya que aprenderás a configurar Babel, React, Vue, Saas y también TypeScript usando Webpack.

Qué es Webpack

Webpack es un gestor de módulos que permite integrar y optimizar los módulos o componentes que uses en tus proyectos. Actualmente es ya raro crear webs con HTML. JavaScript ha pasado de ser un accesorio a ser el lenguaje principal que se usa cuando creas una web. Sin embargo, el código de los módulos utilizados necesita unirse, transpilarse y minificarse, transformando así el código en algo que el navegador pueda entender. Es aquí en donde interviene Webpack.

Los navegadores únicamente entienden HTML, CSS y JavaScript. Sin embargo, podrás crear tu aplicación usando TypeScript y compilar el código en JavaScript mediante Babel gracias a Webpack. Del mismo modo, también podrás programar usando las últimas versiones de JavaScript aunque todavía no estén disponibles para mucho navegadores, ya que Babel también se encargará de transformar el código en una versión más compatible y optimizada.

Además de gestionar módulos, Webpack también te permitirá importar archivos estáticos en los archivos JavaScript. También dispone de un servidor de desarrollo capaz de actualizar el código JavaScript y los estilos aplicados al DOM al vuelo cada vez que modificas algún archivo. Esto es algo que también está disponible en las herramientas create-react-app y vue create, ya que ambas usan Webpack. Sin embargo, en ocasiones es preferible personalizar Webpack desde cero.

Con Webpack puedes hacer muchas otras cosas, aunque en este tutorial nos limitaremos a las tareas más habituales que se usan en el día a día.

Introducción y requisitos

Antes de continuar con este tutorial, es más que recomendable que tengas ciertos conocimientos de HTML, de CSS y de JavaScript. Si no los tienes, consulta las siguientes guías para aprender aquellas tecnologías que desconozcas:

Además, aunque veremos todos los comandos, también es recomendable que tengas unos conocimientos básicos de la línea de comandos. Finalmente, en caso de que no tengas Node.js instalado en tu sistema operativo, consulta el tutorial de instalación de Node.js.

Configuraremos un pequeño proyecto de demostración cuyo código completo está  en GitHub. Consúltalo en caso de dudas.

Una vez finalizado el tutorial habrás aprendido a usar Webpack. Crearás también un servidor de desarrollo y crearás una versión de producción del proyecto con Webpack.

Instalación de Webpack

Lo primero que vamos a hacer es crear un directorio vacío al que llamaremos tutorial-webpack. Luego accede al directorio del proyecto mediante el comando cd e inicializa un nuevo proyecto usando npm, creando así el archivo package.json:

mkdir tutorial-webpack
cd tutorial-webpack
npm init -y

A continuación debes instalar los módulos webpack y webpack-cli mediante el siguiente comando:

npm i -D webpack webpack-cli

El paquete webpack es la herramienta que nos permitirá gestionar e integrar los módulos y los recursos, mientras que el paquete webpack-cli es la interfaz de línea de comandos de Webpack.

Seguidamente, crea un directorio llamado /src en el interior del directorio del proyecto. En este nuevo directorio incluiremos el código del proyecto.

Crea un archivo llamado index.js en directorio /src. Luego edítalo y agrega este mensaje en su interior:

console.log('El miedo le da alas a los hombres.');

Con esto ya tienes los elementos básicos del proyecto, que son el archivo principal de entrada y los módulos básicos de Webpack.

Configuración de Webpack

Para configurar Webpack necesitas crear el archivo webpack.config.js en la carpeta raíz de tu proyecto; es decir, en la carpeta de la que cuelga el directorio /src. Este es el archivo que usaremos para configurar Webpack.

Lo primero que haremos será definir un punto de entrada, que es aquel archivo o archivos que Webpack compilará. En nuestro caso el punto de entrada es el archivo /src/index.js:

const path = require('path');

module.exports = {
  entry: {
    main: path.resolve(__dirname, './src/index.js'),
  },
}

Seguidamente, tenemos que especificar de algún modo el directorio en el que se guardarán los archivos resultantes tras el proceso de compilado, transpilado o minificado que se realizará. Lo más habitual es usar el directorio /dist, en donde guardaremos la versión de la aplicación que se usará en producción:

module.exports = {
  entry: {
    main: path.resolve(__dirname, './src/index.js'),
  },
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: '[name].bundle.js',
  },
}

Tal y como ves hemos usado la expresión [name] en el nombre del archivo, que tendrá el valor del nombre del objeto de entrada que hemos especificado, que es main. Tras esto, ya habremos realizado la configuración básica de Webpack.

Sin embargo, todavía debes crear un script que ejecute el comando Webpack. Para ello usaremos el archivo package.json, al que debes agregar este código en la sección "scripts" del archivo:

"scripts": {
  "build": "webpack"
}

Finalmente, guarda el archivo package.json y ejecuta el siguiente comando desde la terminal:

npm run build

Tras finalizar la ejecución del comando, verás que se ha creado el directorio /dist, que contendrá el archivo main.bundle.js con el código JavaScript de la aplicación, según lo esperado. Sin embargo, todavía no se ha aplicado ningún cambio al código, por lo que el archivo contendrá el código original.

Webpack no procesará el código de los archivos por defecto, siendo una tarea que se lleva a cabo mediante los módulos existentes.

Plugins de Webpack

Los plugins de Webpack son objetos que disponen de un método llamado apply, que podemos llamar desde el compilador de webpack, tal y como veremos más adelante. Son un componente esencial de Webpack, ya que incluso el código interno de Webpack los utiliza. Webpack dispone de una larga lista de plugins, aunque hay unos cuantos que destacan sobre el resto por ser considerados como imprescindibles en muchos proyectos.

Los plugins se configuran mediante el objeto "plugins" del archivo webpack.config.js, aunque primero tendrás que instalarlos mediante npm. Por ejemplo, existe un plugin que cargará el archivo o bundle que hemos generado en la cabecera de la página que vamos a crear.

Necesitamos una página HTML en la que incluir el archivo generado automáticamente. Para ello usaremos el plugin html-webpack-plugin, que generará un archivo HTML en base a una plantilla que le pasemos. Para instalar el plugin html-webpack-plugin usa este comando:

npm i -D html-webpack-plugin

Luego crea un archivo al que llamaremos plantilla.html en el directorio /src. Vamos a incluir una serie de variables, como por ejemplo una que agregue el título de la página. Además también agregaremos el típico div root en el que crearemos la aplicación:

<!DOCTYPE html>
<html lang="es">
  <head>
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>

  <body>
    <div id="root"></div>
  </body>
</html>

Seguidamente vamos a importar el plugin html-webpack-plugin en el archivo webpack.config.js. Luego vamos a crear una instancia del plugin en el interior de la propiedad "plugins", pasándole al constructor un objeto con el título de la página, la ruta en la que se encuentra la plantilla a utilizar y el nombre del archivo resultante, al que llamaremos index.html:

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

module.exports = {
  entry: {
    main: path.resolve(__dirname, './src/index.js'),
  },
}

module.exports = {
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: '[name].bundle.js',
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'Tutorial Webpack',
      template: path.resolve(__dirname, './src/plantilla.html'),
      filename: 'index.html',
    }),
  ],
}

Luego ejecuta el comando npm run build de nuevo. Se creará el archivo index.html en la carpeta /dist, que incluirá el archivo main.bundle.js en su interior. Si abres este archivo usando tu navegador, verás que se muestra el texto El miedo le da alas a los hombres. por la consola, que era lo que habíamos pasado al método console.log.

Vamos a instalar también otro plugin que elimine todo el contenido del directorio /dist cada vez que creamos una nueva build. De este modo no mantendremos aquellos archivos que ya no se usen. Para ello instalaremos el plugin clean-webpack-plugin:

npm i -D clean-webpack-plugin

Seguidamente, edita de nuevo el archivo webpack.config.js, importa el plugin clean-webpack-plugin y crea una nueva instancia del mismo:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const {CleanWebpackPlugin} = require('clean-webpack-plugin');

module.exports = {
  entry: {
    main: path.resolve(__dirname, './src/index.js'),
  },
}

module.exports = {
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: '[name].bundle.js',
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'Tutorial Webpack',
      template: path.resolve(__dirname, './src/plantilla.html'),
      filename: 'index.html',
    }),
    new CleanWebpackPlugin(),
  ],
}

Módulos y loaders de Webpack

Webpack hace uso de loaders para preprocesar los archivos que se cargan a través de los módulos. Los loaders pueden importar archivos de la aplicación, formatearlos o transpilarlos, entre otras tareas, pudiendo así transformar cualquier archivo estático. Por ejemplo, podrás convertir un archivo programado con TypeScript a otro programado con JavaScript automáticamente, de modo que el navegador sea capaz de entenderlo. Un loader puede ser un script, un compilador de TypeScript, una sencilla hoja de estilos o también una aplicación como Babel.

Webpack incluye algunos loaders por defecto, aunque tendrás que instalar la mayoría de ellos. Los más haibutales son aquellos que permiten tranformar el código JavaScript moderno en una versión más compatible o a quellos que permiten usar librerías como React, Vue o Svelte. También aquellos usados para transformar hojas de estilo en formato SCSS a formato CSS o aquellos que permiten importar fuentes e imágenes. A continuación vamos a ver algunos de ellos.

Antes de continuar, vamos a agregar más contenido al archivo index.js. Por ejemplo, vamos a crear un encabezado y a inyectarlo en el DOM de la página. También vamos a agregar contenido al div root tal y como haríamos en una aplicación React o Vue. Edita el archivo y reemplaza su contenido por este otro:

// Declaramos una clase de JavaScript ES6
class Juego {
  constructor(nombre) {
    this.nombre = nombre;
  }
}

// Creamos un juego
const juego = new Juego('Max Payne');

const parrafo = document.createElement('p');
parrafo.textContent = `Me encanta ${juego.nombre}.`;

// Creamos la cabecera
const encabezado = document.createElement('h1');
encabezado.textContent = 'El miedo le da alas a los hombres';

// Agrega el encabezado al div #root
const app = document.querySelector('#root');
app.append(encabezado, parrafo);

Si intentas compilar este código ejecutando el comando npm run build, obtendrás un error de sintaxis, ya que las clases de JavaScript todavía no tienen soporte oficial por parte de todos los navegadores. Para arreglarlo necesitamos transpilar el código JavaScript ES6 a código JavaScript de una versión anterior. Para completar esta tarea usaremos Babel.

Configuración de Babel

Babel es una herramienta que te permite programar usando las últimas versiones de JavaScript, transformando el código a una versión de JavaScript más moderna en la build resultante. A este proceso se le suele llamar transpilación, ya que no se trata de una compilación en sí misma.

Como primer paso de la configuración de Babel, vamos a crear una regla que lea todos los archivos JavaScript del proyecto y los transforme a una versión más compatible del lenguaje usando babel-loader. Debemos leer todos los archivos a excepción de aquellos incluidos en el directorio node_modules.

Para instalar Babel y todas las dependencias que necesita usa este comando:

npm i -D babel-loader @babel/core @babel/preset-env @babel/preset-env @babel/plugin-proposal-class-properties

Hemos instalado babel-loader, que te permitirá transpilar archivos usando Babel y Webpack. También el módulo @babel/core, que permite transpilar el código de la versión ES6 de JavaScript o superior a una versión anterior. El módulo @babel/preset-env sencillamente agregará la configuración típica por defecto de Babel, mientras que el módulo @babel/plugin-proposal-class-properties agregará un archivo de configuración de Babel de ejemplo sobre el que poder trabajar.

Edita el archivo webpack.config.js y agrega la propiedad module al objeto module.exports. Aquí podrás definir las reglas que usaremos. Lo que queremos es leer todos los archivos con extensión .js, para lo cual usaremos la expresión regular /\.js$/. Agregamos el directorio /node_modules/ como excepción mediante otra expresión regular y finalmente indicamos que se use babel-loader para procesar los archivos:

module.exports = {
  /* Código existente... */
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: ['babel-loader'],
      },
    ],
  },
}

No he incluido todo le código del archivo, de modo que se vea más claro lo que queremos lograr. Una vez configurado Babel también tendremos que configurar el plugin creando el archivo .babelrc en la carpeta raíz del proyecto. Edítalo y agrega la configuración por defecto preset-env, que es el módulo que habíamos instalado. Además también debes agregar el plugin @babel/plugin-proposal-class-properties:

{
  "presets": ["@babel/preset-env"],
  "plugins": ["@babel/plugin-proposal-class-properties"]
}

Finalmente, ejecuta de nuevo el siguiente comando para compilar la aplicación usando Babel:

npm run build

Si accedes de nuevo al archivo /dist/index.html con tu navegador, deberías ver este resultado:

A continuación vamos a ver cómo puedes trabajar con recursos externos, como fuentes e imágenes.

Configuración de TypeScript

Vamos a ver cómo se configuraría TypeScript, aunque no lo agregaremos a este proyecto, viéndolo solo con fines ilustrativos. En caso de querer usar TypeScript, tendrías que instalar el loader typescript-loader en lugar de babel-loader. Además seleccionarías los archivos con extensión .ts, o .tsx de usar JSX, en lugar de los archivos con extensión .js, usando el loader ts-loader:

module.exports = {
  
  /* Código existente */
  
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        exclude: /node_modules/,
        use: ['ts-loader'],
      },
    ],
  },
}

Importación de imágenes

Estaría bien poder importar imágenes a tus archivos JavaScript, aunque no es una funcionalidad disponible en JavaScript por defecto. Agrega esta imagen o cualquier otra imagen a la carpeta /src/images del proyecto. Para importar la imagen lo ideal sería poder ejecutar la siguiente sentencia al comienzo del archivo index.js:

import imagenSrc from './images/max-payne.png';

Sin embargo, obtendrás un error. Afortunadamente, Webpack dispone de un módulo capaz de gestionar recursos estáticos externos, como es el caso de las imágenes. Se trata del loader asset/resource, que debemos agregar al archivo webpack.config.js. Para configurarlo debemos seleccionar aquellos formatos de imagen soportados mediante una expresión regular:

/* ... */

module: {
    rules: [
      /* ... */
      {
        test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
        type: 'asset/resource',
      },
    ],
  },
}

Finalmente, asegúrate de haber creado la imagen importada en el archivo index.js. Por ejemplo, con este código:

const imagen = document.createElement('img'); 
imagen.src = imagenSrc;

Luego agrégala al DOM junto con el resto de elementos:

app.append(encabezado, parrafo, imagen);

Cuando ejecutes el comando npm run build podrás ver que la imagen está ahora en el directorio /dist. Este será el resultado que verás en tu navegador:

A continuación vamos a ver cómo agregar más tipos de recursos.

Importación de fuentes

Webpack dispone de un módulo que te permitirá importar fuentes de diferentes formatos y también archivos SVG. Se trata del módulo asset/inline. Primero agrega esta imagen a la carpeta /src/images y luego impórtala al comienzo del archivo index.js:

import logoSrc from './images/remedy.svg';

Ahora edita el archivo webpack.config.js y agrega este otro objeto al array rules:

module: {
    rules: [
      /* ... */
      {
        test: /\.(woff(2)?|eot|ttf|otf|svg|)$/,
        type: 'asset/inline',
      },
    ],
  },
}

Edita del nuevo el archivo index.js y usa el archivo importado para crear una imagen:

const logo = document.createElement('img');
logo.setAttributeNS(null,'height','200');
logo.setAttributeNS(null,'width','200');
logo.src = logoSrc;

Luego agrégala al DOM junto con los otros elementos que habíamos agregado:

app.append(encabezado, parrafo, imagen, logo);

Cuando ejecutes el comando npm run build, la imagen SVG o las fuentes que hayas agregado se incluirán en el directorio /dist.

Por ahora este será el resultado que deberías ver en el navegador:

A continuación veremos cómo agregar estilos CSS.

Gestión de estilos

Existen diferentes formas de agregar estilos CSS a tu aplicación. Por ejemplo, es muy habitual usar las librerías CSS-in-JS o también Styled Components, todo en los propios archivos JavaScript. Sin embargo podrías querer importar archivos CSS, para lo cual podrías usar PostCSS, que te permitirá usar las últimas funcionalidades CSS del navegador cuando programas. Otra opción sería usar un preprocesador como Sass, muy utilizado a día de hoy. Si no has usado nunca Sass, puedes consultar el tutorial de Sass, aunque no lo usaremos en este tutorial.

El caso es que en muchas ocasiones se usan tanto Sass como PostCSS a la vez para exportar finalmente el código a CSS. Para ello tendrás que instalar unas cuantas dependencias:

npm i -D sass-loader postcss-loader css-loader style-loader postcss-preset-env node-sass

El módulo node-sass sencillamente permite usar Sass. El loader sass-loader permite cargar código SCSS y compilarlo a CSS. El loader postcss-loader permite procesar el código CSS usando PostCSS, usando en este caso las opciones predefinidas del módulo postcss-preset-env.

También hemos instalado el loader css-laoder para poder importar archivos CSS en JavaScript y, finalmente, el módulo style-loader para poder agregar código CSS al DOM.

Antes de continuar vamos a crear el archivo SCSS de ejemplo /src/styles/main.scss. En donde incluiremos dos variables Sass, además de un color en formato LCH:

$font-size: 1.2rem;
$font-color: lch(60 90 30);

html {
  font-size: $font-size;
  color: $font-color;
}

Seguidamente, importa el archivo main.scss en la parte superior del archivo index.js:

import './styles/main.scss';

Una vez instalados los módulos y creado el archivo main.css, vamos a configurar PostCSS, para lo cual debes crear el archivo postcss.config.js en el directorio raíz de la aplicación. En el archivo debes agregar el plugin postcss-preset-env a la lista de plugins, especificando que quieres asegurarte de que al menos sean compatibles con el código resultante las últimas tres versiones de cada navegador:

module.exports = {
  plugins: {
    'postcss-preset-env': {
      browsers: 'last 3 versions',
    },
  },
}

Luego debes agregar los loaders que hemos instalado al archivo de configuración de Webpack. Debes agregarlos en orden al archivo webpack.config.js, ya que un loader podría no ser capaz de interpretar el código si no se ha transformado antes con otro. Sin embargo, se compilan del último al primero, por lo que el primero que se usará será el último de la lista. Por ello, debes agregar el loader sass-loader al final de la lista para que compile el archivo .scss. Antes del loader sass-loader debes agregar el loader postcss-loader, el loader css-loader para procesar el código CSS y al inicio de la lista el loader style-loader, que agregará el código CSS resultante al DOM:

module: {
    /* ... */
    rules: [
      /* ...  */
      {
        test: /\.(scss|css)$/,
        use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
      },
    ],
  },

Si ahora ejecutas el comando npm run build, verás que se aplican los estilos que hemos definido.

Ahora podrás ver los estilos aplicados en el navegador:

Sin embargo, el loader style-loader que se encarga de inyectar los estilos solamente se usará en desarrollo. Cuando crees tu versión de producción, querrás usar el plugin MiniCssExtractPlugin, que creará un archivo minificado con el código CSS resultante. La configuración de Webpack para producción suele agregarse en otro archivo separado. Al final de este tutorial veremos cómo hacerlo.

Servidor de desarrollo de Webpack

Ahora, en lugar de acceder al archivo /dist/index.html directamente, podríamos crear un servidor de desarrollo para la aplicación. Existen diversas opciones. Por un lado, puedes instalar el paquete http-server globalmente mediante el siguiente comando:

npm i -g http-server

Para iniciarlo, tendrías que usar el comando http-server en la carpeta /dist. Si luego accedes a la ruta que se muestre en la terminal al iniciar el servidor, podrás ver  que se muestra el encabezado que hemos inyectado.

Sin embargo, todavía tendrás que seguir usando el comando rpm run build cada una de las veces que actualices el código de la aplicación, siendo un proceso bastante tedioso. Además, cuanto más grande sea proyecto, más tiempo durará el proceso de compilación.

En general querrás establecer dos configuraciones; una que uses en tu servidor local de desarrollo y otra que uses en producción. La versión de producción usará los archivos minificados y optimizados, eliminando los source maps. Por otro lado, la versión de desarrollo se ejecutará únicamente en el servidor de Webpack que instalaremos a continuación, actualizándose automáticamente con cada cambio. La versión de desarrollo incluye source maps.

En lugar de crear los archivos en el directorio /dist, cuando uses la configuración en desarrollo se creará todo en la memoria.

Para crear el servidor de desarrollo más avanzado debes instalar primero el paquete webpack-dev-server mediante este comando:

npm i -D webpack-dev-server

Por ahora vamos a agregar la configuración que usaremos en desarrollo en el archivo webpack.config.js que hemos usado a lo largo del tutorial. Incluiremos la propiedad mode, a la que le daremos el valor 'development'. En producción tendría el valor 'production', aunque por ahora todavía no es el caso. Luego agregamos la configuración del servidor mediante la propiedad devServer con algunos datos de configuración por defecto, como el puerto a usar, que será el 8000.

También agregaremos el plugin Hot Module Repladement, que permitirá que los módulos se ejecuten automáticamente, siendo el resultado perceptible en el navegador, de modo que no tengas que refrescar la página con cada cambio. Este sería el código final del archivo webpack.config.js:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const webpack = require('webpack');

module.exports = {
  mode: 'development',
  devServer: {
    historyApiFallback: true,
    contentBase: path.resolve(__dirname, './dist'),
    open: true,
    compress: true,
    hot: true,
    port: 8000,
  },
  entry: {
    main: path.resolve(__dirname, './src/index.js'),
  },
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: '[name].bundle.js',
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'Tutorial Webpack',
      template: path.resolve(__dirname, './src/plantilla.html'),
      filename: 'index.html',
    }),
    new CleanWebpackPlugin(),
    new webpack.HotModuleReplacementPlugin(),
  ],
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: ['babel-loader'],
      },
      {
        test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
        type: 'asset/resource',
      },
      {
        test: /\.(woff(2)?|eot|ttf|otf|svg|)$/,
        type: 'asset/inline',
      },
      {
        test: /\.(scss|css)$/,
        use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
      },
    ],
  },
}

Ahora edita de nuevo el archivo package.json y agrega la opción start en la sección de scripts. En esta opción agregaremos el comando webpack serve, que será el que se ejecute para iniciar el servidor.

"scripts": {
  "start": "webpack serve",
 },

Finalmente, podrás iniciar el servidor con este comando:

npm start

Se abrirá automáticamente en tu navegador la URL http://localhost:8000/, en donde podrás ver el proyecto en funcionamiento. Podrás percibir al instante cualquier cambio que hagas en los archivos JavaScript y SCSS. Por ejemplo prueba a cambiar el tamaño de la fuente del archivo main.css para comprobarlo.

Configuración en producción

Necesitamos crear un archivo de configuración de Webpack para el entorno de desarrollo y otro para el entorno de producción. En desarrollo, podemos usar el que ya tenemos, mientras que para producción crearemos el archivo webpack.prod.js.

El contenido del archivo será similar al que usamos en desarrollo, salvo porque agregaremos un plugin que minifique los archivos CSS. Instala sus dependencias mediante el siguiente comando:

npm i -D css-minimizer-webpack-plugin mini-css-extract-plugin

Este sería el código completo del archivo webpack.prod.js:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const webpack = require('webpack');

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
  mode: 'development',
  devServer: {
    historyApiFallback: true,
    contentBase: path.resolve(__dirname, './dist'),
    open: true,
    compress: true,
    hot: true,
    port: 8000,
  },
  entry: {
    main: path.resolve(__dirname, './src/index.js'),
  },
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: '[name].bundle.js',
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'Tutorial Webpack',
      template: path.resolve(__dirname, './src/plantilla.html'),
      filename: 'index.html',
    }),
    new CleanWebpackPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new MiniCssExtractPlugin({
      filename: 'styles/[name].[contenthash].css',
      chunkFilename: '[id].css',
    }),
  ],
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: ['babel-loader'],
      },
      {
        test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
        type: 'asset/resource',
      },
      {
        test: /\.(woff(2)?|eot|ttf|otf|svg|)$/,
        type: 'asset/inline',
      },
      {
        test: /\.(scss|css)$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              importLoaders: 2,
              sourceMap: false,
              modules: true,
            },
          },
          'postcss-loader',
          'sass-loader',
        ],
      },
    ],
  },
  optimization: {
    minimize: true,
    minimizer: [new CssMinimizerPlugin(), "..."],
    runtimeChunk: {
      name: 'runtime',
    },
  },
  performance: {
    hints: false,
    maxEntrypointSize: 512000,
    maxAssetSize: 512000,
  },
}

Luego edita el archivo package.json y modifica el comando build para que cargue el archivo de configuración de producción:

"build": "webpack --config webpack.prod.js"

Si ahora ejecutas el comando npm run build y luego accedes a la carpeta /dist/styles podrás encontrar el archivo CSS minificado.

Acerca de Webpack 5

Los cambios introducidos en Webpack 5 no son demasiados. Por ejemplo, el comando webpack-dev-server ha cambiado por el comando webpack-serve.

Además, mientras que antes se usaban los loaders file-loader, raw-loader o url-loader según el tipo de archivo, ahora se usan los módulos de recursos de Webpack.

Otro cambio relevante son los polyfills, que ya no están disponibles en Webpack 5, por lo que obtendrás un error si agregas la dependencia stream-browserify y luego añades el valor { stream: 'stream-browserify' } a la propiedad alias de la configuración de Webpack.

Finalizando

Y con esto hemos finalizado el tutorial. Algo que también podrías hacer es configurar React o Vue en conjunción con Typescript, ya que es una configuración cada vez más habitual.

Recuerda que puedes consultar el código completo en GitHub.

Si quieres, dado que también hemos hablado de React y de Vue, puedes consultar estos otros tutoriales:

Y esto ha sido todo.


Avatar de Edu Lazaro

Edu Lázaro: Ingeniero técnico en informática, actualmente trabajo como desarrollador web y programador de videojuegos.

👋 Hola! Soy Edu, me encanta crear cosas y he redactado esta guía. Si te ha resultado útil, el mayor favor que me podrías hacer es el de compatirla en Twitter 😊

Si quieres conocer mis proyectos, sígueme en Twitter.

3 comentarios en “Tutorial de introducción a Webpack 5

  1. Super útil, por cierto he visto una tontería de errata en un párrafo, te lo marco con llaves:

    También hemos instalado el loader {{css-laoder}} para poder importar archivos CSS en JavaScript y, finalmente, el módulo style-loader para poder agregar código CSS al DOM.

    Un saludo

  2. En la versión actual de devServer, la línea:

    contentBase: path.resolve(__dirname, ‘./dist’),

    debe ser:

    static: path.resolve(__dirname, ‘./dist’),

  3. Primero que nada muchas gracias por compartir tus conocimientos, espero sigas con tus aporte de tu experiencia y mucha gente pueda aprender de ellos. Felicitaciones todo muy bien explicado exceptuando algunas excepciones pero nada que no se pueda resolver de verdad aclaraste muchas dudas GRACIAS…

Deja una respuesta

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

“- Hey, Doc. No tenemos suficiente carretera para ir a 140/h km. - ¿Carretera? A donde vamos, no necesitaremos carreteras.”