Radonirina Maminiaina
Posted on March 19, 2021
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]',
},
},
},
},
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>
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:
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.
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
})
}
},
}
Rebuild your app and run the browser again. And voilà , it works perfectly 🎉🎉🎉.
Inspect your page and see the result
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
(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
})
},
},
}
Rebuild again, and run the browser and see the result.
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. 😊
Posted on March 19, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.