Haga que el desarrollo HTML de varias páginas sea menos pesado con Pug

Inspirado en una historia real

Hagamos un viaje ...

Imagina que estás en la lista de llamadas de una agencia autónoma en la ciudad que elijas. Ahora digamos que recibe un mensaje agradable en su bandeja de entrada. Abres el mensaje y parece bastante normal.

Tenemos una necesidad inmediata de que un desarrollador comience hoy.

el mensaje y parece bastante normal.

Tenemos una necesidad inmediata de que un desarrollador comience hoy.

Al ser una persona a la que le gusta comer alimentos para sobrevivir, ingresa información y presenta la solicitud.

A los cinco minutos de presionar el botón de envío, recibe una llamada. 10 minutos después de eso, obtendrá acceso al servidor.

No hace falta decir que tienes una fecha límite. Ese plazo es al final del día.

Abres los archivos HTML y los miras ... con horror.

El código está por todas partes, desordenado y desorganizado. Sin mencionar que tienes que hacer ajustes en el encabezado y pie de página… en cinco páginas diferentes.

Lo primero que debe hacer es ejecutar Prettify (Gracias a Dios por Prettify). Eso lo limpió, pero hay algunos problemas más. Este es un sitio HTML estático, lo que significa que cada cambio que realice en el material global (encabezado, pie de página, etc.), tendrá que copiarlo en CADA archivo. Oh mi.

¿¿¿Qué vas a hacer???

Sencillo, creará un archivo Webpack para manejar la parte de mierda de escribir HTML, y lo hará rápidamente.

Esto es con lo que necesitará estar familiarizado:

  • ¡Javascript! (debido a Webpack)
  • HTML! (porque de eso está hecho Internet)
  • CSS! (porque a quien le gustan las cosas feas?)
  • ¡doguillo! (¡porque ese es el punto de este artículo!)
  • npm (porque es Dios)
  • Conocimientos básicos de la línea de comandos (porque hacer cosas mediante descargas es estúpido ...)
  • Sepa quién es Jim Carrey (porque gifs)

Si no está familiarizado con el pug, aún puede manejar su camino a través de esto. Pero si tienes tiempo, sigue leyendo. Recomiendo aprender pug con pugs. O sus doctores. Esos también están bien, supongo.

Aquí están las versiones que usé para esto:

  • cargador html: 0.5.5,
  • Complemento html-webpack: 3.2.0,
  • pug-html-loader: 1.1.5,
  • Paquete web: 4.12.0
  • paquete web-cli: 3.0.8
  • npm: 6.1.0
  • nodo: 10.4.0

Actualización: ¡hice un video! Compruébalo si no quieres leer, pero prefieres escuchar mi voz durante 30 minutos.

Paso 1. Organiza la estructura de tu proyecto

Así es como me gusta organizar mi carpeta para este tipo de proyectos.

src/ oldHTML/ dist/ images/ css/ webpack.config

Me gusta poner todo el HTML original en una carpeta separada que no puedo eliminar accidentalmente. Webpack es un poco más amable que decir, Gulp, que he tenido que eliminar una carpeta completa antes. Esta estructura es lo suficientemente buena como para comenzar.

Paso 2. Acelere el motor npm

Aparte: Recientemente volví a npmdesde yarnpor algunas razones. Uno de ellos fue que dejó de funcionar y tuve poca paciencia para que funcionara de nuevo. Interesante artículo aquí, si quieres leer más.

De todos modos, inicie ese npm.

npm init -y

Nota: (la -y es si no desea responder ninguna de sus preguntas)

Instale dependencias de desarrollo.

No te preocupes, te explicaré cada uno a medida que avanzamos.

npm install -D webpack webpack-cli pug-html-loader html-webpack-plugin html-loader

Agregue algunos scripts al package.json

Por defecto, package.json tiene una secuencia de comandos, pero necesitamos agregar algunas.

"dev": "webpack --watch --mode development", "prod": "webpack --mode production"

Estos son los dos que me gusta incluir. El primero ejecutará Webpack en modo de desarrollo (nota: el indicador --mode es nuevo en Webpack 4) y observará los cambios de archivo. El segundo es cuando queremos ejecutar Webpack en producción, esto generalmente minimiza las cosas.

Debería verse algo como esto:

"name": "pugTut", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "dev": "webpack --watch --mode development", "prod": "webpack --mode production" }, .....more code

Cree un par de archivos de inicio para probar nuestra configuración de Webpack

