Webpack es una herramienta Frontend que nos permite empaquetar el c贸digo de nuestras aplicaciones, y dem谩s archivos est谩ticos como: HTML, CSS, javascript y fuentes, y prepararlo para colocarlo en producci贸n.

En otras palabras, es un module bundler que nos facilita el desarrollo de aplicaciones, permiti茅ndonos manipular de forma eficiente nuestro c贸digo y dem谩s archivos necesarios de nuestra aplicaci贸n. Finalmente genera la versi贸n de distribuci贸n de la manera m谩s optimizada posible.

Webpack naci贸 en el a帽o 2012 y desde ah铆 se ha convertido en la herramienta de desarrollo m谩s importante para empresas como Meta, Twitter, Paypal y el resto de la comunidad de desarrollo web del mundo.

Es importante que tengas en cuenta que esta herramienta es de una filosof铆a de trabajo modular; esto indica que debemos dividir nuestro c贸digo y elementos est谩ticos en diferentes m贸dulos para que Webpack los empaquete y genere un resultado final listo para producci贸n.

驴Qu茅 puedes hacer con Webpack?

Con esta herramienta puedes:

  • Gestionar las dependencias
  • Ejecutar tareas
  • Convertir archivos est谩ticos
  • Generar un entorno de desarrollo para hacer pruebas locales de tus aplicaciones
  • Cargar diferentes m贸dulos de JavaScript
  • Minificar c贸digo JavaScript y CSS
  • Instalar plugins para extender sus funcionalidades
  • Trabajar con preprocesadores CSS y PostCSS

Conceptos b谩sicos de Webpack

Esta herramienta construye un gr谩fico de dependencias que mapea cada m贸dulo para convertirlo en uno o m谩s m贸dulos seg煤n el caso. Antes de la versi贸n 4, se necesitaba crear un archivo de configuraci贸n para poder crear un entorno de desarrollo con Webpack.

Entry point

El punto de entrada es uno o m谩s documentos de donde parte el inicio de nuestra aplicaci贸n.

Output

El punto de salida es uno o varios documentos que son el resultado del procesamiento de Webpack. Por lo general, es la carpeta dist donde se almacenan los documentos est谩ticos de nuestra aplicaci贸n web lista y optimizada para producci贸n.

Loaders

A trav茅s de los loaders y podemos manipular y empaquetar ciertas particularidades de nuestro proyecto. Por ejemplo, podemos utilizar un loader para que Webpack comprenda un lenguaje en espec铆fico como jsx.

Plugins

A trav茅s de los plugins podemos a帽adir algunas funcionalidades o configuraciones particulares de los loaders.

Modos de Webpack

  • Modo de desarrollo: esta herramienta proporciona elementos para poder trabajar m谩s c贸modamente en un entorno de desarrollo. Por ejemplo, permite generar un servidor web con la posibilidad de observar los cambios en tiempo real.
  • Modo de producci贸n: genera un paquete optimizado para colocar nuestra aplicaci贸n en producci贸n.
  • Modos de performance: nos permite a帽adir configuraciones avanzadas para indicar c贸mo deseamos que se empaquete nuestro proyecto, hacia donde va a almacenarse, como tambi茅n generar un servidor local con un puerto espec铆fico y as铆 ver los cambios en tiempo real en nuestro navegador.

Preparaci贸n de un proyecto antes de instalar Webpack

Te voy a indicar unos pasos previos para poder realizar este instructivo. Cuando era muy novato, se me hac铆a molesto encontrar documentaci贸n sobre lo que necesitaba pero que no me proporcionaban un punto de partida.

Entonces, antes de iniciar, te recomiendo hacer estos breves pasos a continuaci贸n para poder aprender a utilizar webpack.

Si deseas ir a m谩s profundidad, tengo un art铆culo en el que explico la manera de configurar un entorno de desarrollo en Windows.

Elementos a considerar antes de iniciar este instructivo

  • Todos los comandos de consola son basados en el sistema operativo Linux.
  • Entiendo que sabes manejar bien el sistema operativo Windows o Mac OS.

1. Crear la carpeta del proyecto

Simplemente es crear una carpeta d贸nde vas a guardar todos los archivos de tu proyecto web. Si estas utilizando una interfaz gr谩fica, solamente es ubicarte en el lugar de directorio donde deseas crear el proyecto y pum, crearla con clic derecho o en el administrador de carpetas del Sistema Operativo.

Si utilizas una consola el comando es el siguiente: `mkdir nombre_carpeta

2. Ubicarte dentro de la carpeta

El comando de consola para navegar por carpetas es el siguiente: `cd /nombre_carpeta/nombre_carpeta 鈥

