La mayor parte de los sitios web que funcionan con WordPress pueden hacerlo eligiendo un theme del repositorio oficial o de cualquier otro y personalizándolo con las opciones disponibles en el panel de control. Incluso si se necesita desarrollar un theme hoy día es buena idea no empezar de cero, sino usando una estructura básica, genérica ya desarrollada. Por otro lado es recomendable usar ciertas herramientas que produzcan un theme optimizado, que cargue lo más rápido posible, que se adapte a todo tipo de dispositivos. Esto pasa, además de por estructurar bien la información para minimizar las consultas a base de datos, por producir archivos CSS, JS minimizados e imágenes comprimidas y optimizadas que agilicen la carga. Un buen starter theme para WordPress facilita ambas cosas: una estructura genérica sobre la que empezar a construir rápidamente, y un entorno de desarrollo que permita automatizar las tareas de optimización e ir probando los avances ágilmente.
En este post comparto mi manera de trabajar: qué starter theme utilizo últimamente y cuál es el flujo de trabajo con él.
Understrap Starter theme
Undestrap es el starter theme que mejor se adapta a mi manera de desarrollar, que tiene todo lo que necesito:
- npm para instalar y gestionar librerías y otras dependencias.
- Gulp para automatizar rutinas: compilación de archivos de estilo y javascript, optimización de imágenes, carga de librerías y otras dependencias en la estructura del theme…
- Brwsersync para ir probando el desarrollo en tiempo real en el navegador.
- Bootstrap 4 como framework de maquetación.
- understrap-child como child theme para no tocar el theme understrap y poder actualizarlo en cualquier momento.
Tiene una comunidad bastante activa: el repositorio del theme tiene 73 usuarios que mantiene el proyecto muy actualizado. Por ejemplo, cuando escribo esto theme funciona con la última versión 4.3.1 de bootstrap que salío hace menos de un mes. La comunidad ha desarrollado varios child themes. Algunos están disponibles libremente en la cuenta de github del proyecto, otros son de pago. La documentación del theme no es una maravilla, pero algo hay.
Instalar Understrap y todo lo necesario
node.js y npm
Para empezar a desarrollar con Understrap hace falta instalar primero el gestor de paquetes npm, que nos permitirá después instalar el resto de paquetes y librerías que usa Understrap; y node.js que permite levantar un servidor web en local para el desarrollo.
Como acostumbro en este blog cuento cómo instalar ambas dependencias en un entorno Debian 10 Buster. Versiones suficientemente actualizadas de npm y nodejs, aunque no las últimas, se puede instalar desde los repositorios oficiales de Debian:
sudo apt-get update sudo apt install npm nodejs
Para instalar la última versión de node.js, que no es necesario para trabajar con Understrap, se pueden seguir las instrucción de Nodesource. Para instalar la última versión de npm se puede consultar su repositorio en github.
Cómo actualizar con npm las librerías que usa el theme
npm es muy útil para mantener actualizadas las librerías que usa el starter theme. Por ejemplo, si el framework Bootstrap libera una nueva versión, se puede incorporar a nuestros proyecto usando npm. Primero hay que moverse a la carpeta que contenga el theme. Con npm outdated se puede ver los paquetes que no están actualizados:
skotperez@lee:~$ cd understrap-child skotperez@lee:~/understrap-child$ npm outdated Package Current Wanted Latest Location bootstrap 4.1.3 4.1.3 4.3.1 understrap-child del 3.0.0 3.0.0 4.1.0 understrap-child gulp 3.9.1 3.9.1 4.0.0 understrap-child gulp-autoprefixer 5.0.0 5.0.0 6.0.0 understrap-child gulp-clean-css 3.10.0 3.10.0 4.0.0 understrap-child gulp-imagemin 4.1.0 4.1.0 5.0.3 understrap-child gulp-sass 4.0.1 4.0.1 4.0.2 understrap-child gulp-sourcemaps 2.6.4 2.6.4 2.6.5 understrap-child gulp-uglify 3.0.1 3.0.2 3.0.2 understrap-child popper.js 1.14.7 1.15.0 1.15.0 understrap-child understrap 0.8.9 0.8.9 0.9.1 understrap-child
Para actualizar los paquetes:
skotperez@lee:~/understrap-child$ npm install > understrap-child@0.5.3 postinstall /home/skotperez/Documentos/m34/code/themes/understrap-child-alisal > gulp copy-assets [14:29:09] Using gulpfile ~/Documentos/m34/code/themes/understrap-child-alisal/gulpfile.js [14:29:09] Starting 'copy-assets'... [14:29:09] Finished 'copy-assets' after 611 ms npm WARN bootstrap@4.1.3 requires a peer of jquery@1.9.1 - 3 but none is installed. You must install peer dependencies yourself. npm WARN bootstrap@4.2.1 requires a peer of jquery@1.9.1 - 3 but none is installed. You must install peer dependencies yourself. npm WARN gulp-imagemin@5.0.3 requires a peer of gulp@>=4 but none is installed. You must install peer dependencies yourself. npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.7 (node_modules/fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.7: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"}) added 67 packages in 94.097s
Cuando se ejecuta npm para actualizar, una vez que se han descargado las últimas versiones, se ejecuta gulp copy-assets para copiar las nuevas versiones a las ubicaciones adecuadas del theme, tal como se definen en gulpconfig.json, como se explica en el apartado sobre Gulp de este tutorial.
Usar ncu en lugar de npm para controlar qué librerías se actualizan
Si se quieren actualizar paquetes sin tener en cuenta el archivo package.json se puede hacer con ncu. Para ello hay que instalarlo primero:
skotperez@lee:~/understrap-child$ sudo npm install -g npm-check-updates /usr/bin/npm-check-updates -> /usr/lib/node_modules/npm-check-updates/bin/npm-check-updates /usr/bin/ncu -> /usr/lib/node_modules/npm-check-updates/bin/ncu + npm-check-updates@3.1.7 added 154 packages in 15.617s ╭─────────────────────────────────────╮ │ │ │ Update available 5.5.1 → 6.9.0 │ │ Run npm i -g npm to update │ │ │ ╰─────────────────────────────────────╯
En este caso, al instalar ncu, npm nos indica además que hay una actualización para el propio npm. Se puede actualizar también como nos indica:
skotperez@lee:~/understrap-child$ sudo npm i -g npm /usr/bin/npx -> /usr/lib/node_modules/npm/bin/npx-cli.js /usr/bin/npm -> /usr/lib/node_modules/npm/bin/npm-cli.js + npm@6.9.0 updated 1 package in 13.85s
Para comprobar las actualizaciones pendientes:
skotperez@lee:~/understrap-child$ ncu Checking package.json [====================] 30/30 100% bootstrap 4.1.3 → 4.3.1 browser-sync ^2.23.6 → ^2.26.3 del ^3.0.0 → ^4.1.0 gulp 3.9.1 → 4.0.0 gulp-autoprefixer ^5.0.0 → ^6.0.0 gulp-clean-css ^3.9.2 → ^4.0.0 gulp-cssnano ^2.1.2 → ^2.1.3 gulp-imagemin ^4.1.0 → ^5.0.3 gulp-plumber ^1.2.0 → ^1.2.1 gulp-rename ^1.2.2 → ^1.4.0 gulp-sass 4.0.1 → 4.0.2 gulp-sourcemaps 2.6.4 → 2.6.5 gulp-uglify ^3.0.0 → ^3.0.2 merge2 ^1.2.1 → ^1.2.3 popper.js ^1.12.9 → ^1.15.0 understrap ^0.8.6 → ^0.9.1 Run ncu -u to upgrade package.json
El mismo ncu nos dice cómo proceder:
skotperez@lee:~/understrap-child$ ncu -u Upgrading package.json [====================] 30/30 100% bootstrap 4.1.3 → 4.3.1 browser-sync ^2.23.6 → ^2.26.3 del ^3.0.0 → ^4.1.0 gulp 3.9.1 → 4.0.0 gulp-autoprefixer ^5.0.0 → ^6.0.0 gulp-clean-css ^3.9.2 → ^4.0.0 gulp-cssnano ^2.1.2 → ^2.1.3 gulp-imagemin ^4.1.0 → ^5.0.3 gulp-plumber ^1.2.0 → ^1.2.1 gulp-rename ^1.2.2 → ^1.4.0 gulp-sass 4.0.1 → 4.0.2 gulp-sourcemaps 2.6.4 → 2.6.5 gulp-uglify ^3.0.0 → ^3.0.2 merge2 ^1.2.1 → ^1.2.3 popper.js ^1.12.9 → ^1.15.0 understrap ^0.8.6 → ^0.9.1 Run npm install to install new versions.
Una vez actualizado el archivo package.json
se puede ejecutar npm install
para actualizar:
skotperez@lee:~/understrap-child$ npm install
Si se vuelve a comprobar las actualizaciones, se verá que todo está actualizado:
skotperez@lee:~/understrap-child$ ncu Checking package.json [====================] 30/30 100% All dependencies match the latest package versions :)
Cómo solucionar errores de dependencias durante la instalación de las librerías
Si al actualizar hubiese algún error, aconsejo editar el archivo package.json
con las versiones a las que se quiera volver y luego ejecutar npm install
.
También se puede volver a una versión anterior de alguno de los paquetes. Por ejemplo, si se quiere hacer un downgrade de gulp a la versión 3.9.1:
skotperez@lee:~$ sudo npm install -g gulp@3.9.1
Y de manera local, solo para el proyecto:
skotperez@lee:~$ cd understrap-child skotperez@lee:~/understrap-child$ npm install gulp@3.9.1
Understrap y el entorno de desarrollo
Una vez instalados npm y node.js se puede clonar Understrap desde el repo. Si como en mi caso se va a desarrollar usando el child theme de Understrap, hay que clonarlo también. Y luego usar npm para instalar gulp y browsersync y el resto de dependencias, y copiar las librerías necesarias desde node_modules a src:
skotperez@lee:~$ git clone https://github.com/understrap/understrap.git understrap skotperez@lee:~$ git clone https://github.com/understrap/understrap-child.git understrap-child skotperez@lee:~$ cd understrap-child skotperez@lee:~/understrap-child$ npm install skotperez@lee:~/understrap-child$ sudo npm install --global gulp-cli skotperez@lee:~/understrap-child$ sudo npm install --global browser-sync skotperez@lee:~/understrap-child$ gulp copy-assets
Dejo aquí una lista de los archivos que incluyen tanto understrap como understrap-child que conforman el entorno de desarrollo:
- css/. Contiene los archivos CSS del theme, compilados a partir de los archivos Sass ubicados en
sass/
. gulpconfig.json
. Contiene las variables de configuración de Gulp: las ubicaciones en las que debe mirar para compilar, dónde colocar los archivos compilados, qué URL debe vigilar browsersync para crear el navegador de testeo…gulpfile.js
. Contiene la definición de las rutinas a automatizar con gulp.node_modules/
. Contiene los paquetes instalados con npm.package.json
. Contiene las dependencias de Understrap a instalar al ejecutar npm install, que se instalarán ennode_modules
.package-lock.json
. Contiene un registro de los paquetes instalados con npm.sass/
. Contiene los archivos Sass con las reglas para construir los CSS del theme.- src/. En las carpetas
js/
ysass/
contiene los archivos fuente de las librerías que usa el theme que gulp copia desdenode_modules/
. En la carpetaimages/
se alojarán las imágenes del theme que queramos que gulp comprima.
Gulp
Antes de comenzar a desarrollar es conveniente echar un vistazo a la configuración de gulp para personalizarlo según nuestra manera de trabajar. Las variables de configuración de gulp están en gulpconfig.json
:
{ "browserSyncOptions" : { "proxy": "localhost/wordpress/", "notify": false }, "browserSyncWatchFiles" : [ "./css/*.min.css", "./js/*.min.js", "./**/*.php" ], "paths" : { "js": "./js", "css": "./css", "img": "./images", "imgsrc": "./src/images", "sass": "./sass", "node": "./node_modules/", "bower": "./bower_components/", "dev": "./src", "dist": "./dist", "distprod": "./dist-product", "vendor": "" } }
La opción proxy
permite configurar la URL de la instalación de WordPress en localhost que se quiere asociar al servidor de desarrollo. Los tipos de archivo listados en browserSyncWatchFiles
son los que serán vigilados por Browsersync y que cuando se modifiquen harán que el navegador se recargue automáticamente para poder ver los cambios. En paths
se pueden definir todas las ubicaciones que usa gulp para buscar los archivos CSS, JS y de imagen que compilará, minimizará y optimizará. Estas ubicaciones están vigiladas por gulp que tratará automáticamente todos los archivos que se guarden en ellas.
Los distintos comandos de gulp están definidos en gulpfile.js
. Este archivo está bien documentado: cada comando está precedido de una explicación. Por ejemplo:
// Run: // gulp imagemin // Running image optimizing task gulp.task( 'imagemin', function() { gulp.src( paths.imgsrc + '/**' ) .pipe( imagemin() ) .pipe( gulp.dest( paths.img ) ); });
gulp imagemin
comprime las imágenes alojadas en src/images
y guardarlas en images/
.
Para lanzar el navegador de desarrollo se puede ejecutar gulp watch-bs
:
// Run: // gulp watch-bs // Starts watcher with browser-sync. Browser-sync reloads page automatically on your browser gulp.task( 'watch-bs', ['browser-sync', 'watch', 'scripts'], function() { } );
Los comandos definidos en gulpfile.js
se pueden modificar fácilmente. Por ejemplo, el comando gulp copy-assets
copia las librerías usadas por el theme de node_modules/
a src/
:
// Run: // gulp copy-assets. // Copy all needed dependency assets files from bower_component assets to themes /js, /scss and /fonts folder. Run this task after bower install or bower update ////////////////// All Bootstrap SASS Assets ///////////////////////// gulp.task( 'copy-assets', function() { ////////////////// All Bootstrap 4 Assets ///////////////////////// // Copy all JS files var stream = gulp.src( paths.node + 'bootstrap/dist/js/**/*.js' ) .pipe( gulp.dest( paths.dev + '/js/bootstrap4' ) ); // Copy all Bootstrap SCSS files gulp.src( paths.node + 'bootstrap/scss/**/*.scss' ) .pipe( gulp.dest( paths.dev + '/sass/bootstrap4' ) ); ////////////////// End Bootstrap 4 Assets ///////////////////////// // Copy all Font Awesome Fonts gulp.src( paths.node + 'font-awesome/fonts/**/*.{ttf,woff,woff2,eot,svg}' ) .pipe( gulp.dest( './fonts' ) ); // Copy all Font Awesome SCSS files gulp.src( paths.node + 'font-awesome/scss/*.scss' ) .pipe( gulp.dest( paths.dev + '/sass/fontawesome' ) ); // _s SCSS files gulp.src( paths.node + 'undescores-for-npm/sass/media/*.scss' ) .pipe( gulp.dest( paths.dev + '/sass/underscores' ) ); // _s JS files into /src/js gulp.src( paths.node + 'undescores-for-npm/js/skip-link-focus-fix.js' ) .pipe( gulp.dest( paths.dev + '/js' ) ); // Copy Popper JS files gulp.src( paths.node + 'popper.js/dist/umd/popper.min.js' ) .pipe( gulp.dest( paths.js + paths.vendor ) ); gulp.src( paths.node + 'popper.js/dist/umd/popper.js' ) .pipe( gulp.dest( paths.js + paths.vendor ) ); // UnderStrap SCSS files gulp.src( paths.node + 'understrap/sass/**/*.scss' ) .pipe( gulp.dest( paths.dev + '/sass/understrap' ) ); return stream; });
Si se quiere añadir por ejemplo la librería Isotope a los archivos del theme, se puede añadir las siguientes líneas al comando gulp copy-assets
:
// Run: // gulp copy-assets. // Copy all needed dependency assets files from bower_component assets to themes /js, /scss and /fonts folder. Run this task after bower install or bower update ////////////////// All Bootstrap SASS Assets ///////////////////////// gulp.task( 'copy-assets', function() { ////////////////// All Bootstrap 4 Assets ///////////////////////// // Copy all JS files var stream = gulp.src( paths.node + 'bootstrap/dist/js/**/*.js' ) .pipe( gulp.dest( paths.dev + '/js/bootstrap4' ) ); // Copy all Bootstrap SCSS files gulp.src( paths.node + 'bootstrap/scss/**/*.scss' ) .pipe( gulp.dest( paths.dev + '/sass/bootstrap4' ) ); ////////////////// End Bootstrap 4 Assets ///////////////////////// // Copy all Font Awesome Fonts gulp.src( paths.node + 'font-awesome/fonts/**/*.{ttf,woff,woff2,eot,svg}' ) .pipe( gulp.dest( './fonts' ) ); // Copy all Font Awesome SCSS files gulp.src( paths.node + 'font-awesome/scss/*.scss' ) .pipe( gulp.dest( paths.dev + '/sass/fontawesome' ) ); // _s SCSS files gulp.src( paths.node + 'undescores-for-npm/sass/media/*.scss' ) .pipe( gulp.dest( paths.dev + '/sass/underscores' ) ); // _s JS files into /src/js gulp.src( paths.node + 'undescores-for-npm/js/skip-link-focus-fix.js' ) .pipe( gulp.dest( paths.dev + '/js' ) ); // Copy Popper JS files gulp.src( paths.node + 'popper.js/dist/umd/popper.min.js' ) .pipe( gulp.dest( paths.js + paths.vendor ) ); gulp.src( paths.node + 'popper.js/dist/umd/popper.js' ) .pipe( gulp.dest( paths.js + paths.vendor ) ); // UnderStrap SCSS files gulp.src( paths.node + 'understrap/sass/**/*.scss' ) .pipe( gulp.dest( paths.dev + '/sass/understrap' ) ); // Copy Isotope JS files gulp.src( paths.node + 'isotope-layout/dist/isotope.pkgd.min.js' ) .pipe( gulp.dest( paths.js ) ); gulp.src( paths.node + 'isotope-layout/dist/isotope.pkgd.js' ) .pipe( gulp.dest( paths.js ) ); return stream; });
Previamente, si el paquete no está instalado, se tiene que instalar usando npm.
skotperez@lee:~/understrap-child$ npm install isotope-layout --save
Bootstrap
Understrap viene preparado para usar Bootstrap: los archivos PHP del theme incluyen las clases de bootstrap y los archivos Sass de bootstrap vienen incluidos también. Las variables de bootstrap se pueden sobreescribir en el archivo sass/theme/_child_theme_variables.scss
. Para un listado completo de variables se puede consultar el archivo src/sass/bootstrap4/_variables.scss
.
Otros starter themes
Por si alguien quiere probar algún otro Starter theme para WordPress aquí dejo una lista de los que he probado en algún momento:
- HTML5 Blank
- Realmente un starter theme. Lo más básico que he encontrado. No incluye entorno de desarrollo. Enlace al repositorio del proyecto.
- _s
Es el starter theme de Automattic, la empresa detrás del desarrollo del WordPress, lo que da ciertas garantías de continuidad del proyecto. Su web permite generar un theme mínimamente personalizado basado en Underscore, lo cual agiliza el desarrollo al principio. Enlace al repositorio del proyecto.
- Bootstrap Starter Theme for WordPress
- Starter theme basado en el framework Bootstrap. Permite generar un theme con las variables de bootstrap personalizadas desde su web.Enlace al repositorio del proyecto.
- WordPress Starter Theme
- Tiene todo lo necesario, aunque algo desactualizado (último cambio hace 4 años), lo que hace necesario actualizar todos los módulos antes de empezar a desarrollar. Enlace al repositorio del proyecto.