Webpack necesita un punto de entrada, así que hagamos uno. Cree un archivo app.js en la carpeta src / . Puede estar en blanco. No importa. También necesita un archivo pug inicial para compilar. Cree también un archivo index.pug en la carpeta src / .

Cree y configure webpack.config.js en el directorio raíz

Muy bien, si no ha usado Webpack antes, voy a repasar cada parte individualmente para darle (y con suerte a mí) una idea de lo que ocurre en este archivo de configuración.

Primero, declaremos nuestras dependencias.

// webpack.config.js const path = require('path'); const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin');

La ruta es una dependencia nativa de Nodo, por lo que no debería tener que preocuparse de que se requiera en su package.json.

Webpack es, bueno Webpack ...

HtmlWebpackPlugin es cómo extraemos HTML. No soy un experto en cómo funciona Webpack. Por lo que entiendo, dado que está diseñado para consumir JavaScript, tenemos que tener cargadores en nuestro archivo de configuración para extraer cosas como HTML y CSS. HtmlWebpackPlugin es cómo hacemos algo útil con el HTML que se extrae de los cargadores.

¿Frio? Próximo paso…

const pug = { test: /\.pug$/, use: ['html-loader?attrs=false', 'pug-html-loader'] };

This method is used by Wes Bos and I really like it, so I use it. We have to define rules on how to handle certain file types, for example .pug or .css. Putting it into a variable makes it more legible, in my opinion. Anyways, we setup a test case with a regexp, then define the loaders we want to use. For whatever reason, the loaders are listed in reverse order of what you’d think. I’m sure there is an explanation but I couldn’t find it.

Confused? What that means is, if we want to use pug to compile to HTML, we write it in the order above: our html loader ->pug loader. However, in reality when the code runs, it runs the pug loader first…then the HTML loader. Yep.

Note: Don’t worry about ?attrs=false for right now, I’ll explain it a bit later.

Cool? Next step…

const config = { entry: './src/app.js', output: { path: path.resolve(__dirname, 'dist'), filename: '[name].bundle.js' }, module: { rules: [pug] }, plugins: [ new HtmlWebpackPlugin({ filename: 'index.html', template: 'src/index.pug', inject: false }) ] }; module.exports = config;

Holy Crap. That’s a lot of stuff. Let’s break it down.

entry is simply the entry point for our JS file.

output defines where we want our JS file to go. This is not where our HTML files will go. As mentioned above, path is a node module. __dirname is a variable we can get from Node. The filename is what we want to call our JS file. The [name] is a substitution. In this case, it uses the file name of the entry file. You can also use [hash] if you want a unique identifier.

module defines the different modules. For the purpose of this tutorial, there is only one module with one set of rules. rules defines the rules we will use for that module. We throw the pug variable we made earlier into there. So nice, so clean.

Finally, plugins is where we get to add any third party stuff. In our case, we are using HtmlWebpackPlugin to do something with our pug files.

filename is what we want our HTML file to be called. template is the pug file that are compiling. inject is: “inject all assets into the given template.” I have it set to false because…well, honestly I don’t remember.

One of the crappiest things about HtmlWebpackPlugin is that you have to create an entry for EVERY HTML file. I tried to figure a way around it, but found no simple solutions.

// webpack.config.js const path = require('path'); const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const pug = { test: /\.pug$/, use: ['html-loader?attrs=false', 'pug-html-loader'] }; const config = { entry: './src/app.js', output: { path: path.resolve(__dirname, 'dist'), filename: '[name].bundle.js' }, module: { rules: [pug] }, plugins: [ new HtmlWebpackPlugin({ filename: 'index.html', template: 'src/index.pug', inject: false }) ] }; module.exports = config;

Before we move on, let’s make sure our code works! Run the script.

npm run dev

If all went well, you should see something like this:

We’ve come a long way. Here’s a present:

Step 3. Break up the pages into partials

This is where magic starts happening. I know it seems like we’ve been working for a while with very little gain, but trust me…it was worth it.

One of the most important features for pug is the partials. The idea is to have one file that holds most of your global code (head, header, footer, nav, and so on) and have individual files for all your content.

Let’s make a couple files. You should have created the index.pug file already, but let’s make one more, layout.pug.

src/ - index.pug - layout.pug

Step 4. Setup layout file

The layout file is basically the main template for your whole site. It will have hold all the global stuff, for example head, header and footer.

//- layout.pug doctype html html head title I'm a title body block header block content block footer script(src="somescript.js")

