node-task / spec

A specification for javascript tasks.
MIT License
153 stars 2 forks source link

Where is the overlap? #20

Open balupton opened 10 years ago

balupton commented 10 years ago

In the meeting between Grunt, Brocolli, DocPad, and Gulp, there was a pre-supposition that our tasks/plugins/scripts (adapters) are duplicating effort, because the plugins are trying to do the same thing.

Jo challenged this saying that most adapters are really simple, in which BenA replied that things like sourcemaps makes them really complicated. Both are true in my own experience. Our CoffeeScript adapter is a few lines, but our SASS plugin are many more due to sourcemaps support.

However, I fail (at this point) to see how having one adapter for each library, will actually reduce effort, or perhaps be possible.

For instance, DocPad works with buffers, Gulp works with streams, Grunt works with files. Each of these are fundamentally different at this stage. Each go about what they do differently, in simplified terms; DocPad uses an in-memory database, Gulp takes stream input and outputs stream output, Grunt takes configuration, and reads and writes files. Each of these require different contexts, hence why we each have our own adapters, to allow a common module, e.g. a rending engine, to actually be able to be applied to our applications context.

For things like DocPad's SASS plugin. It is unfortunate that it is so complicated due to the sourcemap support (among the support for compass, requires, stdin, files, etc). However, I don't see the solution to this complication, to be having a unified task spec.

Lets say right now, to provide an example, I have the project bevry/projectz, I mentioned this to a grunt user, and they said that they wouldn't use it because it isn't a grunt task, the wording here is very very important. When I said that you could include projectz as a npm module, into a grunt task, they were confused. Which then lead me to drawing the following:

ben's sketch

In this sketch we have DocPad, Grunt and Brunch, all each with an overlap with NPM Modules. In the ideal, the overlap is the adapter, and the npm module is a generic npm module that makes writing the adapters trivially easy.

For instance, let's take the docpad feedr plugin. If I were to make this as a grunt task, or as a docpad plugin*, then the feedr functionality would actually be inside the task, and then only compatible with systems that implement that task framework. E.g. grunt tasks only work with grunt, you can't just npm require them into another npm module without also requiring grunt and setting up grunt and all that (same goes for DocPad currently).

However, in the case of the feedr plugin, we actually have all the heavy lifting abstracted out into a generic npm module that any task, module, whatever can use. https://github.com/bevry/feedr — making our actualy docpad feedr plugin, trivial. It is simply an adapter for the module.

So there are really few ways proposed that we can take this:

  1. Context-specific (application-specific) adapters around generic npm modules
  2. A generic task standard, that requires the implementors to implement a particular task framework (like the current grunt and docpad setups)
  3. A generic task standard, that can be npm required without any task framework (docpad will move into this direction, it is planned).

Personally, I like 1 and think it is the most freeing, applicable, and instantly implementable solution. Grunt tasks should be trivially simply, as all the heavy lifting should be there own module. I shouldn't have to have a grunt configuration file, I should just be able to do require('some-grunt-task')(someGruntConfiguration) and be done.

2 I think will suffer from all the exact same problems as grunt and docpad currently face.

3 I think is a good option that we are already working on. DocPad plugins are already really generic and well documented. They can theoretically work without DocPad already, but it just isn't well documented nor supported. It will probably take a week or so of work to make our entire plugin system generic so anything can use it, but right now there is no need to do so. But it would certainly be cool.

tkellen commented 10 years ago

3 is definitely the direction I'd like to go. This morning I cleaned up the node-task org (moved all but the spec repo to my personal account) and started cleaning up the spec wiki as well. I'm super excited to get into the concrete implementation details of this. Hopefully I'll be ready for us to do that in the next few days.

I really appreciate you taking notes and dropping them in the wiki, Ben!

RobLoach commented 10 years ago

If I read this correctly, looking at grunt-contrib-cssmin, we may end up with a number of different npm modules:

npm module Description
clean-css The Logic
node-tasks-cssmin The Node Task
grunt-contrib-cssmin The Grunt adapter for node-tasks-cssmin
gulp-cssmin The Gulp adapter for node-tasks-cssmin
docpad-plugin-cssmin The DocPad plugin for node-tasks-cssmin

In essence, this would abstract the way generic configuration-driven tasks are handled, allow the same business logic across all different platforms. Grunt, Gulp, DocPad, it wouldn't matter as all of them would use the same node-tasks-cssmin configuration spec. This eases the maintainability of each module, as well as reduce the amount of duplicate code across modules.

tkellen commented 10 years ago

@RobLoach That is one possible route, but I'd rather see this:

npm module Description
clean-css The Logic
clean-css-task The Node Task

If we can iron out a spec that can cover the use cases for all task runners, we only need one task.