Curso de Webpack 4 – Iniciación

¿Que es Webpack?

Webpack es un empaquetador de módulos para el desarrollo de aplicaciones Javascript, ya que las aplicaciones que se desarrollan y se están desarrollando actualmente son cada día mas complejas y requieren de múltiples tipos de ficheros, tales como .css, .sass, .jpg, .png, .js, .ts, etc.. y los navegadores actuales son incapaces de interpretar.

Para usar estos u otros tipos de archivos y que el navegador pueda interpretarlos se usan los módulos, y estos se pueden controlar de múltiples formas.

Una de las formas es mediante AMD (Asynchronous module definition) y la librería mas conocida y usada es require.js. Dentro de un fichero de javascript se importan/incluyen todas las librerías necesarias, y estas se llamaran según se vayan necesitando.

La ventaja es que la carga inicial es muy rápida, pero la desventaja es que estamos realizando múltiples llamadas y eso al final nos acabara penalizando, porque el navegador tiene limitado el número de peticiones.

Para solucionar el problema de las múltiples peticiones, apareció CommonJS (Sistema de módulos de node.js). En un fichero de javascript se importan/incluyen todas las librerías necesarias y todas estas librerías quedaran empaquetadas en un único fichero.

La principal ventaja es que solo se realizara una única llamada, pero la desventaja que esa llamada sera mucho mas pesada ya que incluye todo el código de todas las librerías que vamos a necesitar.

Bueno pues aquí es donde aparece webpack, y que une lo mejor de cada gestor de módulos (AMD y CommonJS).

Empezando con webpack

Lo primero de todo, desde áqui accedemos al repositorio en Github y desde aquí al ejemplo.

Ahora vamos a empezar definiendo algunos términos para poder entender las «tripas» de webpack:

  • Entry points: El punto de entrada y es el fichero donde se comenzara a importar los demás módulos. Este sera el archivo que webpack va a leer para generar el bundle.
  • Output: Esta parte define la configuración del archivo de salida,  su nombre y donde estará guardado.
  • Loaders: Añade funcionalidades que permiten interpretar archivos con otras extensiones en nuestro código javasciprt.
  • Plugins: Extiende las características de webpack realizando la minificación de los archivos o por ejemplo dividirlos en archivos mas pequeños para su distribución

Instalación del entorno

Para que webpack funcione necesitamos node.js y npm. Pulsando sobre los enlaces anteriores puedes descargar las herramientas necesarias.

Cuando instalas node.js tambien se instala npm (node package manager) por defecto y para comprobar que esta funcionando correctamente usaremos los siguientes comandos:

  • node -v, mostrara la versión que tenemos instalada de node.js (v6.11.2 esta es mi versión)
  • npm -v, mostrara la versión que tenemos instalada de npm (6.0.1 esta es mi versión)

Si todo es correcto podemos continuar con la instalación de webpack.

Vamos a iniciar un proyecto en javascript desde cero y poder usar webpack. Creamos una carpeta con el nombre que deseemos, en mi caso la he llamado ‘webpack-project‘.

Una vez dentro de la carpeta vamos a inicializar un proyecto con npm, usando el siguiente comando:

  • npm init, para iniciar el proceso manual
  • npm init -y, para iniciar el proceso automático

Este comando comenzara un proceso para la configuración del proyecto y que al finalizar nos creara un fichero de configuración llamado package.json.

package.json