3. Inicializamos un proyecto JavaScript

Ubicados dentro de la carpeta introducimos el siguiente c贸digo en la consola: npm init 鈥搚

  • npm. Es el administrador de paquetes
  • init. Es el comando utilizado para inicializar con npm un proyecto JavaScript
  • -y. Es un comod铆n el cual responder谩 鈥淪铆鈥 a todas las preguntas que se solicitan en el momento de la creaci贸n de un proyecto JavaScript. Es algo para ahorrar tiempo, el documento manifiesto del proyecto se puede modificar en cualquier otro momento.

4. Inicializamos un proyecto git

Git es un sistema gesti贸n de versiones muy 煤til para hacer trazabilidad al avance de desarrollo de un proyecto. Luego, este mismo proyecto se puede subir a un sistema administrador de versiones en la nube como github o gitlab.

Para inicializar un proyecto git, escribimos el siguiente comando en consola: git init

Instalaci贸n de Webpack

Ubicados en la carpeta donde deseamos trabajar nuestro proyecto, introducimos el siguiente comando:

npm install webpack webpack-cli 鈥揇

  • npm. Es el sistema gestor de paquetes que nos proporcionar谩 a Webpack.
  • install. Es el comando para instalar webpack.
  • webpack. Es el nombre del paquete que estamos requiriendo.
  • webpack-cli. Es otro paquete de webpack para que podamos hacer uso de los comandos espec铆ficos que solo funcionan para la herramienta.
  • -D. Es un comod铆n con el que le indicamos a npm que instale esta herramienta solo en un entorno de desarrollo. Es decir, estos archivos se omitir谩n cuando se genere la distribuci贸n de producci贸n, pues no se necesitan.

Creaci贸n del archivo de configuraci贸n webpack.config.js

Este archivo nos va ayudar a establecer la configuraci贸n de los diferentes elementos que vamos a utilizar, como los loaders, plugins, entry points, outputs y dem谩s elementos que necesitemos procesar con Webpack.

1. Creamos un archivo en la ra铆z de nuestro proyecto y lo llamamos webpack.config.js

Con el editor de c贸digo que utilicemos creamos un nuevo documento de JavaScript y lo nombramos 鈥渨ebpack.config.js鈥

2. Requerimos la librer铆a de node llamada 鈥減ath鈥

Este m贸dulo ya viene instalado por defecto en node.js y no es necesario requerir una dependencia.

const path = require('path');

3. Creaci贸n del m贸dulo de Webpack

Creamos un m贸dulo que vamos a exportar con un objeto que contiene toda la informaci贸n de la configuraci贸n deseada de Webpack.

module.exports = {
    ...
}

4. Creaci贸n del entry point, punto de entrada

Dentro del objeto module.exports, creamos el primer par谩metro de configuraci贸n de webpack que nos permite obtener el archivo de entrada de nuestro proyecto. Esto es muy importante porque debemos de indicarle el elemento de inicio de nuestra aplicaci贸n.

entry: './src/index.js',

  • ./src/index.js. Es la ruta donde se encuentra nuestro archivo de entrada.

5. Creaci贸n del output

El output es el lugar de destino a donde ir谩 nuestro c贸digo una vez sea empaquetado por Webpack. Es decir, es la carpeta que contiene los archivos listos para producci贸n de nuestro proyecto.

Creamos un objeto que tendr谩 las configuraciones que deseamos en la carpeta 鈥渄ist鈥 que es un diminutivo del nombre 鈥渄istribution鈥.

output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'main.js'
    },
  • Path: path.resolve(__dirname, 鈥榙ist鈥). Nos indica el lugar donde se va a guardar nuestro proyecto una vez compilado. Se utiliza el m贸dulo path con el fin de evitar problemas de ejecuci贸n de Webpack en el momento de empaquetar los archivos para producci贸n.

Se recomienda utilizar la palabra 鈥渄ist鈥 porque es un est谩ndar para determinar la carpeta que contiene los archivos de producci贸n del proyecto.

  • filename: 鈥榤ain.js鈥. Es el nombre que le asignamos al archivo resultante que contendr谩 todo nuestro proyecto empaquetado. Tambi茅n se puede utilizar el nombre 鈥渂undle.js鈥 aunque se puede colocar el nombre que se desee.

6. Especificamos con qu茅 extensiones vamos a trabajar en el proyecto

Creamos un objeto que se llame resolve y dentro de este creamos un arreglo que contendr谩 las extensiones de archivo que vamos a utilizar en el proyecto y por ende, vamos a necesitar que Webpack procese.

resolve: {
        extensions: ['.js'],
    },

