Thursday, August 31, 2017

Controlling SPFx bundle file name in production builds

As promised, sharing the code as discussed in my SPFx advanced development session , in this blog post and in this GitHub discussion.


As you might know already, when building an SPFx component in production (gulp --ship) you could not control the produced file name of your bundle JS file.

The file would be generated as:
{product}.bundle-{hash}.js

That caused a lot of grief for our caching mechanism and our version management and product release strategy, preventing us from taking control over our cache strategy, using other java script optimization tools (due to the bundle file name) and publishing minor fixes without requiring our clients to install a new package.

It seems currently there is no supported way to control that, and that the production file name is being set hard coded in the copyAssetsTask.

After a lot of trials, I finally managed to find a way to control it, but it involves hacking into the build process in a way that I am pretty sure will not be future-upgrade proof.

So, until such time as the good people at Microsoft exposes this to us in a supported way, here is what you can do today.

Remove the hash from SPFx bundle file name

1. Load package-solution.json so that you can get the version number from it:
const packageJson = require('./config/package-solution.json');

2. Add this code in your gulp file, just before build.initialize(gulp);
var original_renameWithHash = build.copyAssets._renameWithHash.bind(build.copyAssets);
build.copyAssets._renameWithHash = function (gulpStream, getFilename, filenameCallback) {
var original_GetFileName = getFilename;
getFilename = function (hash) { return original_GetFileName(hash)
.replace('_' + hash, '.' + packageJson.solution.version); };
return original_renameWithHash(gulpStream, getFilename, filenameCallback);
};

Remove the .bundle from SPFx bundle file name

This one, was suprisingly simple to do.
Thanks to @iclanton pointing out, all you need to do is edit the config/config.json file, and change the outputPath property.

Adding a post build task

As a part of my trial an errors, I tried adding a post build task. It didn't help in this case since it runs before the bundle process begins but here is how you do it just in case you might need to:

//Add post build task. This still runs before bundle task
let renameFilesProductionTask = build.subTask'rename-files-production',
function(gulp, buildOptions, done) {
var production = (process.argv.indexOf('--ship') !== -1);
if(production)
this.log('Built in production!');
done();
});
build.rig.addPostBuildTask(renameFilesProductionTask);


I hope this helps. I will update this post once I learn if there is a better way to achieve this.

Thanks.

No comments: