Estructura del proyecto

Vamos a empezar creando un directorio de trabajo al que llamaremos webpack-base mkdir webpack-base y a continuación arrastramos el directorio a VSCode.

Ahora creamos una estructura básica para nuestro proyecto Javascript:

Creamos el directorio src (source) que contendrá la mayor parte de nuestro código, dentro creamos un directorio al que llamaremos componentes con todos nuestros módulos, un directorio scss para nuestros estilos y el directorio assets para nuestros recursos gráficos y normalmente también para nuestros estilos (css). Creamos también en el directorio src un index.html donde renderizaremos nuestra aplicación y un index.js que usará los módulos para renderizar la app.

Una vez creada nuestra estructura básica de directorios y archivos vamos a crear nuestro package.json, Para ello ejecutamos el comando npm init -y. Necesitaremos tener Node instalado.

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

Hasta ahora, nos hemos centrado en la estructura básica de nuestro proyecto pero todavía no hemos empezado con la configuración de webpack.

Instalación y configuración de package.json y webpack.config.js

Primero tenemos que instalar webpack con el siguiente comando npm i --save-dev webpack webpack-cli.

A partir de aquí vamos a centrarnos en la configuración de package.json y de webpack.config.js.

Vamos a realizar primero una configuración básica a package.json. Añadimos lo siguiente en el apartado scripts:

 "scripts": {
 	"build": "webpack build",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

A continuación escribimos en el terminal npm run build. Vemos como se nos ha creado un directorio llamado dist en nuestra estructura de directorios. También vemos un aviso en el terminal como el siguiente:

Para evitar este warning vamos a añadir lo siguiente en nuestro package.json quedando este de la siguiente manera:

{
  "name": "webpack-base",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack --mode production",
    "dev": "webpack --mode development --watch",
    "test": "echo \"Error: no test specified\" && exit 1",
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^5.38.1",
    "webpack-cli": "^4.7.0"
  }
}

Vamos a centrarnos ahora en la creación y configuración del archivo webpack.config.js que crearemos en el mismo nivel que package.json.

Configuración webpack.config.js:

const path = require("path");

module.exports = {
    entry: "./src/index.js",
    output: {
        filename: "app.js",
        path: path.resolve(__dirname, "dist"),
        publicPath: "./",
        assetModuleFilename: 'assets/images/[name][ext][query]'
    }
}

De momento, tenemos configuradas dos secciones dentro de module.exports, la entrada donde seleccionaremos nuestro archivo .js principal (index.js) y la salida (dist) donde tenemos especificado el nombre del .js compilado (app.js).

Instalación de paquetes y reconfiguraciones

Empezamos con la instalación de los siguientes loaders para poder dar estilo a nuestra aplicación: npm i -D sass-loader css-loader node-sass.

Instalamos también el plugin Mini CSS Extract: npm i -D mini-css-extract-plugin.

Añadimos la sección module a nuestro archivo de configuración de webpack (webpack.config.js) justo debajo de la sección output, es importante añadir las librerias necesarias en la parte superior del archivo:

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

module.exports = {
    plugins: [
        new MiniCssExtractPlugin({
            filename: "[name].css"
        })
    ],
    entry: "./src/index.js",
    output: {
        filename: "app.js",
        path: path.resolve(__dirname, "dist"),
        publicPath: "./",
        assetModuleFilename: 'assets/images/[name][ext][query]'
    },
    module: {
        rules: [
            {
                test: /\.scss$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'sass-loader'
                ]
            },
            {
                test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
                type: 'asset/resource',
            }
        ]
    }
}

Una vez añadidas las reglas, necesitamos importar el archivo scss al archivo index.js.

Ejecutamos de nuevo npm run dev y veremos el resultado de esta configuración en el directorio dist.

HTML Webpack Plugin

Vamos ahora a instalar el plugin html para webpack, ejecutamos el siguiente comando: npm i -D html-webpack-plugin.

Instalamos también un último plugin para minimizar el archivo CSS extraído. Ejecutamos el siguiente comando: npm i -D optimize-css-assets-webpack-plugin.

A continuación modificamos el archivo de configuración de la siguiente manera:

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

module.exports = {
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        }), 
        new MiniCssExtractPlugin({
            filename: "[name].css"
        })
    ],
    entry: "./src/index.js",
    output: {
        filename: "app.js",
        path: path.resolve(__dirname, "dist"),
        publicPath: "./",
        assetModuleFilename: 'assets/images/[name][ext][query]'
    },
    module: {
        rules: [
            {
                test: /\.scss$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'sass-loader'
                ]
            },
            {
                test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
                type: 'asset/resource',
            }
        ]
    },
    optimization: {
        minimize: true,
        minimizer: [ new OptimizeCssAssetsPlugin() ]
    }
}

Finalmente, la configuración de nuestro package.json queda de la siguiente manera:

{
  "name": "webpack-base",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack --mode production",
    "dev": "webpack --mode development --watch",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "css-loader": "^5.2.6",
    "html-webpack-plugin": "^5.3.1",
    "mini-css-extract-plugin": "^1.6.0",
    "node-sass": "^6.0.0",
    "optimize-css-assets-webpack-plugin": "^6.0.0",
    "sass-loader": "^12.0.0",
    "webpack": "^5.38.1",
    "webpack-cli": "^4.7.0"
  }
}

El parámetro --watch compilará nuestro código cada vez que se detecte un cambio, de esta manera no tendremos que ejecutar npm run dev constantemente.

Ejecutamos ahora nuestro index.html con la extensión Live Server instalada en nuestro VSCode.

Con toda esta configuración ya podemos desarrollar nuestro proyecto aprovechando todas las ventajas que nos ofrece Webpack 5.