{
  "name": "webpack-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Con los pasos anteriores ya tenemos nuestro proyecto básico para empezar a desarrollar e instalar las dependencias necesarias, en nuestro caso webpack.

Desde nuestra consola vamos a usar el siguiente comando: npm i webpack webpack-cli –save-dev. (corresponde a la versión 4 de webpack ya que ahora viene por separado el CLI)

  • i o install, indicamos que vamos a instalar un nueva dependencia y se guarde en nuestro fichero package.json.
  • webpack webpack-cli, nombre del paquete/s.
  • –save-dev, opción que usamos para indicar que se instale solo como dependencia para desarrollo y evitar que se empaquete para producción.

Comandos básicos para NPM

Aunque no corresponde al curso voy a poner algunos ejemplo de flags usados en npm y que son los que mas se usan:

  • npm i/install, Se instalan en la carpeta donde se encuentre la terminal de comandos, NO se registran en el archivo package.json.
  • npm i/install paquete –save-dev/-D, se instalan en la carpeta donde se encuentre la terminal de comandos, SI se registran en el archivo package.json como dependencias de desarrollo del proyecto, esto significa que facilitan y optimizan las tareas comunes de desarrollo y publicación del proyecto.
  • npm i/install paquete –save/-S, Se instalan en la carpeta donde se encuentre la terminal de comandos, SI se registran en el archivo package.json como dependencias del proyecto, esto significa que el proyecto requiere de éstos paquetes para funcionar.
  • npm i/install paquete –global/-g, Se instalan localmente en el ordenador independientemente de donde se encuentre la terminal de comandos, esto significa que estarán disponibles en todas las carpetas del ordenador, NO se registran en el archivo package.json.
  • npm uninstall paquete –global/-g, elimina el paquete de forma global.
  • npm uninstall paquete –save/-S, elimina el paquete de nuestra dependencia.
  • npm uninstall paquete –save-dev/-D, elimina el paquete de nuestra dependencia de desarrollo.

Una ultima apreciación sobre npm package.json, cuando revises las dependencias instaladas justo lado se muestra un número que nos indica la versión que tenemos, por ejemplo: «webpack»:»^4.8.3″.

Al inicio de la versión aparece un carácter, pues ese carácter dependiendo del tipo que usemos nos puede variar la versión que npm debe descargar cuando nos traiga las dependencias. A continuación un pequeño ejemplo sacado de la documentación de npm:

  • ~version: Una versión aproximadamente equivalente
  • ^version: Una versión compatible o superior
    • ^1.2.3: >=1.2.3 y <2.0.0
  • version: La misma versión
  • >version: Una versión superior
  • >=version: Una versión igual o superior
  • <, <=,=: Versiones usando otros operadores de comparación
  • 1.2.x: Desde la versión 1.2.0 hasta 1.2.9
  • *: Cualquier versión
  • latest: Ultima versión liberada

Continuamos con webpack

Una vez terminada la instalación de webpack, con el comando npx webpack -v ( uso npx para poder ejecutar webpack como dependencia no global) si esta instalado correctamente y la versión que se ha instalado (en mi caso la 4.8.3)

Vamos a comprobar de nuevo nuestro archivo package.json.

Podemos ver que ahora tiene una nueva linea al final que se llama «devDependencies»:

{
  "name": "webpack-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.8.3",
    "webpack-cli": "^2.1.3"
  }
}

Dentro de esa definición se añadirán las dependencias que instalemos con el flag –save-dev o -D.

Si todo el proceso de instalación es correcto desde la consola podemos ejecutar el siguiente comando:

  • npx webpack -v, nos muestra la versión de webpack (4.2.0)

npx ejecuta un <comando> desde node_modules/ .bin local, o desde un caché central, instalando los paquetes necesarios para que se ejecute un <comando>.

Por defecto, npx comprobará si <comando> existe en $ PATH, o en los binarios del proyecto local, y lo ejecutará. Si no se encuentra <comando>, se instalará antes de la ejecución.

Creando nuestro primer bundle

Para comenzar necesitamos tener un fichero en javascript que sera nuestro entry point (punto de entrada) en la configuración de webpack.

Para nuestro ejemplo le llamaremos index.js y no tiene mucho código:

alert("Hola mundo");

Desde la consola vamos a ejecutar npx webpack –mode development (webpack por defecto esta en modo producción y nos crea el fichero minificado)  –entry ./index.js(fichero de entrada) –ouput bundle.js(fichero de salida).

Para evitar tener que estar ejecutando este comando constantemente vamos añadirlo a nuestro fichero package.json en la zona de script para que sea mas cómodo de ejecutar.

{
  "name": "webpack-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --mode development --entry ./index.js --output bundle.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.8.3",
    "webpack-cli": "^2.1.3"
  }
}

Lo único que hemos hecho es añadir una nueva linea dentro de la sección de scripts, que se compone de el nombre del script y orden que ejecuta.

Para ejecutar este script usaremos el comando npm run nombre de script, en nuestro caso sería así: npm run build.

