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.
- bootstrap
- @popperjs/core
- autoprefixer
- clean-webpack-plugin
- node-sass
- nodemon
- postcss-cli
- webpack
- webpack-cli
- webpack-merge
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
Omar Villafuerte says:
Excelente publicación 👏