I guess something to explain is that pug is all based on indentation, similar to YAML. It is glorious, because that means no more closing tags! However, this can throw some, especially those with crappy indentation to begin with. So just make sure to start slow and make sure everything is indented correctly and you’ll be fine.

Looking at our layout.pug file, you’ll see some familiar HTML tags mixed with unfamiliar ones. I highly suggest downloading syntax highlighting for pug in your editor of choice. If you’re using VSCode, it should come with it by default. Thanks Microsoft.

I think it’s pretty easy to figure out, but let’s take a look at the meat of the document to make sure we know what’s going on.

head title I'm a title body block header block content block footer script(src="somescript.js")

head, body, title and script are normal tags, but what the hell is block? block is how we define dynamic content. Basically, this is telling pug that some content is going to go in here. Hopefully it’ll make more sense when we create our individual page files.

Step 5. Create more partials

Let’s make use of that index.pug file.

//- index.pug extends layout block content p Woah.

Looking at our index file, it seems awfully small for a whole HTML page. That’s because of that little extends fella. extends tells pug that you want to use another pug file as the template, in our case layout. Then below that block content is in reference to what we put in our layout.pug file.

If you have your Webpack still running in the background, it should recompile and you’ll get a fresh new index.html in your dist/ folder. If not, run Webpack again.

Step 6. Grab all the old HTML

Those starter files are fine and dandy, but we need to make some real progress. We need to start grabbing that HTML and using it! Luckily, pug will recognize regular old HTML tags, so you can literally copy all the HTML content you want and just paste it in there.

It might look something like this:

extends layout block content 

blerb

Woah.

Alright, it’s not really that simple.

Like I mentioned, pug is based on indentation. To make life easier on yourself, I suggest removing all indentation from the HTML file before pasting into the pug file. It will mostly work, but you’ll probably have to finagle it a bit. Lucky for us, pug-html-loader will tell us what’s wrong with it when it tries to compile. There are some examples of common problems in the next Step.

Step 7. Start optimizing

No voy a mentir, cuando lances HTML por primera vez, a Webpack no le gustará. Aquí hay algunas cosas a tener en cuenta:

Imagenes

  1. Asegúrese de que los enlaces a las imágenes sean correctos. Por cualquier razón, a menudo falla si src = "images /" en lugar de src = "/ images /"

2. Prometí antes volver a lo que ?attrs=falseera, bueno, ¡aquí estamos!

Esta es la propaganda del sitio html-loader que explica lo que hace.

Para deshabilitar completamente el procesamiento de atributos de etiquetas (por ejemplo, si está manejando la carga de imágenes en el lado del cliente) puede pasar attrs=false.
html-loader?attrs=false 

Javascript

pug no juega bien con JS en las etiquetas de script. Si está pegando etiquetas de script JS de apertura y cierre regulares, puede funcionar bien. Sin embargo, si desea utilizar la etiqueta de script pug, asegúrese de agregar un punto al final, como este:

Step 8. Make more pages and start converting to pug tags

Clearly it’s useless if you are only doing the index page. For whatever you’re doing, just create a new file for each page you want. Also, make sure to make new HtmlWebpackPlugin entries in the plugins section in Webpack.

It’ll end up looking like this:

//webpack.config.js ...previous code... plugins: [ new HtmlWebpackPlugin({ filename: 'index.html', template: 'src/index.pug', inject: false }), new HtmlWebpackPlugin({ filename: 'contact.html', template: 'src/contact.pug', inject: false }) ] ...more code...

You don’t have to convert everything to pug format immediately. In fact, if you have a huge site with a crap ton of HTML, then you can do it as you go, but it does make it easier.

Includes

This wouldn’t be a very good tutorial if we didn’t talk about includes. Remember those blocks in the layout file? Well, if you don’t want the layout file to be giant, you can create separate files that will be pulled in at compile time. For instance, if you want to make a single file that holds all the header info. Breaking it up this way also helps substantially with indentation.

Create a new file “header” in a new folder “includes”:

src/ -- includes/ header.pug

In that file, put whatever you want to be in the header.

//- header.pug header h1 I'm a header

Now go back to layout.pug and include it.

//- layout.pug doctype html html head title I'm a title body block header include includes/header block content block footer script(src="somescript.js")

Step 7. Want to get Fancy?

There’s a ton more stuff you can do with pug and webpack. However, I think we’ve reached the end of the basics. Still, check out mixins. Those things are amazing.

Wrapping Up

I highly suggest bringing in HTML slowly, otherwise you’ll end up debugging 1,000 errors at once.