- Setup Node
- setup NPM
- setup Webpack and webpack plugins
- setup Babel
- setup babel plugins
- setup a task runner: Gulp, Grunt, or scripts
- setup possible gulp/grunt plugins to run webpack or whatever else
Urgh, right? It can take a whole day or even two to have a properly setup project (and I’m not even getting into putting together a proper babelrc file, editorconfig, and so on).
On top of that, tools change all the time! Instead of Webpack, we used to use Browserify, now there’s Rollup and who-knows-what-else. Grunt used to be the king of the castle, but then Gulp swept it away and now people are moving toward using straight CLI commands. Babel? Do you guys remember traceur? Or do you just want to use TypeScript instead?
There are just so many choices and decisions to make. It’s fatiguing! And in fact, why do these decisions even matter when they will be obsolete within a year?
The problem has by default been the fact that front-enders are super-susceptible to this:
And the fact that we all want to “Invent Here” rather than implement NIH. In reality, the problems of a front-end developer have been solved time and time again. If you look at the problems for they are, you’ll see a much clearer picture:
- Step 1 — use a package manager
- Step 2 — use a bundler that deals with module loading
- Step 3 — convert ES2015/2016/2017 to ES5
- Step 4 — have a task runner that handles Step 2 and 3 automatically.
The reason everything is so difficult is interoperability, support, and people ignoring the fact that when something is “open source”, they can actually contribute and make a change.
The reason Gulp is such a pain in the ass today is that the wrapper between the actual tool you want to use (eg. Babel) and Gulp is usually an independent plugin developer that may or may not support the latest version of your tool and may or may not support all of the options. And the same goes for Webpack which has suddenly become its own task runner rather than just a simple bundler like Browserify (btw, Browserify deals with the same problem).
The issue in essence are the adapters that connect our tools, not the tools themselves. Why is it so hard? Why is there no easy standard API that connects our tools?
Node works perfectly fine by itself, have you noticed? To run Babel, you just require it. If you want to run Coffeescript, again, require it. If you want to run TypeScript, I can’t remember but I’m pretty sure you just require a hook and that’s it. This one-liner allows us to use a tool without having to think about it much.
Obviously, Babel has made things a little more difficult with its plugin system but at least we’re minimizing damage here.
The reason why there is nothing else to worry about with Node is because we created sane standards that make most libraries pluggable.
Ever notice that Node apps are all written in a similar manner? All of them look very much like ExpressJS apps? That’s because Node developers recognized the power of using Middleware and decided to pretty much standardize that API (get a reg, res, next, output a req, res, next). This means that when you have an authentication middleware, you don’t have to look for a specific plugin for your stack, you just use the middleware and it works with most back-end routers/frameworks.
THIS is what’s meant by modularity. I can grab a “connect” plugin and use it in a variety of frameworks. Not what the front-end JS developers are doing where each tool needs a specific plugin to function correctly. Even setting up a server in Node is pretty straight forward and works similarly across the entire platform. This reduces churn of our base platforms but allows us to keep innovating where it matters: with actual functionality.
What the front-end world is experiencing is a non-stop churn of “let me start over” rather than “let me add new functionality and features”. The beauty of Gulp (when it came out) was that the API was simple: everything was a stream. In fact, writing a Gulp plugin takes no time at all, and anyone can do it. This allowed developers to build a plethora of amazing plugins that did anything and everything you could imagine.
Except, people had to constantly write wrappers for libraries that didn’t wish to include Gulp in its toolchain (or at least a stream api). Fine, you don’t have to but look at how Node benefited from assuming an ExpressJS-like middleware syntax into most of its modules: ExpressJS doesn’t have to be used and libraries are portable.
I can appreciate that Babel is standalone or that TypeScript is as well, or Coffeescript, or Webpack, or Browserify but where it hurts is when developers try to shove this one tool into a specific box that has worked for a couple of years but is suddenly incompatible.
Same goes with Babel and trying to shove that into Webpack and/or Browserify.
> Each new tool we build requires a new wrapper for existing libraries and when that tool takes off, the old wrappers fall into deprecation
This gets multiplied many times over when tools wrap tools on top of tools. Gulp wraps Webpack to run it, Webpack wraps Babel to run it and so on. When one tool changes in that toolchain, we have to install and configure new wrappers. If you use Grunt with Webpack, you have to install a grunt plugin. If you decide to run TypeScript with Webpack, you have to install the correct loader and so on.
Recently, libraries have started migrating from Bower to NPM. Fucking great.
So why aren’t we making things TRULY modular?
Let’s Be Modular According To A Standard
Because otherwise, you’re not being modular. You’re creating a hellhole of dependencies that fatigue the best of us. I’m all for advancement as long as I can change one thing in my toolchain and not have to worry about the rest.
Can you imagine doing something like this in your code?
And when you change your toolset, all you have to do is this:
Why aren’twe building tools this way? Why aren’t we all suscribing to a standard API, not driven by a single tool, in order to run it?