Back to articles
February, 23rd 2022

Better DOM Debugging With Component Name in HTML Attribute

The problem

Sometimes the key of keeping great DX is in tiny details. Debugging markup of modern frontend might be very scary these days. With atomic CSS classes getting trendy, the DOM in devtools becomes harder and harder to read. Look at this:

As a developer who is looking for a rendered certain part of the code he is debugging, it's very painful to even start looking. Even after working with project for months it's hard to navigate in this kind of code blocks, looking for certain components.

In times when we had CSS BEM convention popular, CSS block names helped a lot, just look at this one:

How much more readable it is. Navigation in the DOM becomes instantly better. You can easily find content, heading and text parts of the layout, if you follow your naming convention consistently you can ever see that it's probably the RecyclingPageTop.jsx template file that you need to find in your codebase to edit this part of the code.

The other way

But I don't wanna fight TailwindCSS or any other atomic CSS framework for poor readability. We can easily enhance DX, learning from the past. Look at this example:

It's the same code from the first example but with a small tweak: all the component names are set in the data-name attribute and are capitalised. Looks better, huh? We are able to bring readability, code navigation, and visual separation from other CSS classes.

The solution

My way of achieving this in Vue.js is a mixin. Let's define a mixin with $NAME computed property that doesn't a couple of things:

  • Read from current component name via $options API. In my projects, component filenames also match their names, so it's easy to search through the codebase.
  • Do regexp magic and parse camelcase into an array with uppercased strings. Join them with a dash.
  • In the end, we don't want for this to happen on production, so this logic is scoped with ternary condition and returns null outside of development environment.
/* js */
import Vue from 'vue'

Vue.mixin({
  computed: {
    $NAME () {
      return process.env.NODE_ENV === 'development' ? this.$options.name
        .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
        .map(x => x.toUpperCase())
        .join('-') : null;
    }
  }
})

In the template file later, your can access the name like this.

/* html */
<template>
  <nav
    :data-name="$NAME"
    class="app-p-16 md:app-p-32"
  >
    <AppStack
      tag="ul"
      align="center"
      justify="between"
    >
      <li>...

That's it! Huge improvement, very handy and easy to integrate. Further optimisations may be applied to strip this code completely from production builds, so the JS engine doesn't have to go through environment condition checks all the time.


Other Posts
July, 28th 2022 Background-aware swiper pagination Some parts of user interface are not background aware, however are meant to be. It’s especially noticeable when working with user-generated content that is different in colors, exposure and size. Take..
March, 31st 2022 Tree-shaking Vuex State in Nuxt Document response The way Nuxt delivers state data from server to client can play a bad joke with your loading performance. All of your Vuex state data on the server will be printed in the response Document as JS objec..