Configurando webpack con webpack.config.js

Para comenzar debemos crear un fichero que se llame webpack.config.js. Este fichero tendrá toda la configuración de webpack para nuestro proyecto.

// El módulo path proporciona utilidades para trabajar con rutas de archivos y directorios
// Evitamos conflictos con node, ya que windows y linux tienen diferentes estilos de rutas
const path = require("path");

// Exportamos como un módulo de commonjs
module.exports = {
    // Modo desarrollo, ya que webpack por defecto esta en modo producción
    mode: 'development',
    // Nuestro punto de entrada
    entry: path.join(__dirname, 'index.js'),
    // Nuestra salida
    output: {
        // Obtenemos la ruta absoluta
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    }
}

También modificamos el fichero index.js para añadir algo mas de contenido

//alert("Hola mundo");
var MATEMATICAS = MATEMATICAS || {};
MATEMATICAS = {
    suma: (a, b) => a + b,
    resta: (a, b) => a - b,
    multiplicacion: (a, b) => a * b,
    division: (a, b) => a / b
};
console.log(MATEMATICAS.suma(1,2));
console.log(MATEMATICAS.resta(1,2));
console.log(MATEMATICAS.multiplicacion(1,2));
console.log(MATEMATICAS.division(1,2));

Con ambos ficheros creados ahora abrimos el fichero package.json y desde allí añadimos una nueva linea dentro de scripts..

{
  "name": "webpack-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --mode development --entry ./index.js --output bundle.js",
    "webpack-build": "webpack --mode development"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.8.3",
    "webpack-cli": "^2.1.3"
  }
}

Dentro de scripts se ha añadido un nuevo script llamado webpack-build que únicamente ejecutara webpack. 

Cuando ejecutas webpack automáticamente busca el fichero de configuración y se ejecuta con los parámetros que hemos añadido.

Si esta todo bien configurado, ejecutaremos desde la consola el siguiente comando: npm run webpack-build. 

Con este comando estamos ejecutando el contenido de ese script, en este caso webpack y cuando este se ejecute buscara el archivo webpack.config.js para poder usar esa configuración.

Loaders

Los loaders como decíamos al principio de este curso nos ayudan a interpretar archivos de otras extensiones en nuestro código javascript.

Para usar loaders necesitamos incluirlos en el webpack.config.js.

Dentro del fichero de configuración, debemos definir una nueva sección llamada module, y dentro de module debemos definir rules. Rules es un array con la lista de loaders que necesitamos.

Dentro de el nivel rules para este ejemplo tenemos dos secciones, test use. En test añadimos el tipo de archivo que necesitamos y en use los loaders necesarios.

Para este ejemplo vamos a usar css así que debemos instalar desde la consola los loaders necesarios. Usamos npm para la instalación con el siguiente comandos: npm i style-loader y css-loader –save-dev.

Una vez mas usando el flag –save-dev se instala como dependencia de desarrollo, y si revisamos el fichero package.json veremos que se han añadido nuevas devDependencies.

A continuación los ficheros que he usado hasta ahora mismo con su código comentado.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>WEBPACK</title>
</head>
<body>
    <p>
        Hola mundo, WEBPACK!!!!
    </p>
    <script src="./dist/bundle.js"></script>
</body>
</html>

style.css

body {
    font-size: 30px;
    color: #00aadd;
    background: #000000;
}

package.json

{
  "name": "webpack-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --mode development --entry ./index.js --output bundle.js",
    "webpack-build": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "css-loader": "^0.28.11",
    "style-loader": "^0.21.0",
    "webpack": "^4.8.3",
    "webpack-cli": "^2.1.3"
  }
}

webpack.config.js

// El módulo path proporciona utilidades para trabajar con rutas de archivos y directorios
// Evitamos conflictos con node, ya que windows y linux tienen diferentes estilos de rutas
const path = require("path");

