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:

  1. Check your package.json version and increase it by 0.0.1
  2. Minify your script.js file as script.min.js
  3. 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?