Por ejemplo, le hemos indicado a Webpack que la extensi贸n que vamos a utilizar es JavaScript

Con el comando de consola: npx webpack 鈥搈ode production 鈥揷onfig webpack.config.js Ejecutamos webpack para que empaquete y prepare nuestro c贸digo para producci贸n. Si puedes observar, al utilizar --config webpack.config.js le estamos indicando a la herramienta que utilice el archivo de configuraci贸n que hemos creado de los puntos 1 al 6

El c贸digo completo de la configuraci贸n inicial de webpack ser铆a el siguiente

const path: require('path');

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

Configuraci贸n de Babel

Babel es una herramienta que nos permite utilizar las 煤ltimas especificaciones del lenguaje JavaScript en nuestros proyectos.

Al configurar Babel en Webpack, podremos utilizar JavaScript de 煤ltima generaci贸n durante el desarrollo con la tranquilidad de que cuando se construya el bundle (o paquete de producci贸n) Webpack transformar谩 el JavaScriptde 煤ltima generaci贸n que hemos utilizado a un JavaScript que puedan interpretar todos los navegadores.

1. Instalamos las dependencias necesarias para poder utilizar Babel en Webpack

npm install babel-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime -D

  • @babel/core. Es el contenido total del recurso babel
  • @babel/preset-env. Nos permitir谩 utilizar el JavaScript m谩s moderno y convertirlo a un lenguaje que puedan interpretar todos los navegadores
  • @babel/plugin-transform-runtime. Como utilizamos funciones as铆ncronas en nuestro proyecto, es necesario adicionar esta funcionalidad.

2. Creamos una configuraci贸n especial para Babel

Creamos un archivo llamado 鈥.babelrc鈥 en la ra铆z del proyecto.

El punto inicial se utiliza para indicar que es un archivo oculto. Es decir, un archivo que no es visible para los usuarios.

2.1 Creamos un objeto donde especificamos las configuraciones de Babel

Este archivo de configuraci贸n es para que Babel entienda c贸mo va a trabajar con nuestro JavaScript.

{
    鈥減resets鈥: [
        鈥淍babel/preset-env鈥
    ],
    鈥減lugins鈥: [
        鈥淍babel/plugin-transform-runtime鈥
    ]
}

3. Agregamos Babel a nuestro archivo de configuraci贸n de Webpack

Creamos un objeto llamado module que servir谩 para agregar todas las configuraciones de babel dentro de un objeto.

module: {
    鈥
}

3.1 Agregamos las reglas para el uso de babel

Dentro del objeto module, agregamos un arreglo que contendr谩 un objeto con las reglas de uso.

rules: [
	{
		鈥
	}
]

3.2 Realizar un test

Este test nos permitir谩 saber qu茅 tipo de extensiones vamos a utilizar. Esto se hace con expresiones regulares. Este test se ubica dentro del objeto creado en el arreglo module.

test: /\.m?Js$/,

  • /\.m?Js$/,. Esta es una expresi贸n regular que indica que Webpack utilice cualquier extensi贸n que inicie por 鈥渕js鈥 o 鈥渏s鈥. La extensi贸n 鈥渕js鈥 es la de los m贸dulos.

3.3 Excluir los m贸dulos de node

Esto nos permitir谩 evitar conflictos en la ejecuci贸n de nuestro proyecto.

Exclude: /node_modules/,

3.4 Indicamos que utilice Babel

Creamos un objeto llamado use dentro del objeto del arreglo rules e indicamos que utilice el loader de Babel.

use: {
	loader: 'babel-loader'
}

El c贸digo resultante hasta ahora ser铆a el siguiente:

const path: require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'main.js'
    },
    resolve: {
        extensions: ['.js'],
    },
    module: {
        rules: [
            {
                test: /\.m?js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader'
                }
        ]
    }
}

HTML en Webpack

Para que esta herramienta pueda utilizar y procesar HTML debemos hacer lo siguiente

1. Instalar el plugin de html-webpack-plugin

npm install html-webpack-plugin 鈥揇

2. Configuramos HTML en nuestro archive webpack.config.js

2.1 Requerimos el recurso

const HtmlWebpackPlugin = require(鈥榟tml-webpack-plugin鈥)

2.2 Agregamos la secci贸n de plugins en webpack.config.js

Despu茅s de la secci贸n module, agregamos la nueva secci贸n plugins

Plugins: [
	鈥
]

2.3 Configuramos el plugin HTML dentro de la secci贸n plugins

Generamos un nuevo objeto que contendr谩 todas las configuraciones del plugin HTML

new HtmlWebpackPlugin({
	鈥
})