// Exportamos como un módulo de commonjs
module.exports = {
    // Modo desarrollo, ya que webpack por defecto esta en modo producción
    mode: 'development',
    // Nuestro punto de entrada
    entry: path.join(__dirname, 'index.js'),
    // Nuestra salida
    output: {
        // Obtenemos la ruta absoluta
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    },
    module: {
        // Array con la lista de loaders
        rules: [{
            // test: que tipo de archivo 
            test: /\.css$/,
            // use: Array o texto con el/los loader(s) que se va encargar el archivo
            use: [
                // Estos y muchos otros loaders son necesarios descargar
                // Respetar el orden en la declaración de los loaders, porque cambiando el orden no funciona.
                // Explicación oficial: https://webpack.js.org/configuration/module/#rule-use
                // Los loaders pueden encadenarse pasando varios loaders, que se aplicarán de derecha a izquierda (de la última a la primera configuración).

                // style-loader: Permite imprimir el archivo css en pantalla insertándolos en una etiqueta style dentro del head
                { loader: 'style-loader' },
                // css-loader: Permite cargar archivos css e interpretarlos dentro de js
                // import "style.css" -> dentro de Javascript
                { loader: 'css-loader'}
            ]
          }
       ]
    }
}

Bien, ya hemos conseguido en este ejemplo por medio de loaders insertar en una etiqueta style  nuestros estilos.

Viendo el resultado de aplicar loaders en webpack, ya podemos confirmar que los loaders son transformaciones que se aplican en el código fuente de un módulo.

Permiten preprocesar archivos a medida que los importa o los «carga». Por lo tanto, los loaders son algo así como «tareas» en otras herramientas de compilación, y proporcionan una forma poderosa de gestionar los pasos de compilación de aplicaciones para el usuario.

Los loaders pueden transformar archivos de un lenguaje diferente como TypeScript a JavaScript o imágenes en línea como URL de datos.

Los loaders incluso te permiten hacer cosas como importar archivos CSS directamente desde tus módulos de JavaScript.

Plugins

Los plugins son la columna vertebral de webpack. El propio webpack está construido sobre el mismo sistema de complementos que usas en la configuración de tu paquete web.

También sirven para hacer todo lo que un loader no puede hacer. Estupendo, ¿pero que diferencia existe entre plugins loaders?

  • Loaders: Son intérpretes, parsers y pre-procesadores.
  • Plugins: Son librerías, métodos que aportan funcionalidades particulares en Javascript al entorno de webpack.

Con esta pequeña definición vamos a realizar un ejemplo que aclare todo esto.

Para usar un plugin es necesario definir una nueva estructura dentro de webpack llamada plugins.

En este array (plugins) dentro del fichero webpack.config.js de configuración usaremos nuestro plugin y su configuración.

Para poder usar el plugin en webpack es necesario instalar la dependencia y luego importarlo como si fuera un módulo de node.js, de la misma forma que importamos el módulo path dentro de webpack.

Para este ejemplo voy a usar el plugin babel-webpack-pluginporque nos permite transformar nuestro código Javascript de última generación (o con funcionalidades extras, ES6, etc..) a Javascript que cualquier navegador o versión de Node.js entienda.

En la consola ejecutamos el siguiente comando: npm i babel-webpack-plugin –save-dev.

Ahora vamos a importar el módulo para poder usarlo en nuestro plugin con la siguiente linea dentro de webpack.config.js: const BabelPlugin = require(«babel-webpack-plugin«);

Para finalizar debemos declarar el plugin y su configuración dentro de la sección plugins y así poder usarlo.

A continuación el código que hemos generado hasta este momento, porque los enlaces al repositorio y el ejemplo funcionando están al principio del curso.

index.js

import "./css/style.css"
//alert("Hola mundo");
var MATEMATICAS = MATEMATICAS || {};
MATEMATICAS = {
    suma: (a, b) => a + b,
    resta: (a, b) => a - b,
    multiplicacion: (a, b) => a * b,
    division: (a, b) => a / b
};
console.log(MATEMATICAS.suma(1,2));
console.log(MATEMATICAS.resta(1,2));
console.log(MATEMATICAS.multiplicacion(1,2));
console.log(MATEMATICAS.division(1,2));

// Comprobaciones ES6 y ES7 para babel webpack
// Arrow functions
// Original
/*((win, doc) => {
    console.log(doc);
    console.log(win);
})(window, document);*/
((win, doc) => {
    console.log("ARROW FUNCTION");
    console.log(doc);
    console.log(win);
})(window, document);

