FE / js / node

Versioning, banners and why you may consider using it

One day, while working on a big project I had a manager coming angry at me.

What have you done guys? Did you test the code after integration at least to be sure it was fine?

We were close to a deadline — a lot of pressure as we were going to go live soon — and she was worried and furious because all of the bugfixes in UAT were getting rejected.

I could understand her, the deadline was so close.

It took me 20 very unpleasing minutes to discover that the testers had been testing the old release instead of the new one.

It was not the first time I had been dealing with testers testing the wrong thing but this time the experience was so shocking and aggressive to make me have a “No more in my life” moment and actually do something about it.

I thought I’m gonna put a hash or token or similar within the css and js files and the comment task so that the tester can immediately tell if she’s testing the right release or not.

We were already using semver and npm version for the release, so I end up using the version number and a timestamp within a banner.

With that in place, not only the testing experience started to get smoother and smoother but basically, the whole process sped up as it started to be very clear and obvious for everyone (not only the testers) which code we had and in which environment.

We even discovered some caching issues along the way (and fix them, of course) but that’s another story.

Hoping this story enlightens the importance of having a banner with some identifier, let’s dive into the code.

webpack

If you have webpack in place within you project, it should be pretty straightforward to get a banner as you can use the webpack bannar plugin.

// within webpack.config.js
const package = require('./package.json');
const banner = `${package.name}-${package.version}-${new Date().getTime()}`;

module.export = {
    entry: ...,
    output: ...

    .
    .
    .

    plugins: [
        new webpack.BannerPlugin(banner)
    ]
};

@borracciablu/banner-cli

In case webpack is not present in the project you are working on, having a cli tool that does just this task may be the right idea.

Something you could drop within the package.json in the scripts section with some configs to do the trick.

Possibly with a stable API so You won’t have to re-do the setup on every update.

This would have had the benefit of being independent of any bundler or toolchain.

For this tasks, I would recommend an open-source package I’m working on, which is @borracciablu/banner-cli.

Note: Most of the variables in package.json are accessible via a node script using the npm_package_ prefix. E.g.: $npm_package_version

//
// The example is using NEXT_TAG=$(semver $npm_package_version -i patch) 
// because sometimes you may want to banner files before bumping up a release.
//
// as per the docs
{
    "scripts" : {
        "banner:patch": "NEXT_TAG=$(semver $npm_package_version -i patch) banner-cli 'dist/*.js' --template='/*! v[tag] :: [time] */' --tag=$NEXT_TAG"
    }
}

How did @borracciablu/banner-cli was born?

I start exploring and discovered a package called banner-cli but I soon found that it was not playing nice with the css generated with node-sass.

Long story short, this was happening because node-sass uses a BOM character and the package used by banner-cli to prepend the banner was ignoring it.

This lead me to try to contribute to some of these projects and use my branched repo for a while but I late realised that banner-cli was not actively maintained and with the need for some new features (e.g.: template, debug, dry-run) @borracciablu/banner-cli was born.

In summary

We saw how a banner with some unique identifier can consolidate communication within a team and speed up things while avoiding frustration.

Then we saw how to implement a solution using the webpack bannar plugin or the @borracciablu/banner-cli cli tool.

Links