Webpack – How to Transpile and Minimize JavaScript Code and Import as Plain Text

This will be a quick one.

Over the weekend, while working on feature for an app, I had the need to import a JavaScript file as a raw text string but also ensure that its content was ES5 compliant and minified. The feature I was working (for SharePoint MyBoard) was around being able to provide the user with a code snippet that allowed them to “embed” a widget into other pages/sites.  The code snippet did not have to be legible to the user and my goal was to make it as short as possible.

The Loader

To do this, I needed a webpack loader (not a plugin) that would allow me to run the JavaScript file through Babel (to transpile it to ES5 code), then minimize the ES5 code (I am already using UglifyJS in the project) and then finally get the content of that file back as a raw value (text string – I am already using raw-loader).  So basically, the flow (from a webpack loader standpoint) is: raw-loader!minify-loader!babel!./my/file.js.

My first effort at this was to see if there was already a “minify-loader” out there that I could use, but my search skills did not reveal anything that could have helped me achieve the above. Because loaders are very easy to create in Webpack and this one was simplistic in nature, I just decided to create it myself – here it is (all 4 lines of code):


const UglifyJS = require("uglify-js");

module.exports = function minifyLoader(source) {
    return UglifyJS.minify(source, {fromString: true}).code;
};

This loader was saved along with my project’s source and not installed as normal loader are. This is OK, because Webpack support defining loader by path, so using it is not a problem.

Using It

My webpack setup already had module.rules to handle .js files, thus adding another one that would use the above loader chain only for the one file would just complicate the setup (with use of exclude/include/regexp). Because I only needed this for a single file, I instead changed the import statement to include the desired loaders – in other words, I used webpack’s inline loaders feature.

So my component that needed the JavaScript code to be provided as a string now includes the following import which achieved my goal:


import embedCodeSnippet from "raw-loader!../path-to/minify-loader!babel-loader?{\"presets\": [ [\"env\", { \"modules\": false }] ] }!./embed-code.js"

In my case, (as you can see above) I also provided Babel some inline options.  Yes, that is an ugly line of code and goes against my normal pattern of not including loaders into the source, but in this case it made sense and it was the path of least resistance.

I did think about whether I should post this to github and create an official webpack loader out of it. To do that, I should probably make it more robust – like accept options that are passed along to UglifyJS or even support other minifiers, like babel-minify or perhaps even UglifyJS-next. Perhaps in the near future I will do that, but for now I hope that the post above is enough to get you going should you encounter the same need.

 

</Paul>

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s