// Original
/*let a = [2,4,6,8,10];
console.log(a);
let r = a.map(n => n*n);
console.log(r);*/
console.log("ARROW FUNCTION Y MAP");
let a = [2,4,6,8,10];
console.log(a);
let r = a.map(n => n*n);
console.log(r);

// Clases
// Original
/*class Humano {
    constructor(_sexo, _edad) {
        this.sexo = _sexo;
        this.edad = _edad;
    }
    getEdad() {
        return this.edad;
    }
    getSexo() {
        return this.sexo;
    }
}
let Maria = new Humano("Hembra", 20);
let David = new Humano("Varon", 30);*/
console.log("CLASES JAVASCRIPT");
class Humano {
    constructor(_sexo, _edad) {
        this.sexo = _sexo;
        this.edad = _edad;
    }
    getEdad() {
        return this.edad;
    }
    getSexo() {
        return this.sexo;
    }
}
let Maria = new Humano("Hembra", 20);
let David = new Humano("Varon", 30);
console.log(Maria.getEdad(), Maria.getSexo());
console.log(David.getEdad(), David.getSexo());

webpack.config.js

// El módulo path proporciona utilidades para trabajar con rutas de archivos y directorios
// Evitamos conflictos con node, ya que windows y linux tienen diferentes estilos de rutas
const path = require("path");
// Importamos babel para usarlo dentro de la sección de plugins
const BabelPlugin = require("babel-webpack-plugin");

// Exportamos como un módulo de commonjs
module.exports = {
    // Modo desarrollo, ya que webpack por defecto esta en modo producción
    mode: 'development',
    // Nuestro punto de entrada
    entry: path.join(__dirname, 'index.js'),
    // Nuestra salida
    output: {
        // Obtenemos la ruta absoluta
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    },
    module: {
        // Array con la lista de loaders
        rules: [{
            // test: que tipo de archivo 
            test: /\.css$/,
            // use: Array o texto con el/los loader(s) que se va encargar el archivo
            use: [
                // Estos y muchos otros loaders son necesarios descargar
                // Respetar el orden en la declaración de los loaders, porque cambiando el orden no funciona.
                // Explicación oficial: https://webpack.js.org/configuration/module/#rule-use
                // Los loaders pueden encadenarse pasando varios loaders, que se aplicarán de derecha a izquierda (de la última a la primera configuración).

                // style-loader: Permite imprimir el archivo css en pantalla insertándolos en una etiqueta style dentro del head
                { loader: 'style-loader' },
                // css-loader: Permite cargar archivos css e interpretarlos dentro de js
                // import "style.css" -> dentro de Javascript
                { loader: 'css-loader'}
            ]
          }
       ]
    },
    plugins: [
        // Array con la lista de plugins
        new BabelPlugin({
            test: /\.js$/,
            presets: ['es2015'],
            sourceMaps: false,
            compact: false
        })
    ]
}

package.json

{
  "name": "webpack-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --mode development --entry ./index.js --output bundle.js",
    "webpack-build": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-webpack-plugin": "^0.1.1",
    "css-loader": "^0.28.11",
    "style-loader": "^0.21.0",
    "webpack": "^4.8.3",
    "webpack-cli": "^2.1.3"
  }
}

Multiples entry points

Este punto es bastante reducido, y lo agrego porque me ha parecido interesante de cara a una personalización de webpack y la organización para proyectos grandes.

En algún proyecto, ya sea personal o profesional nos podemos encontrar que necesitemos tener múltiples puntos de entrada, pues con webpack no tendríamos ningún problema en gestionarlo.

Webpack nos permite usar un objeto JSON como punto de entrada, y allí añadir todos los ficheros que necesitemos.

Dentro de ese objeto JSON, definiremos una key (nombre) y su valor (ruta) (linea 13).

También debemos cambiar el objeto JSON output, y en vez de usar un nombre fijo (bundle.js), usar [name].js (linea 22).

webpack.config.js

// El módulo path proporciona utilidades para trabajar con rutas de archivos y directorios
// Evitamos conflictos con node, ya que windows y linux tienen diferentes estilos de rutas
const path = require("path");
// Importamos babel para usarlo dentro de la sección de plugins
const BabelPlugin = require("babel-webpack-plugin");

