DEV Community

Piotr Sobuś
Piotr Sobuś

Posted on

Angular & Gulp: custom assets hashing mechanism

In this post you will learn how to create a flexible, fully customizable and easily maintainable cache busting mechanism using gulp.js for Angular applications. We'll compose a 2 step pipeline that hashes all files in the assets directory after application build is performed.

First, let's install all the required libraries.

npm install -D gulp gulp-rev gulp-rev-replace gulp-rev-delete-original

Alright, let's create our pipeline. Create a new file in the root directory and name it gulpfile.js. Good, now import all the dependencies inside the file.

const gulp = require("gulp");
const rev = require("gulp-rev");
const revreplace = require("gulp-rev-replace");
const revdel = require("gulp-rev-delete-original");

const { name } = require("./package.json");
const assets = `dist/${name}/assets`;
Enter fullscreen mode Exit fullscreen mode

Let's create a first task that will traverse the assets folder and append unique hashes to the file names.

gulp.task("hash:revision-media", () =>
  gulp
    .src(`${assets}/**/*.*`)
    .pipe(rev())
    .pipe(revdel())
    .pipe(gulp.dest(assets))
    .pipe(rev.manifest())
    .pipe(gulp.dest(assets))
);
Enter fullscreen mode Exit fullscreen mode

I will briefly describe each step:

(1) locates all matching files and reads them into memory to pass through the stream

Having inserted this pattern, gulp will match any file with any extension in any directory. If you want to target a concrete extension or multiple extensions, use a glob pattern syntax {x1,x2,..,xn}, e.g: *.{jpg,jpeg,png}

(2) hashes a file, e.g: mylovelydog.png -> mylovelydong-df1cr0g.png
(3) removes old, unused fingerprinted files
(4) writes hashed assets to build directory
(5) maps the original paths to the revisioned paths and places the directory in a manifest file
(6) writes the manifest to build directory

Now, we need to find all occurrences in our bundled output files and update them by replacing the original paths with the hashed ones using our manifest that holds all the mappings.

gulp.task("hash:replace-hashed-media-imports", () => {
  const manifest = gulp.src(`${assets}/rev-manifest.json`);

  return gulp
    .src(`dist/${name}/*.{html,css,js}`)
    .pipe(revreplace({ manifest }))
    .pipe(gulp.dest(`dist/${name}/`));
});
Enter fullscreen mode Exit fullscreen mode

Almost there! Now, we will combine these two tasks into a single task.

gulp.task(
  "optimize",
  gulp.series("hash:revision-media", "hash:replace-hashed-media-imports")
);
Enter fullscreen mode Exit fullscreen mode

Finally, let's set up our package.json in the way that our pipeline will run after build is complete.

"scripts": {
    ...
    "postbuild": "gulp optimize",
},
Enter fullscreen mode Exit fullscreen mode

Done. I hope this post will help you building your own pipeline. If you have any questions, feel free to ask them in the comments!

Latest comments (1)

Collapse
 
siriusv21 profile image
SiriusV21

Not working, the manifest file is containing paths without dist/${name}/ in prefix and maybe thats why its is not changing the refernces in the output build