Using npm as a Build Tool

This tutorial is out of date and no longer maintained.


Every developer will love this saying “It is hard to build software without using a build tool.” To get rid of the repetitive tasks, we are using build tools. If you think Gulp has killed Grunt you may want to think about another tool because npm has surpassed both.

Now Node provides a great way to implement a build process with only npm.

Imagine a situation where using build tools makes you horrible, I felt the same thing when I use Grunt and Gulp. Now that I have been using npm as a build tool, I feel more comfortable. Here I will share with you how to do the same and make yourself comfortable while using the build tool.

At the end of this article, we will be making our own boilerplate.

Drawbacks of using others

When using Grunt or Gulp, the packages specific to that build tool are usually just wrappers on the main package. For instance, gulp-sass is really a Gulp-specific wrapper to node-sass. We can go straight to the source and just use node-sass with npm!

There are drawbacks to using Grunt/Gulp-specific packages.

  1. We need to watch the versions of each sub-module which we are using. If anything gets updated or removed we have to look for another one to achieve the same. But here with npm, no such problem will come.
  2. Adding new tasks into the build tool will increase dependencies. But here we can use command prompt commands like && to combine multiple tasks.
  3. Custom script file (like Gruntfile.js) for tasks. Here only package.json file is enough.
  4. Doesn’t support any commands which we use in the command prompt. Here you can use all commands in your package.json file.

Types of npm scripts

  1. Default scripts
  2. Custom scripts

Getting started

Let’s start our build commands!

  1. Create an empty directory and initialize it as npm using npm init. It will ask you to construct your package.json file. If you feel lazy like me to hit enter many times, then go with shorthand script npm init --yes.

  2. Now check your directory, a package.json file gets created like this:

  "name": "your_directory_name",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  "keywords": [],
  "author": "",
  "license": "ISC"
  1. By default, a test script will get created inside the script object. Inside the script object, we are going to configure our tasks.

  2. Run the default task using npm test shorthand for npm run test:


It states that node_modules missing. We have to add our dependencies.

  1. Let’s install dev dependencies first:
  • npm i -D jshint lite-server mocha concurrently node-sass uglify-js
  1. Let’s start creating our scripts:
"scripts": {
  "dev": "lite-server"

npm run dev - I have used it as a development server. lite-server will take provide browser-sync for live-reloading. We don’t need to configure a watch property for all your files like (HTML, CSS, JS).

To know more about lite-server refer docs.

  "scripts": {
    "db": "json-server --watch db.json --port 3005"

npm run db - If you want to know more about JSON-Server refer my article.

  "scripts": {
    "start": "concurrently -k \"npm run dev\" \"npm run db\""

npm start shorthand for npm run start. Concurrently, using it we can perform two tasks simultaneously. You can also combine both the tasks using && operator. To know more about it refer docs.

  "scripts": {
   "uglify": "mkdir -p dist/js && uglifyjs src/js/*.js -m -o dist/js/app.js"

npm run uglify - It will minify your JavaScript files and move them into your desired directory. It will create a new folder only if it does not already exist (-p flag).

  "scripts": {
    "lint": "jshint src/**.js"

npm run lint - It will look for any JavaScript files inside the source folder and helps detect errors and potential problems in your JavaScript code.

"scripts": {
  "sass": "node-sass --include-path scss scss/main.scss assets/main.css"

npm run sass - It allows compiling your .scss files to CSS automatically and at a good speed.

"scripts": {
  "test": "mocha test"

npm test shorthand for npm run test. Mocha is a JavaScript test framework, which helps you to write test cases.

"scripts": {
  "bash": "Location of the Bash/Shell script file"

npm run bash - If you think you’re making a lot of commands inside the scripts object, you can make it as Bash/Shell script and include it in your package.json file as above.


So far we have seen the basic npm build commands and explanations for them. Let’s start to prepare our own boilerplate. Using this boilerplate will save your time in preparing the build tool. Allowing you to invest more time in building your app.

"scripts": {

  "start": "concurrently -k \"npm run dev\" \"npm run watch-css\"",

  "dev": "lite-server",
  "db": "json-server --watch db.json --port 3005",

  "build-js": "mkdir -p dist/js && uglifyjs src/js/*.js -m -o dist/js/app.js",

  "lint": "lint jshint src/**/**.js",

  "build-css": "node-sass --include-path scss scss/main.scss assets/main.css",
  "watch-css": "nodemon -e scss -x \"npm run build-css\"",

  "test": "mocha test",
  "pretest": "npm run lint",
  "posttest": "echo the test has been run!",

  "bash": "Location of the bash/shell script file"

This boilerplate will take care of all the necessary things which we need during the development phase like:

  1. npm run dev- Bootstraps our app, opens it in the browser, reloads the browser whenever we make changes in the source.

  2. build-js- Minifies all our JavaScript files, which will be needed during production.

  3. watch-css- Nodemon is a utility that will monitor for any changes in your source and automatically restart your server. Here I have used it to monitor for any changes in the .scss file, if there are changes, it will restart the server and build our CSS.

"scripts": {
  "test": "echo I am test",
  "pretest": "echo I run before test",
  "posttest": "echo I run after test"
  1. npm test- It wraps the above three commands “pretest test posttest” and executes them in the order I have listed. Initially when you hit npm test it will look for pretest command. If it is there, it gets executed first, followed by test and then posttest. During the lookup, if it doesn’t find the pretest command it will directly execute the test command.

The remaining commands I have explained in the previous section. You can also customize this boilerplate based on your needs.


I hope this article has saved your time while preparing a build tool. Now we have prepared our own boilerplate for npm as a build tool. I hope now you will accept npm has killed both Grunt and Gulp. Feel free to use my boilerplate and contributions are welcome. Further, you can refer to the official npm scripts.

If you have any queries, please let me know in the comments.

Creative Commons License