DEV Community

Cover image for Let Obfuscate it. (Reducing html size)
Radonirina Maminiaina
Radonirina Maminiaina

Posted on • Edited on

Let Obfuscate it. (Reducing html size)

Intro

You can download the source code here
If you want your website to be indexed by Google search engine, you must optimize your code and your website should load as fast as possible (Not more than 3s according to this article).

Minify and gzip come to rescue

The first solution is to minify your assets as html, css, javascript, images. (You can use tools to proceed minify, e.g: html-minify for html)
You can use gzip to compress statics assets using your favorite server such as nginx, node, or apache.

Let reduce our html use obfuscate technic

If you inspect google or facebook source page you can see that their classnames are unreadable.
Because if you use long classname, your html will have a big size too. Therefore, it will impact your page loading.
Then, we can deduct that minify is good but not enough.

Here come obfuscate

Before we start, you should have a minimum knowledge of webpack, you should have css-loader.
Along this article, I use nuxt for example, but you can use React or Angular.

After, creating a nuxt app we should modify our build object into nuxt.config.js.
Add the following line:

build: {
    loaders: {
      css: {
        modules: {
          localIdentName:
            process.env.NODE_ENV === 'development'
              ? '[local]_[hash:base64:5]'
              : '[hash:base64:5]',
        },
      },
    },
  },
Enter fullscreen mode Exit fullscreen mode

And within your index.vue for instance, add the following css:

<template>
<h1 :class="$style.articleTitle">Let obfuscate it</h1>
</template>

<style module>
.articleTitle {
    color: red;
}
</style>
Enter fullscreen mode Exit fullscreen mode

Now, start the application with yarn dev or npm run dev and open it in your favorite browser. Inspect the page and you should have something like this:

image

Let build the web app with yarn build or npm run build and run yarn start or npm run start. Now, inspect the page, and see the result.

image

Oops, it doesn't work. 😥
Apparently, overriding build.loaders.css is not the solution.
So, how can we do that? 🔥🔥🔥

Let use extend to do it manually.

Extend the webpack configuration manually for the client & server bundles.

Use extend manually to do obfuscate

Remove loader and add the following code within your build property.

   extend(config, { isClient }) {
      if (isClient) {
        const cssLoader = config.module.rules.find((rule) => {
          return rule.test.toString() === '/\\.css$/i'
        })
        cssLoader.oneOf = cssLoader.oneOf.map((loader) => {
          loader.use = loader.use.map((item) => {
            if (item.options.modules) {
              if (process.env.NODE_ENV === 'production') {
                item.options.modules.localIdentName = '[hash:base64:5]'
              }
            }
            return item
          })
          return loader
        })
      }
    },
  }
Enter fullscreen mode Exit fullscreen mode

Rebuild your app and run the browser again. And voilà, it works perfectly 🎉🎉🎉.
Inspect your page and see the result

image

We can go further for smaller classnames 🙌...

I found this article which talk about reducing classnames, so let use it in our code.
In the root of your project, create a new file getLocalIdent.js:

import incstr from 'incstr'

// region CSS Scope Minify
const createUniqueIdGenerator = () => {
  const index = {}

  const generateNextId = incstr.idGenerator({
    alphabet: 'abcdefghijklmnopqrstuvwxyz0123456789_-',
  })

  return (name) => {
    if (index[name]) {
      return index[name]
    }

    let nextId

    do {
      // Class name cannot start with a number.
      nextId = generateNextId()
    } while (/^[0-9_-]/.test(nextId))

    index[name] = generateNextId()
    // console.log(`${name} has id = ${index[name]}`);

    return index[name]
  }
}

const idLocal = createUniqueIdGenerator()
const idComponent = createUniqueIdGenerator()
const generateScopedName = (localName, resourcePath) => {
  const componentName = resourcePath.split('/').slice(-2).join('/')
  return idComponent(componentName) + idLocal(localName)
}

const getLocalIdent = (context, _localIdentName, localName) =>
  generateScopedName(localName, context.resourcePath)

export default getLocalIdent
Enter fullscreen mode Exit fullscreen mode

(Make sure you installed incstr)

Now, let use it in our nuxt.config.js:

import getLocalIdent from './getLocalIdent'
export default {
 // another config
 build: {
    extend(config) {
      const cssLoader = config.module.rules.find((rule) => {
        return rule.test.toString() === '/\\.css$/i'
      })
      cssLoader.oneOf = cssLoader.oneOf.map((loader) => {
        loader.use = loader.use.map((item) => {
          if (item.options.modules) {
            if (process.env.NODE_ENV === 'production') {
              item.options.modules.getLocalIdent = getLocalIdent
            }
          }
          return item
        })
        return loader
      })
    },
  },
}
Enter fullscreen mode Exit fullscreen mode

Rebuild again, and run the browser and see the result.

image

Conclusion

You can reduce your html file size using this technic, and combined to another technics, your web page will load more and more faster.

Here the git url of this article.
For more advanced nuxt concept, please read my previous article

Thanks for reading. 😊

Top comments (0)