2.4 Insertamos los elementos del plugin

Dentro del objeto creado en el punto 2.3 escribimos:

inject: true,

2.5 agregamos el template a la configuraci贸n

A Webpack debemos informarle d贸nde est谩 el recurso HTML que vamos a utilizar en el proyecto. Para este manual se har铆a de la siguiente forma.

Dentro del objeto creado en el punto 2.3 agregamos el siguiente c贸digo:

template: './public/index.html',

2.6 Indicamos el resultado de la preparaci贸n del archivo HTML

Dentro del objeto creado en el punto 2.3 agregamos la siguiente instrucci贸n.

filename: './index.html'

Se puede agregar el nombre que deseamos, sin embargo, por convenci贸n es importante manejar el est谩ndar 鈥渋ndex.html鈥.

Entonces realizando los puntos 2.1 hasta 2.6, Webpack tomar谩 nuestro template, lo procesar谩 y lo llevar谩 optimizado a la carpeta de 鈥渄ist鈥 con el nombre de index.html.

Aviso importante

Como Webpack integra el template HTML en JavaScript, no es necesario importar el archivo index.js (o cualquiera sea el nombre) dentro del documento HTML.

3. En la consola comprobamos el funcionamiento de todas las configuraciones realizadas hasta ahora incluyendo HTML.

Crearemos un script para ejecutar el build de Webpack con caracter铆sticas de producci贸n.

3.1 Generamos el script en package.json

En el archivo package.json, en su secci贸n de scripts, agregamos el siguiente c贸digo:

"build": "webpack --mode production"

3.2 Ejecutamos el script para crear un paquete de nuestro proyecto en producci贸n

Escribimos el siguiente c贸digo en nuestra consola y lo ejecutamos

npm run build

Si todo est谩 OK, debe aparecer la consola de la siguiente manera.

Como vemos, se ha creado una carpeta llamada 鈥渄ist鈥 que contiene nuestro proyecto optimizado para colocarlo en producci贸n.

3.3 Crearemos un script para empaquetar nuestro proyecto pero en modo development

En el archivo package.json, en su secci贸n de scripts, agregamos el siguiente c贸digo:

"dev": "webpack --mode development"

3.4 Ejecutamos el script para crear un paquete de nuestro proyecto en producci贸n

Escribimos el siguiente c贸digo en nuestra consola y lo ejecutamos

npm run dev

CSS y Webpack

S茅 que este ha sido uno de los momentos que m谩s has estado esperando; pues como desarrolladores Frontend, pasamos horas y horas d谩ndole sentido visual a nuestros proyectos.

Esta herramienta de desarrollo la puedes configurar completamente para trabajar con CSS; incluso, puedes trabajar con preprocesadores como Stylus, SASS, LESS o tambi茅n con postCSS.

1. Configuraci贸n de CSS en Webpack

1.1 Instalaci贸n de dependencias

npm install mini-css-extract-plugin css-loader -D

1.2 Configuraci贸n del archivo webpack.config.js

1.2.1 Importamos el plugin para poder trabajar con CSS

Declaramos una variable constante para obtener el recurso

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

1.2.3 Creamos las reglas necesarias para que Webpack pueda reconocer nuestro CSS

Dentro del arreglo de rules del objeto module, creamos un nuevo objeto para agregar las reglas CSS.

module: {
rules: [
	{
		test: /\.m?js$/,
		exclude: /node_modules/,
		use: 'babel-loader'
	},
	{
		鈥
	}
	]
}
1.2.4 聽Creamos el test dentro del nuevo objeto para que Webpack reconozca los archivos CSS a trav茅s de una expresi贸n regular.

test: /\.css$/i,

1.2.5 Creamos el par谩metro 鈥渦se鈥 para indicarle a Webpack que utilice el loader de CSS
use: [MiniCssExtractPlugin.loader,
	'css-loader'
],
1.2.6 Dentro del apartado de plugins, creamos una nueva instancia para que Webpack reconozca el plugin CSS

new MiniCssExtractPlugin()

Ahora, podemos empaquetar nuestra aplicaci贸n en modo de desarrollo utilizando npm run dev

IMPORTANTE

  • En el archivo de HTML no es necesario invocar el archivo CSS
  • El CSS se debe invocar desde el archivo index.js de la siguiente manera:

import './styles/main.css';

Obvio, la ruta cambia seg煤n tu orden de carpetas.

2. Preprocesadores y Webpack

En esta oportunidad vamos a trabajar con el preprocesador Stylus, sin embargo, la configuraci贸n es muy parecida para los preprocesadores SASS y LESS.

2.1 Instalaci贸n del loader de Stylus

