Entorno de desarrollo con NPM y WebPack

Cada vez que comenzamos un nuevo proyecto, los pasos iniciales no varían mucho uno de otro. En esta guía podrás conocer cómo crear tu propio entorno utilizando NPM y WebPack como herramientas fundamentales.

Introducción

Lo primero que tenemos que tener claro es qué tecnologías vamos a usar. En este ejemplo vamos a aprender a configurar algunos script con NPM y WebPack. Para ello necesitamos tener previamente instalado Node.js en nuestro ordenador.

Debemos estar concientes que este será un ejemplo muy sencillo en el que crearemos una página index.html, además de un par de archivos css y js, que es la estructura básica que un sitio web puede tener.

Toca por parte de ustedes adaptar esto a entornos más complejos.

NPM

Una vez que hayamos configurado nuestro servidor para alojar nuestro proyecto, ya podemos comenzar con el asistente que nos ayudará a crear el archivo package.json, que nos servirá para manejar las dependencias y los scripts que vamos a ejecutar en nuestro proyecto.

Navegamos hasta el directorio en el que vamos a trabajar y ejecutamos el siguiente comando:

$ npm init

Inmediatamente se nos presentará un asistente, que nos ayudará a crear el archivo package.json.

En este caso los puntos más importantes son: package name, version, description, keywords, author y license. Puedes ver un listado completo de licencias en este enlace.

Una vez terminado este paso, podemos abrir el archivo package.json con nuestro editor de código y eliminar el campo main, así como el script test, pues no inciden en nada en el funcionamiento del mismo.

{
   "name": "project-npm-webpack",
   "version": "1.0.0",
   "description": "Project NPM WebPack",
   "main": "index.js",
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1"
   },
   "keywords": [
     "npm",
     "webpack"
   ],
   "author": "RogerTM",
   "license": "GPL-2.0-or-later"
 }

Quedando entonces de la siguiente manera:

{
   "name": "project-npm-webpack",
   "version": "1.0.0",
   "description": "Project NPM WebPack",
   "scripts": {},
   "keywords": [
     "npm",
     "webpack"
   ],
   "author": "RogerTM",
   "license": "GPL-2.0-or-later"
 }

Dependencias

Ya estamos listos para instalar las dependencias que necesitamos para nuestro proyecto. En la siguiente lista podemos detallar de qué va cada plugin que vamos a usar.

Entonces procedemos a instalar las dependencias que necesitamos:

$ npm install bootstrap @popperjs/core autoprefixer clean-webpack-plugin node-sass nodemon postcss-cli webpack webpack-cli webpack-merge --save-dev

Ahora nuestro archivo package.json luce de la siguiente manera:

{
   "name": "project-npm-webpack",
   "version": "1.0.0",
   "description": "Project NPM WebPack",
   "scripts": {},
   "keywords": [
     "npm",
     "webpack"
   ],
   "author": "RogerTM",
   "license": "GPL-2.0-or-later",
   "devDependencies": {
     "@popperjs/core": "^2.9.2",
     "autoprefixer": "^10.2.5",
     "bootstrap": "^5.0.1",
     "clean-webpack-plugin": "^4.0.0-alpha.0",
     "node-sass": "^6.0.0",
     "nodemon": "^2.0.7",
     "postcss-cli": "^8.3.1",
     "webpack": "^5.37.1",
     "webpack-cli": "^4.7.0",
     "webpack-merge": "^5.7.3"
   }
 }

Directorios

Antes de pasar a crear los scripts que vamos a utilizar, debemos tener la estructura de directorios y archivos que usaremos, pues este paso es determinante para la configuración de los mismos.

Personalmente me auxilio de un directorio assets y ahí dentro guardo mis archivos scss y js, así como los resultantes compilados, quedando de la siguiente manera:

├── assets
│   └── src
│       ├── js
│       └── scss
├── package.json
└── package-lock.json

Como es lógico, en el directorio assets/src/scss/ vamos a guardar nuestros archivos scss y en assets/src/js/ los archivos js.

Estilos

Vamos a comenzar creando un archivo styles.scss en assets/src/scss/, desde el que importaremos los archivos precompilados scss de Bootstrap.

En este sencillo ejemplo vamos a usar la opción más obvia, pero personalmente recomiendo usar solamente lo que necesitamos, así no generamos un archivo de estilos sobre cargado.

@import "../../../node_modules/bootstrap/scss/bootstrap";

Javascripts