// Exportamos como un módulo de commonjs
module.exports = {
    // Modo desarrollo, ya que webpack por defecto esta en modo producción
    mode: 'development',
    // Nuestro punto de entrada
    //entry: path.join(__dirname, 'index.js'),
    entry: {
        "index": path.join(__dirname, 'index.js'),
        "contacto": path.join(__dirname, 'contacto.js')
    },
    // Nuestra salida
    output: {
        // Obtenemos la ruta absoluta
        path: path.resolve(__dirname, 'dist'),
        //filename: 'bundle.js'
        filename: '[name].js'
    },
    module: {
        // Array con la lista de loaders
        rules: [{
            // test: que tipo de archivo 
            test: /\.css$/,
            // use: Array o texto con el/los loader(s) que se va encargar el archivo
            use: [
                // Estos y muchos otros loaders son necesarios descargar
                // Respetar el orden en la declaración de los loaders, porque cambiando el orden no funciona.
                // Explicación oficial: https://webpack.js.org/configuration/module/#rule-use
                // Los loaders pueden encadenarse pasando varios loaders, que se aplicarán de derecha a izquierda (de la última a la primera configuración).

                // style-loader: Permite imprimir el archivo css en pantalla insertándolos en una etiqueta style dentro del head
                { loader: 'style-loader' },
                // css-loader: Permite cargar archivos css e interpretarlos dentro de js
                // import "style.css" -> dentro de Javascript
                { loader: 'css-loader'}
            ]
          }
       ]
    },
    plugins: [
        // Array con la lista de plugins
        new BabelPlugin({
            test: /\.js$/,
            presets: ['es2015'],
            sourceMaps: false,
            compact: false
        })
    ]
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>WEBPACK</title>
</head>
<body>
    <p>
        Hola mundo, WEBPACK!!!!
    </p>
    <!--<script src="./dist/bundle.js"></script>-->
    <script src="dist/index.js"></script>
    <script src="dist/contacto.js"></script>
</body>
</html>

Webpack DevServer (Servidor de desarrollo)

Cada vez que hacemos cambios sobre el código debemos ejecutar de nuevo el script en npm para que podamos ver los cambios en la pantalla.

Si esa tarea la realizas un par de veces no es molesto, pero si tienes que estar modificando el código muchas veces lo mejor es tener un sistema que este esperando a que existan cambios para actualizar nuestra pantalla.

Para esta tarea existe varias formas, la primera es usar watch: true dentro de nuestro fichero webpack.config.js, quedando webpack a la escucha para cualquier cambio.

Esta forma esta bien y es simple pero…., los cambios se han guardado pero la página tenemos que recargar nosotros manualmente.

Para ejecutar esta tarea vamos a usar una nueva dependencia y la vamos a instalar con npm: npm i webpack-dev-server -D

Una vez instalado deberíamos añadir un nuevo script en nuestro package.json para que todo sea mas cómodo si lo tenemos que ejecutar.

Cuando ejecutemos el script de npm debería actualizarse nuestra página cada vez que hagamos algún cambio.

En la linea 10 se muestra el nuevo script en npm, en la linea 21 el repositorio instalado.

package.json

{
  "name": "webpack-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --mode development --entry ./index.js --output bundle.js",
    "webpack-build": "webpack",
    "webpack-dev-server": "webpack-dev-server"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-webpack-plugin": "^0.1.1",
    "css-loader": "^0.28.11",
    "style-loader": "^0.21.0",
    "webpack": "^4.8.3",
    "webpack-cli": "^2.1.3",
    "webpack-dev-server": "^3.1.4"
  }
}

A continuación un vídeo con una pequeña prueba de los cambios en cada vez que guardamos

Bien con esto he terminado el módulo de iniciación de Webpack 4. Me gustaría continuar con otros 2 módulos mas, uno de nivel medio dedicado al soporte de EcmaScript, imágenes, videos, fuentes, Sass  y un último módulo de webpack avanzado con algunos conceptos como la selección de dependencias mas comunes, cargar módulos asíncronos e intentar hacer un proyecto real usando webpack.

Nos vemos en el próximo curso y/o articulo.