npm install stylus stylus-loader 鈥揇

2.2 En el archivo webpack.config.js, creamos la regla para que Wepback reconozca el lenguaje Stylus

Esto lo hacemos en la expresi贸n regular donde decimos que reconozca CSS.

test: /\.css|.styl$/i,

2.3 En el archivo webpack.config.js, agregamos el loader en el arreglo de use del objeto que se utiliza para manipular CSS

use: [MiniCssExtractPlugin.loader,
	'css-loader',
	'stylus-loader'
],

2.4 Importamos el archivo de Stylus que utilizamos para escribir el c贸digo .styl en el archivo index.js. As铆 como cuando importamos el archivo CSS

import './styles/main.styl';

Hasta este punto el c贸digo de configuraci贸n webpack.config.js deber铆a estar as铆.

const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'main.js'
    },
    resolve: {
        extensions: ['.js'],
    },
    module: {
        rules: [
            {
                test: /\.m?js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader'
                }
            },
            {
                test: /\.css|.styl$/i,
                use: [MiniCssExtractPlugin.loader,
                    'css-loader',
                    'stylus-loader'
                ],
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            inject: true,
            template: './public/index.html',
            filename: './index.html'
        }),
        new MiniCssExtractPlugin()
    ]
}

Copia de archivos con Webpack

Para copiar archivos desde la carpeta src hacia la carpeta de distribuci贸n sigue los siguientes pasos.

1. Instalar del plugin copy-webpack-plugin

npm install copy-webpack-plugin 鈥揇

2. Configurar los elementos que van a ser copiados a trav茅s de Webpack

2.1 Creamos la variable constante que traer谩 el plugin a nuestro documento de configuraci贸n.

const CopyPlugin = require(鈥榗opy-webpack-plugin鈥);

2.2 Creamos una instancia del plugin en la secci贸n plugins en el documento de configuraci贸n

new CopyPlugin({
})

2.3 Dentro de esta instancia generamos un objeto dentro de un arreglo llamado patterns que tendr谩 las rutas de los archivos

patterns: [
                {
                    from: path.resolve(__dirname, "src", "assets/images"),
                    to: "assets/images"
                }
            ]

Nota: cambia las rutas seg煤n tus necesidades.

3. referenciaci贸n de im谩genes

Como el destino final de las im谩genes es la carpeta 鈥渄ist鈥, la manera correcta de referenciar las im谩genes es agregando en la etiqueta que utiliza ese archivo, la ruta final definida en el punto 2.3. Por ejemplo:

<img src =鈥漚ssets/images/imagen.jpg鈥 />

As铆 quedar铆a el archivo de configuraci贸n con esta nueva actualizaci贸n:

const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyPlugin = require('copy-webpack-plugin');

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'main.js'
    },
    resolve: {
        extensions: ['.js'],
    },
    module: {
        rules: [
            {
                test: /\.m?js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader'
                }
            },
            {
                test: /\.css|.styl$/i,
                use: [MiniCssExtractPlugin.loader,
                    'css-loader',
                    'stylus-loader'
                ],
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            inject: true,
            template: './public/index.html',
            filename: './index.html'
        }),
        new MiniCssExtractPlugin(),
        new CopyPlugin({
            patterns: [
                {
                    from: path.resolve(__dirname, "src", "assets/images"),
                    to: "assets/images"
                }
            ]
        })
    ]
}

Loaders de im谩genes

Anteriormente observamos la posibilidad de copiar, o mejor dicho, trasladar archivos desde la carpeta src del proyecto hacia la carpeta dist. En esta oportunidad, vamos a darle tratamiento de nuestras im谩genes haciendo un import de las mismas, llam谩ndolas como variables y gener谩ndolas directamente en nuestro proyecto.

1. Configuraci贸n del archivo webpack.config.js

1.1 Agregamos la herramienta assets module nativa de Webpack

Dentro del arreglo rules del objeto module, agregamos la regla

{
                test: /\.png/, // indicamos el listado de archivos a los cuales vamos a dar tratamiento
                type: 'asset/resource', // Permite la importaci贸n del recurso en el template
            }

1.2 Cambiamos la manera en la que webpack nombra y ubica el recurso de imagen

En el objeto output, despu茅s de filename: 'main.js Colocamos el siguiente c贸digo:

assetModuleFilename: 'assets/images/[hash][ext][query]'

Con esto, las im谩genes se guardar谩n en la carpeta assets/images y lo har谩 con el c贸digo hash y su extensi贸n.

2. Modificaci贸n de la manera en que se llama el recurso en el template

La imagen puede ser ahora llamada a modo de importaci贸n en el archivo template.js