Ahora toca el turno al archivo que se encargará de cargar la librería de plugins de Bootstrap. Para ello crearemos un archivo llamado scripts.js dentro de assets/src/js/. Como en el ejemplo anterior, vamos a usar la opción convencional, pero de igual manera recomiendo cargar solo lo que realmente vamos a usar.

import "../../../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js";

Estructura del proyecto

Una vez superados estos pasos, ya tenemos nuestro proyecto listo para comenzar a trabajar con los script de NPM y WebPack:

├── assets
│   └── src
│       ├── js
│       │   └── scripts.js
│       └── scss
│           └── styles.scss
├── package.json
└── package-lock.json

Scripts NPM y WebPack

Ya estamos listos para comenzar a trabajar con NPM y WebPack. Para ello necesitamos editar el archivo package.json que creamos al inicio de esta guía. Donde añadiremos los scripts que necesitamos al campo scripts, valga la redundancia.

WebPack

Pero antes vamos a comenzar por WebPack, quien se encargará de compilar nuestros archivos js, en este caso solo tenemos el archivo assets/src/js/scripts.js, pero dejaremos todo listo para compilar varios archivos a la vez.

Antes, echa un vistazo a los diferentes modos en que puedes configurar WebPack, para un mejor entendimiento y profundización de lo que veremos a continuación.

En nuestro ejemplo usaremos tres archivos, webpack.common.js, que contendrá la configuración general, común para ambos modos development y production. Además webpack.dev.js y webpack.prod.js, para los modos development y production respectivamente.

Common

const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
    entry: {
        scripts: './assets/src/js/scripts.js',
    },
    plugins: [
        new CleanWebpackPlugin(),
    ],
    output: {
        path: path.resolve(__dirname, 'assets/dist/js/'),
        filename: '[name].js',
    }
};

En este caso debemos notar, que si deseamos agregar otro archivo js, solo debemos agregarlo al campo entry, por ejemplo:

entry: {
     scripts: './assets/src/js/scripts.js',
     plugin1: './assets/src/js/plugin1.js',
     plugin2: './assets/src/js/plugin2.js',
     …
 },

El campo output se encargará de hacer el resto del trabajo. Nótese que la salida apunta al directorio assets/dist/js/.

Development

const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
    mode: 'development',
    watch: true,
    watchOptions: {
        ignored: /node_modules/
    }
});

Aquí nos llama la atención fundamentalmente el valor del campo mode que como es lógico es development y sobre todo que hemos ignorado totalmente lo que ocurre en el directorio node_modules/, por razones obvias.

Production

const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
    mode: 'production',
});

Aquí no hay mucho que comentar, la principal diferencia con el archivo webpack.dev.js es el valor del campo mode que está definido como production.

NPM

Ahora solo nos queda el último paso, crear los scripts que ejecutaremos, tanto en modo de producción como de desarrollo, dependiendo del entorno en que se encuentre nuestro proyecto.

Como hemos dicho antes, necesitamos editar en el archivo package.json, el campo scripts, así que veremos a continuación cómo quedaría:

"scripts": {
     "build": "npm run css && webpack --config webpack.prod.js",
     "css-compile": "node-sass --include-path node_modules --output-style compressed --source-map true --source-map-contents true --precision 6 assets/src/scss -o assets/dist/css/",
     "css-prefix": "postcss --replace assets/dist/css/styles.css --use autoprefixer --map",
     "css": "npm run css-compile && npm run css-prefix",
     "watch": "nodemon -e scss -x \"npm run css && webpack --config webpack.dev.js\""
   },

Vamos a concentrarnos solamente en los scripts build y watch, que en definitiva son los que vamos a utilizar continuamente. Ellos son los que se encargarán de llamar a los demás comandos cuando estos sean necesarios.

Pero antes si debemos hacer énfasis que en los comandos css-compile y css-prefix, el output apunta al directorio assets/dist/css/.

Build

Este comando lo utilizaremos en un entorno de producción, es decir, cuando nuestro proyecto esté visible desde internet.

Para ejecutarlo solo debemos navegar hasta la raíz de nuestro proyecto y:

$ npm run build

Si no ha ocurrido ningún error, entonces obtendremos una respuesta como la siguiente:

> project-npm-webpack@1.0.0 build
> npm run css && webpack --config webpack.prod.js
> project-npm-webpack@1.0.0 css
> npm run css-compile && npm run css-prefix
> project-npm-webpack@1.0.0 css-compile
> node-sass --include-path node_modules --output-style compressed --source-map true --source-map-contents true --precision 6 assets/src/scss -o assets/dist/css/
 Rendering Complete, saving .css file…
 Wrote CSS to /var/www/html/project-npm-webpack/assets/dist/css/styles.css
 Wrote Source Map to /var/www/html/project-npm-webpack/assets/dist/css/styles.css.map
 Wrote 1 CSS files to /var/www/html/project-npm-webpack/assets/dist/css/
