Sombriks Has A Plan



Using GNU Make as your preferred javascript build tool

So, Make was created a long long time ago and the tales told us that it's destined to be recreated again and again over the eons, because people don't understand how make works.

Ant, SCons and others exists because people didn't understood make.

For Maven and Gradle we open a small exception since they do more than build.

What we cannot forgive is mistakes like gulp and grunt.

You see, there is a reason to use specialized DSL's instead general purpose languages to build complex projects.

You need to be objective.

You need to be simple.

Make do this since the dancing days.

Even yet javascript people got too puzzled that decided to make things on their own.

Enough talk, look at this:

# Makefile
export PATH := ./node_modules/.bin:$(PATH)

clean:
  rm -rf public

prepare:
  mkdir public

build: clean prepare
  browserify src/main.js -p common-shakeify -o tmp.js
  uglifyjs tmp.js --compress  --verbose > public/build.js
  cp index.html public/index.html
  cp -r assets public/assets
  rm -rf tmp.js

release: build
  firebase deploy

dev:
  budo src/main.js:build.js --live --wg="**.{html,css,js,vue,md}" --open -H 127.0.0.1

And of course you call it invoking make and a target, for example:

make build

The line setting up the $PATH is just to make sure the non-global tools inside the node_modules/.bin will be found.

Wanna see the same thing with gulp?

// gulpfile.js
const gulp = require("gulp"); // npm i gulp --save-dev
const budo = require("budo"); // npm i budo --save-dev
const del = require("del"); // npm i del --save-dev
const browserify = require("browserify"); // npm i browserify --save-dev
const fs = require("fs"); // built-in node fs module

const dev = cb => {
  budo("./src/main.js", {
    serve: "build.js",
    live: true,
    open: true,
    host: "127.0.0.1",
    stream: process.stdout,
    watchGlob: "**.{html,css,js,vue,md}",
  });
  cb();
};

const clean = cb => {
  del("public").then(_ => {
    fs.mkdirSync("public");
    cb();
  });
};

const build = cb => {
  browserify({
    entries: "src/main.js",
  })
    .bundle()
    .pipe(fs.createWriteStream("public/build.js"));
  fs.copyFileSync("assets", "public/assets");
  fs.copyFileSync("index.html", "public/index.html");
  cb();
};

const release = cb => {
  cb();
  // not implemented yet. maybe never.
};

exports.dev = dev;
exports.clean = clean;
exports.build = gulp.series(clean, build);
exports.release = gulp.series(clean, build, release);

To make it work you'll need these dev dependencies:

npm install --save-dev gulp

In order to see it happening, hit your bash with this command:

npx gulp build

And that's it, twice lines of code for half functionality seen on Makefile.

Please don't ask me for the Grunt version.

The only serious caveat to pay attention when adopting Make is windows.

But a windows development environment for modern web will always present exotic challenges. Like the maximum path size

Conclusion

So, if someone asks you to set-up grunt or gulp for a brand new project, please don't.