2.1 Importaci贸n o llamado de los recursos de im谩genes

import instagram from '../assets/images/instagram.png';
import twitter from '../assets/images/twitter.png';
import github from '../assets/images/github.png';

2.2 Llamado de las im谩genes en la etiqueta <img/>

<div class="card_social">
          <a href="https://twitter.com/gndx">
            <img src="${twitter}" />
          </a>
          <a href="https://github.com/gndx">
            <img src="${github}" />
          </a>
          <a href="https://instagram.com/gndx">
            <img src="${instagram}" />
          </a>
</div>

Una vez terminada la configuraci贸n, cuando el navegador haga render de las vistas del proyecto las im谩genes ser谩n importadas y se les asignar谩 un c贸digo hash.

As铆, el archivo de configuraci贸n de Webpack quedar铆a as铆:

const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const { resourceUsage } = require('process');

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'main.js',
        assetModuleFilename: 'assets/images/[hash][ext][query]'
    },
    resolve: {
        extensions: ['.js'],
    },
    module: {
        rules: [
            {
                test: /\.m?js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader'
                }
            },
            {
                test: /\.css|.styl$/i,
                use: [MiniCssExtractPlugin.loader,
                    'css-loader',
                    'stylus-loader'
                ],
            },
            {
                test: /\.png/, // indicamos el listado de archivos a los cuales vamos a dar tratamiento
                type: 'asset/resource', // Permite la importaci贸n del recurso en el template
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            inject: true,
            template: './public/index.html',
            filename: './index.html'
        }),
        new MiniCssExtractPlugin(),
        new CopyPlugin({
            patterns: [
                {
                    from: path.resolve(__dirname, "src", "assets/images"),
                    to: "assets/images"
                }
            ]
        })
    ]
}

Loaders de fuentes

Configurar las fuentes en Webpack es mucho m谩s eficiente que llamarlas desde un CDN. Por eso, es importante incorporarlas a nuestro proyecto y Webpack nos proporciona la manera de hacerlo.

Desde Google Fonts puedes descargar gran cantidad de fuentes; sin embargo, no ofrece la posibilidad de descargarlas con la extensi贸n de archivo .woff, este tipo de archivo ofrece una fuente optimizada para ser utilizada en la web.

Con esta utilidad podr谩s obtener las fuentes optimizadas para ser utilizadas en tus proyectos.

1. Instalaci贸n de los recursos necesarios

Para que podamos utilizar las fuentes, debemos hacer que se copien los archivos de fuentes desde la carpeta src hacia dist las fuentes. Entonces, se debe instalar dos recursos: uno para leerlos y otro para moverlos seg煤n el caso.

Instalaci贸n de los recursos url-loader y file-loader

npm install url-loader file-loader 鈥揇

2 Configuraci贸n del archivo config.webpack.js

Dentro del arreglo rules del objeto module, agregamos las siguientes configuraciones.

{
                test: /\.(woff|woff2)$/, // Expresi贸n regular para que utilice las extensiones de archivo
                use: {
                    loader: 'url-loader',
                    options: {
                        limit: 10000,
                        mimetype: "application/font-woff", // "Especificamos de que tipo de archivo se trata"
                        name: "[name].[ext]", // Indicamos que respete el nombre y la extensi贸n que tiene la fuente
                        outputPath: "./assets/fonts", // Indicamos hacia donde se va a dirigir el recurso
                        publicPath: "./assets/fonts", // Tambi茅n es necesario asignar un public path
                        esModule: false
                    }
                }
            }

2. Agregamos las propiedades CSS para la utilizaci贸n de las fuentes en nuestro proyecto

@font-face{
	font-family: 'Ubuntu';
	src: url('../assets/fonts/ubuntu-regular.woff2') format('woff2'),
		url('../assets/fonts/ubuntu-regular.woff') format('woff');
	font-weight: 400; /* 400 es normal */
	font-style: normal;
}

Hasta el momento, el documento de configuraci贸n est谩 as铆:

const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const { resourceUsage } = require('process');

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'main.js',
        assetModuleFilename: 'assets/images/[hash][ext][query]'
    },
    resolve: {
        extensions: ['.js'],
    },
    module: {
        rules: [
            {
                test: /\.m?js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader'
                }
            },
            {
                test: /\.css|.styl$/i,
                use: [MiniCssExtractPlugin.loader,
                    'css-loader',
                    'stylus-loader'
                ],
            },
            {
                test: /\.png/, // indicamos el listado de archivos a los cuales vamos a dar tratamiento
                type: 'asset/resource', // Permite la importaci贸n del recurso en el template
            },
            {
                test: /\.(woff|woff2)$/, // Expresi贸n regular para que utilice las extensiones de archivo
                use: {
                    loader: 'url-loader',
                    options: {
                        limit: 10000,
                        mimetype: "application/font-woff", // "Especificamos de que tipo de archivo se trata"
                        name: "[name].[ext]", // Indicamos que respete el nombre y la extensi贸n que tiene la fuente
                        outputPath: "./assets/fonts", // Indicamos hacia donde se va a dirigir el recurso
                        publicPath: "./assets/fonts", // Tambi茅n es necesario asignar un public path
                        esModule: false
                    }
                }
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            inject: true,
            template: './public/index.html',
            filename: './index.html'
        }),
        new MiniCssExtractPlugin(),
        new CopyPlugin({
            patterns: [
                {
                    from: path.resolve(__dirname, "src", "assets/images"),
                    to: "assets/images"
                }
            ]
        })
    ]
}

Optimizaci贸n de un proyecto web

En este apartado te explicar茅 la forma de optimizar los recursos que intervienen en el funcionamiento de un proyecto web. Esto, con el fin de que cargue r谩pido y funcione de forma eficiente para los usuarios finales.

驴Qu茅 se optimizar谩? Se optimizar谩n hashes y se realizar谩n tareas de compresi贸n y minificaci贸n de archivos.

1. Minimizar JavaScript y CSS

1.1 Instalaci贸n de las dependencias

npm install css-minimizer-webpack-plugin terser-webpack-plugin -D

1.2 Requerimos los plugins instalados en el punto 1.1 en nuestro archive de configuraci贸n de Webpack

const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');

1.3 Creamos un nuevo objeto llamado 鈥渙ptimization鈥 justo debajo del arreglo 鈥減lugins鈥 en webpack.config.js

En este objeto se colocar谩n todas las configuraciones de optimizaci贸n.

optimization: {
        minimize: true,
        minimizer: [
            new CssMinimizerPlugin(),
            new TerserPlugin(),
        ]
    }

2. Optimizaci贸n Hash

Esta optimizaci贸n es recomendada si deseamos saber si ha cambiado la versi贸n de los archivos en el momento de realizar un nuevo build (empaquetado del proyecto). Entonces, seg煤n el documento de configuraci贸n que se ha venido trabajando, cambiaremos la estructura del nombre de: 鈥渕ain.js鈥, tambi茅n el nombre de nuestras fuentes de texto y el archivo CSS.

2.1 Cambio del filename

En el output de webpack, cambiamos la propiedad del filename por la siguiente

filename: '[name].[contenthash].js',

2.2 Cambio de nombre a c贸digo hash de las fuentes de texto

Cambiamos la propiedad name del objeto options ubicado en el objeto use de la configuraci贸n de las fuentes en webpack.config.js

name: 鈥淸name].[contenthash].[ext]鈥,

2.3 Cambio de nombre para el archivo CSS

Pasamos como par谩metro una configuraci贸n en el objeto MiniCssExtractPlugin del arreglo plugins.

new MiniCssExtractPlugin({
            filename: 'assets/[name].[contenthash].css'
        }),

Hasta este punto, el archivo de configuraci贸n luce as铆:

const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const { resourceUsage } = require('process');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].[contenthash].js',
        assetModuleFilename: 'assets/images/[hash][ext][query]'
    },
    resolve: {
        extensions: ['.js'],
    },
    module: {
        rules: [
            {
                test: /\.m?js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader'
                }
            },
            {
                test: /\.css|.styl$/i,
                use: [MiniCssExtractPlugin.loader,
                    'css-loader',
                    'stylus-loader'
                ],
            },
            {
                test: /\.png/, // indicamos el listado de archivos a los cuales vamos a dar tratamiento
                type: 'asset/resource', // Permite la importaci贸n del recurso en el template
            },
            {
                test: /\.(woff|woff2)$/, // Expresi贸n regular para que utilice las extensiones de archivo
                use: {
                    loader: 'url-loader',
                    options: {
                        limit: 10000,
                        mimetype: "application/font-woff", // "Especificamos de que tipo de archivo se trata"
                        name: "[name].[contenthash].[ext]", // Indicamos que respete el nombre y la extensi贸n que tiene la fuente
                        outputPath: "./assets/fonts", // Indicamos hacia donde se va a dirigir el recurso
                        publicPath: "./assets/fonts", // Tambi茅n es necesario asignar un public path
                        esModule: false
                    }
                }
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            inject: true,
            template: './public/index.html',
            filename: './index.html'
        }),
        new MiniCssExtractPlugin({
            filename: 'assets/[name].[contenthash].css'
        }),
        new CopyPlugin({
            patterns: [
                {
                    from: path.resolve(__dirname, "src", "assets/images"),
                    to: "assets/images"
                }
            ]
        })
    ],
    optimization: {
        minimize: true,
        minimizer: [
            new CssMinimizerPlugin(),
            new TerserPlugin(),
        ]
    }
}

Webpack Alias

Webpack permite generar alias para ubicar m谩s f谩cilmente los archivos de dependencias de nuestros proyectos.

Por ejemplo en el archivo index.js de la carpeta src, estamos requiriendo otros archivos ubicados en diferentes carpetas. Algunas veces, esta b煤squeda se hace compleja y las rutas pueden quiz谩 ser tan complejas que las olvidamos o no sabemos c贸mo acceder a ellas.

Entonces, generando alias, solucionamos este problema.

1. Configuraci贸n de alias en Webpack

Dentro del objeto resolve, creamos un objeto llamado alias que contendr谩 las configuraciones que necesitamos.

Alias: {
}

2 Identificaci贸n de carpetas

Luego, debemos identificar las carpetas que estamos utilizando en el desarrollo del proyecto dentro de la carpeta src. Estas carpetas son las que vamos a configurar dentro del objeto alias, realizado en el punto 1.

3. Configuraci贸n de los alias

Dentro del objeto alias creado en el punto 1, agregamos el siguiente c贸digo:

'@utils': path.resolve(__dirname, 'src/utils/'),
'@templates': path.resolve(__dirname, 'src/templates/'),
'@styles': path.resolve(__dirname, 'src/styles/'),
'@images': path.resolve(__dirname, 'src/assets/images/')
  • '@utils'鈥 Es el alias asignado a la resoluci贸n de la direcci贸n de donde se encuentra el recurso.

Con esto, podemos utilizar los alias generados en las rutas que se referencian en nuestro proyecto.

Ejemplo sin alias

import Template from './templates/Template.js';
import './styles/main.css';
import './styles/main.styl';
import instagram from '../assets/images/instagram.png';
import twitter from '../assets/images/twitter.png';
import github from '../assets/images/github.png';

Ejemplo con alias

import Template from '@templates/Template.js';
import '@styles/main.css';
import '@styles/main.styl';
import instagram from '@images/instagram.png';
import twitter from '@images/twitter.png';
import github from '@images/github.png';

Finalmente, el archivo de configuraci贸n de Webpack quedar铆a as铆:

const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const { resourceUsage } = require('process');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].[contenthash].js',
        assetModuleFilename: 'assets/images/[hash][ext][query]'
    },
    resolve: {
        extensions: ['.js'],
        alias: {
            '@utils': path.resolve(__dirname, 'src/utils/'),
            '@templates': path.resolve(__dirname, 'src/templates/'),
            '@styles': path.resolve(__dirname, 'src/styles/'),
            '@images': path.resolve(__dirname, 'src/assets/images/')
        }
    },
    module: {
        rules: [
            {
                test: /\.m?js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader'
                }
            },
            {
                test: /\.css|.styl$/i,
                use: [MiniCssExtractPlugin.loader,
                    'css-loader',
                    'stylus-loader'
                ],
            },
            {
                test: /\.png/, // indicamos el listado de archivos a los cuales vamos a dar tratamiento
                type: 'asset/resource', // Permite la importaci贸n del recurso en el template
            },
            {
                test: /\.(woff|woff2)$/, // Expresi贸n regular para que utilice las extensiones de archivo
                use: {
                    loader: 'url-loader',
                    options: {
                        limit: 10000,
                        mimetype: "application/font-woff", // "Especificamos de que tipo de archivo se trata"
                        name: "[name].[contenthash].[ext]", // Indicamos que respete el nombre y la extensi贸n que tiene la fuente
                        outputPath: "./assets/fonts", // Indicamos hacia donde se va a dirigir el recurso
                        publicPath: "../assets/fonts", // Tambi茅n es necesario asignar un public path
                        esModule: false
                    }
                }
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            inject: true,
            template: './public/index.html',
            filename: './index.html'
        }),
        new MiniCssExtractPlugin({
            filename: 'assets/[name].[contenthash].css'
        }),
        new CopyPlugin({
            patterns: [
                {
                    from: path.resolve(__dirname, "src", "assets/images"),
                    to: "assets/images"
                }
            ]
        })
    ],
    optimization: {
        minimize: true,
        minimizer: [
            new CssMinimizerPlugin(),
            new TerserPlugin(),
        ]
    }
}

Newsletter

* Campo requerido

Powered by Mailchimp

Manual instructivo de Webpack