How to

How to hash class names in Astro using astro-rename integration

Post - How to hash class names in Astro using astro-rename integration
October 14, 2023 8 months ago Tags 6 min read Comments
Share to Linkedin
Share to X (Twitter)
Share to Reddit
Share to Bluesky
Copy link

Table of Contents

Open Table of Contents

Introduction

In this post you’ll learn how to use the astro-renameastro integration to hash all CSS class names from your astro project.

What is astro-rename

The package astro-rename is an Astrointegration that uses postcss-renameto rename all CSS class names. This integration will also rename all JS/HTML files.

By default the postcss-rename only supports none, debug and minimal strategies. So, we’ll use the strategy option with a custom hash generator.

Create a new Astro project

Let’s get started creating a new Astro project:

Terminal window
npm create astro@latest
Terminal window
yarn create astro

All you have to do is follow the step-by-step instructions.

Running the Astro project

Once you have created your Astro project, you can start the dev server using:

Terminal window
npm run dev
Terminal window
yarn run dev

Now, the Astro project is running on localhost using the default port :4321:

Terminal window
1
http://localhost:4321

Astro default template running on localhost
Astro default template running on localhost - View image in a new tab

Let’s take a look at the DevTools from this default project:

Devtools from default Astro project
Devtools from default Astro project - View image in a new tab

As you can see, all CSS class names are “exposed”.

Installing dependencies

First of all, let’s install the astro-renamedependency:

Terminal window
npm install astro-rename --save-dev
Terminal window
yarn add astro-rename --dev

The astro-rename package require node >= 18.18. You don’t actually need this version and can use the --ignore-engines flag to bypass this error.

Set up astro integration

After installing the package, let’s import and include the integration:

Import dependency:

astro.config.mjs
1
import rename from 'astro-rename';

Add to integrations option:

astro.config.mjs
1
import { defineConfig } from 'astro/config';
2
3
import rename from 'astro-rename';
4
// import compress from 'astro-compress';
5
6
// https://astro.build/config
7
export default defineConfig({
8
output: 'static',
9
integrations: [
10
rename(),
11
// compress()
12
],
13
});

The integration will only work when output is set to static

If you are using other integration like astro-compress, include the astro-rename before this integration

Testing with default options

At this point, you already can build the project using:

Terminal window
npm run build
Terminal window
yarn run build

Now, run the output file using the VSCode Live Server extensionand take a look at the DevTools:

Devtools from default astro-rename strategy
Devtools from default astro-rename strategy - View image in a new tab

Note that all class names have been replaced with letters, by default the integration will use the minimal1 strategy.

The next step is to create our custom hash generator.

Generating hash names

We can take a look at the minimal renamermethod from postcss-rename plugin and uses as template for creating our custom hash generator.

First, create a new file named hash-renamer.ts, with a HashRenamer class:

src/lib/hash-renamer.ts
1
/**
2
* Creates a new hash generator class.
3
*/
4
export default class HashRenamer {
5
/** The max size of the generated hash name */
6
private maxSize = 8;
7
8
/** A map from original CSS names to their renamed equivalents. */
9
renames = new Map<string, string>();
10
11
/** A lists containing all hashed names */
12
values: string[] = [];
13
14
rename(key: string): string {
15
let value = this.renames.get(key);
16
17
// The key will be invalid when a hashed name is used as key
18
const isInvalid = this.values.includes(key);
19
20
if (isInvalid) return key;
21
if (value) return value;
22
23
value = getHash(this.maxSize);
24
25
this.renames.set(key, value);
26
this.values.push(value);
27
28
return value;
29
}
30
}
  • The maxSize will define the max length of the hashed name;
  • The renames will hold our old and new class names;
  • The values will hold ONLY the new class names;

The postcss-rename plugin will not keep the files context so, if the output has multiple CSS files, it will rename all renamed class names. That’s the reason we use the values array to validate if some hashed name is used as key.

See more: Support multiple CSS files

Hash method

Now, let’s create the getHash method. This function will loop from 0 to maxSize and take a random letter from CHARS constant.

src/lib/hash-renamer.ts
1
const CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_';
2
3
/**
4
* Generate a hash name
5
* @param maxSize The max size of hash
6
* @returns A string with the hash name
7
*/
8
function getHash(maxSize: number): string {
9
let result = '';
10
11
for (let i = 0; i < maxSize; i++) {
12
result += CHARS.charAt(Math.floor(Math.random() * CHARS.length));
13
}
14
15
return result;
16
}
17
18
/**
19
* Creates a new hash generator class.
20
*/
21
export default class HashRenamer {
22
/** The max size of the generated hash name */
23
private maxSize = 8;
24
25
/** A map from original CSS names to their renamed equivalents. */
26
renames = new Map<string, string>();
27
28
/** A lists containing all hashed names */
29
values: string[] = [];
30
31
rename(key: string): string {
32
let value = this.renames.get(key);
33
34
// The key will be invalid when a hashed name is used as key
35
const isInvalid = this.values.includes(key);
36
37
if (isInvalid) return key;
38
if (value) return value;
39
40
value = getHash(this.maxSize);
41
42
this.renames.set(key, value);
43
this.values.push(value);
44
45
return value;
46
}
47
}

Set up custom strategy

Open the astro.config.cjs file and add the custom strategy:

astro.config.mjs
1
import { defineConfig } from 'astro/config';
2
3
import rename from 'astro-rename';
4
5
import HashRenamer from './src/lib/hash-renamer';
6
7
const renamer = new HashRenamer();
8
9
// https://astro.build/config
10
export default defineConfig({
11
output: 'static',
12
integrations: [
13
rename({
14
rename: {
15
strategy: (key) => renamer.rename(key),
16
},
17
}),
18
],
19
});

When using this custom strategy, the prefix option from astro-rename will not work properly.

See my hash-renamer.ts fileto understand how i implemented CSS prefix on this website.

Testing with custom strategy option

Build the project:

Terminal window
npm run build
Terminal window
yarn run build

Run the output file using the VSCode Live Server extensionand take a look at the DevTools:

Devtools from custom astro-rename strategy
Devtools from custom astro-rename strategy - View image in a new tab

All class names have been replaced with hash names.

Two notes before using this astro-rename integration:

1 - Avoid naming your classes with html tags. E.g: body, title, link, img, etc…
2 - Avoid repeating class names on differents pages/components.

Using any method above will replace and/or confuse the replacement of the names since the plugin don’t save the CSS context

Conclusion

There you have it. A quick and simple integration to hash all CSS class names from your final Astro website.

Here’s the final project repository:

Resources and References

Footnotes

  1. Use the shortest possible names, in order of appearance: the first class is renamed to .a, the second to .b, and so on.

Enjoy this post? Feel free to share!
Share to Linkedin
Share to X (Twitter)
Share to Reddit
Share to Bluesky
Copy link

Comments

© 2023 Lucas Josino All Rights Reserved.