> project-npm-webpack@1.0.0 css-prefix
> postcss --replace assets/dist/css/styles.css --use autoprefixer --map
 asset scripts.js 77.1 KiB [emitted] [minimized] (name: scripts) 1 related asset
 runtime modules 663 bytes 3 modules
 cacheable modules 77 KiB
    ./assets/src/js/scripts.js 74 bytes [built] [code generated]
    ./node_modules/bootstrap/dist/js/bootstrap.bundle.min.js 76.9 KiB [built] [code generated]
webpack 5.37.1 compiled successfully in 3244 ms

Si observamos ahora dentro de nuestro directorio assets, ahora tenemos una nueva carpeta dist donde se han guardado los archivos css y js compilados y comprimidos.

├── assets
│   ├── dist
│   │   ├── css
│   │   │   ├── styles.css
│   │   │   └── styles.css.map
│   │   └── js
│   │       ├── scripts.js
│   │       └── scripts.js.LICENSE.txt
│   └── src
│       ├── js
│       │   └── scripts.js
│       └── scss
│           └── styles.scss

Watch

El comando watch lo usaremos en un entorno de desarrollo, es útil para que a medida que vamos trabajando, él solo va compilando los archivos scss y js.

$ npm run watch

Entonces, mientras editamos los archivos scss o js, nos irá respondiendo de la siguiente manera, en caso de que no ocurra ningún error:

> project-npm-webpack@1.0.0 watch
> nodemon -e scss -x "npm run css && webpack --config webpack.dev.js"
 [nodemon] 2.0.7
 [nodemon] to restart at any time, enter rs
 [nodemon] watching path(s): .
 [nodemon] watching extensions: scss
 [nodemon] starting npm run css && webpack --config webpack.dev.js
> project-npm-webpack@1.0.0 css
> npm run css-compile && npm run css-prefix
> project-npm-webpack@1.0.0 css-compile
> node-sass --include-path node_modules --output-style compressed --source-map true --source-map-contents true --precision 6 assets/src/scss -o assets/dist/css/
 Rendering Complete, saving .css file…
 Wrote CSS to /var/www/html/project-npm-webpack/assets/dist/css/styles.css
 Wrote Source Map to /var/www/html/project-npm-webpack/assets/dist/css/styles.css.map
 Wrote 1 CSS files to /var/www/html/project-npm-webpack/assets/dist/css/
> project-npm-webpack@1.0.0 css-prefix
> postcss --replace assets/dist/css/styles.css --use autoprefixer --map
 asset scripts.js 83.7 KiB [emitted] (name: scripts)
 runtime modules 937 bytes 4 modules
 cacheable modules 77 KiB
   ./assets/src/js/scripts.js 74 bytes [built] [code generated]
   ./node_modules/bootstrap/dist/js/bootstrap.bundle.min.js 76.9 KiB [built] [code generated]
webpack 5.37.1 compiled successfully in 361 ms

Archivo index.html

Finalmente necesitamos crear un archivo index.html que funcionará como la página del proyecto, donde llamaremos los archivos css y js dentro del directorio assets/dist/css/ y assets/dist/js/ respectivamente.

<!doctype html>
<html lang="en">
 <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <link rel="stylesheet" href="assets/dist/css/styles.css">
     <title>Project NPM WebPack</title>
 </head>
 <body>
     <h1>Hello World!</h1>
     <p>Project NPM WebPack</p>
     <script src="assets/dist/js/scripts.js"></script>
 </body>
 </html>

Conclusiones

Hasta aquí, hemos creado un pequeño proyecto basando en NPM y WebPack, que además incluye Bootstrap a manera de ejemplo.

Debo decirles que este es el entorno que uso básicamente en todos mis proyectos, que claro está, luego puede compejizarse un poco más en dependencia de la envergadura de cada trabajo, pero realmente no varía mucho.

Para ahorrarte un poco de tiempo, he creado un repositorio en GitHub que contiene todos los archivos que se describen en esta guía, así que puedes descargarlo o clonarlo y comenzar a trabajar a partir de él.

Para instalarlo en tu servidor, solo debes clonar el repositorio y ejecutar los mismos scripts que hemos visto aquí:

$ git clone https://github.com/rogertm/enviroment-npm-webpack.git
$ npm install
$ npm run build

One reply on “Entorno de desarrollo con NPM y WebPack”


Leave a comment

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