One of the studies with the Center for Media Engagement needed a straightforward way to maintain and deploy a single JS file. I didn’t want to use a big fancy WebPack or Gulp setup when all we needed was to minify and version a single JS file, so I turned to using npm scripts
.
tl;dr
The following package.json
file, when you do npm run production
will:
- Check your
package.json
version and increase it by 0.0.1 - Minify your
script.js
file asscript.min.js
- Add the new version number and build time to the header of your
script.min.js
file
{
"name": "my-rad-scriptz",
"version": "0.0.1",
"description": "This script is the kewlest!",
"scripts": {
"minifyJS": "uglifyjs scripts.js --compress --mangle --warn --output scripts.min.js",
"production": "npm run version:bump --silent && rm -f scripts.min.js && npm run minifyJS --silent && npm run version:add --silent",
"version:add": "echo "/*! My Rad Scriptz!!!!1!11! v - $(npm run version:extract --silent)n * © Someone probably n * Build time: $(date '+%m-%d-%Y %H:%M:%S')n */n$(cat scripts.min.js)" > scripts.min.js",
"version:bump": "npm version patch --no-git-tag-version --silent",
"version:extract": "cat package.json | grep version | head -1 | awk -F: '{ print $2 }' | sed 's/[",]//g' | tr -d '[[:space:]]'"
},
"author": "Rad D00d",
"devDependencies": {},
"dependencies": {
"uglify-js": "^3.3.11"
}
}
Thanks to the A11y Dialog project, as that’s where I got the command for reading the version number from package.json
.
The Set-up
To get started, create a new directory and script file to host your project. I’ll use terminal commands to do this stuff because it’s useful to know and we’ll need to be in terminal when we start running npm
commands anyways.
# create the directory
mkdir my-rad-project
# change directory (cd) into your new project directory
cd my-rad-project
# create a scripts file
touch scripts.js
# create a package.json file
touch package.json
Copy and paste the package.json
contents above into your package.json
file.
Now, make sure you’re in your my-rad-project directory (you didn’t change it, did you!?!?) and run in terminal:
npm install
This will install any packages in the devDependencies
and dependencies
sections of your package.json
file. In this case, it’s only uglify-js
, which is what we’re using to minify our JavaScript file.
Now, when you build production assets it will take whatever is in your scripts.js
, minify it into scripts.min.js
and add the new version number into the header of scripts.min.js
.
While still in your my-rad-project directory to kick off the minification process, run in terminal:
npm run production
How it Works
Our package.json
file contains a scripts
object where we can define shortcuts for running terminal commands. Each of those scripts we could run via terminal, but why would we when can just do npm run production
?
When we do npm run production
, it runs whatever is in the production
section of the scripts
. In our case, it’s this:
"production": "npm run version:bump --silent && rm -f scripts.min.js && npm run minifyJS --silent && npm run version:add --silent"
This one command, npm run production
, ends up running multiple other commands, chaining them together with &&
.
# npm run production runs... (the --silent tag suppresses output to terminal. otherwise you get lots of unnecessary stuff output in your terminal window)
npm run version:bump --silent && rm -f scripts.min.js && npm run minifyJS --silent && npm run version:add --silent
# which runs npm run version:bump (increase the version of package.json by 0.0.1)
npm version patch --no-git-tag-version --silent
# and then runs rm -f scripts.min.js to delete our old scripts.min.js file
# and then runs npm run minifyJS to minify the script.js file into script.min.js
uglifyjs scripts.js --compress --mangle --warn --output scripts.min.js
# and then runs npm run version:add to prepend a comment to scripts.min.js with the new version number and timestamp
echo "/*! My Rad Scriptz!!!!1!11! v - $(npm run version:extract --silent)n * © Someone probably n * Build time: $(date '+%m-%d-%Y %H:%M:%S')n */n$(cat scripts.min.js)" > scripts.min.js
# which, during npm run version:add has $(npm run version:extract) that runs to find the new version number
cat package.json | grep version | head -1 | awk -F: '{ print $2 }' | sed 's/[",]//g' | tr -d '[[:space:]]'
Whew! See why it’s lots easier to just do npm run production
?
2 responses to “Tutorial: How to Minify & Version a JS File with NPM Scripts”
Hi Jeremy, is there a way to provide uglifyjs with a folder of javascript files and have it minify the JS but spit out the separate minified files instead of combining them into one? Thanks.
LikeLike
I’m sure it can be done, but I’m not sure of the best way to do it at the moment. I’d start by taking a look at some of the ideas here: https://stackoverflow.com/questions/10523415/execute-command-on-all-files-in-a-directory.
LikeLike