Let Obfuscate it. (Reducing html size)
Tags: nuxt, vue, cssloader, webpack
Published: 2021-03-19 10:03:54

## Intro
You can download the source code [here](https://github.com/radonirinamaminiaina/let-obfuscate-it)
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](https://www.thinkwithgoogle.com/intl/en-ca/marketing-strategies/app-and-mobile/mobile-page-speed-new-industry-benchmarks/)).

## 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](https://webpack.js.org/loaders/html-loader/) 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](https://v4.webpack.js.org/), you should have [css-loader](https://github.com/webpack-contrib/css-loader/).
Along this article, I use [nuxt](https://nuxtjs.org/) for example, but you can use [React](https://reactjs.org/) or [Angular](https://angular.io/).

After, [creating a nuxt app](https://nuxtjs.org/docs/2.x/get-started/installation/) we should modify our `build` object into `nuxt.config.js`.
Add the following line:

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

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

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

<style module>
.articleTitle {
    color: red;
}
</style>
```

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x95znaxy9sub0ay6tzxq.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x95znaxy9sub0ay6tzxq.png)

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

Let use [extend](https://nuxtjs.org/docs/2.x/configuration-glossary/configuration-build#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.

```javascript
   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
        })
      }
    },
  }
```
Rebuild your app and run the browser again. And voilà, it works perfectly 🎉🎉🎉. 
Inspect your page and see the result

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vog4p2qzm5m1l053zirp.png)

### We can go further for smaller classnames 🙌...
I found this [article](https://medium.com/@my_own_grave/reducing-css-generated-by-vue-loader-by-using-classnames-shorten-trick-aa1d25d77473) which talk about reducing classnames, so let use it in our code.
In the root of your project, create a new file `getLocalIdent.js`:

```javascript
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
```
(*Make sure you installed incstr*)

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

```javascript
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
      })
    },
  },
}
```

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

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g3a5vschapqyh3ne627m.png)

## 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](https://github.com/radonirinamaminiaina/let-obfuscate-it) url of this article.
For more advanced nuxt concept, please read my [previous article](https://dev.to/radonirinamaminiaina/nuxt-like-a-pro-use-service-pattern-my-best-practice-1dna)

Thanks for reading. 😊