duojs / duo

A next-generation package manager for the front-end
3.42k stars 118 forks source link

Proposal: Change how CLI handles arguments and stdout #400

Closed dominicbarnes closed 9 years ago

dominicbarnes commented 9 years ago

So, I have a proposal I'd like to make for duo's CLI. This is not backwards compatible, but I do think this simplifies things and makes them more predictable. (especially for new devs)

Currently, if you only have 1 argument it will always use stdout, even if you specify multiple entry files via a glob. This has bitten me a number of times, and I have to work around this behavior.

In addition, duo will inspect the last argument to see if it's a directory. If it is, that is assumed to be the output directory. (unless you specify --output)

Both of these are pretty "magical", since they can change without warning just depending on the number of arguments provided. (or the order they come in)

As such, I propose that we allow duo to treat all arguments as entry files, and to only change behavior when given explicit flags:

As an aside, I think we should treat arguments that are directories like assets, and recursively copy (or symlink) the entire directory to the output directory. (goes along with the above about treating all arguments the same) And to extend this concept a little further, any unrecognized filetype should just be copied/symlinked to the output directory as well.

stephenmathieson commented 9 years ago

-1 from me

I'm using duo < index.js > build.js in far too many places to go back and add a --stdout param :/

matthewmueller commented 9 years ago

I'm actually +1 in doing something, because I agree that the CLI is too magical.

The thing I like to be able to do is:

duo index.{css,js} build => duo index.css index.js build

We could probably make that less magical as you said by using an --output:

duo index.css index.js --output build

But what happens when you do:

duo index.css index.js

You can't really get a usable build from multiple assets. This is my main concern, I guess we could just error out saying you need an --output or something.

dominicbarnes commented 9 years ago

You can't really get a usable build from multiple assets. This is my main concern, I guess we could just error out saying you need an --output or something.

@MatthewMueller What do you mean by this exactly? --output defaults to build/, right?

@stephenmathieson Do you think we could get away with always using stdout whenever you use stdin as well?

dominicbarnes commented 9 years ago

I really like the idea of using duo to hook into all types of assets. It would make it really easy to hook in a plugin that could handle things like optimizing images, adding gzip compression for things, etc.

duo index.{js,css} public

Given the directory structure:

Would output the same structure in build/, along the way treating all the files within public as "entry" files that can be processed via plugins. But for now, all it would do is copy them to build following the same directory structure:

When referencing the assets in my HTML or whatever, I only need to know my own directory structure, which is far easier than having duo assign something else that I would need to either predict, duplicate or somehow get a hook.

stephenmathieson commented 9 years ago

Do you think we could get away with always using stdout whenever you use stdin as well?

hmm yeah probably

duo index.{css,js} build => duo index.css index.js build

@MatthewMueller why not just use a 5-second makefile:

CSS = $(wildcard index.css lib/*/*.css)
JS = $(wildcard index.js lib/*/*.js)

build: build/build.css build/build.js

build/build.css: $(CSS)
  @mkdir -p $(dir $@)
  duo --type css < index.css > $@

build/build.js: $(JS)
  @mkdir -p $(dir $@)
  duo --type js < index.js > $@

.PHONY: build

... now you get all of the mtime magic and stuff and still have a single command for building all of your assets ($ make build).

duo index.{js,css} public

@dominicbarnes again, a 5-second makefile does this for you:

CSS = $(wildcard index.css lib/*/*.css)
JS = $(wildcard index.js lib/*/*.js)
ASSETS = $(wildcard public/* public/*/*)

build: build/build.css build/build.js build/public

build/build.css: $(CSS)
  @mkdir -p $(dir $@)
  duo --type css < index.css > $@

build/build.js: $(JS)
  @mkdir -p $(dir $@)
  duo --type js < index.js > $@

build/public: $(ASSETS)
  @mkdir -p $@
  @cp -R $^ $@

.PHONY: build
dominicbarnes commented 9 years ago

@stephenmathieson Yeah, I end up using a Makefile just like that. However, it would be simpler if I could just pass in anything to duo and it behaves similarly. Then, you could simplify the makefile to:

JS = $(wildcard apps/*/index.js)
CSS = $(wildcard apps/*/index.css)
ASSETS = $(wildcard apps/*/public)

build: $(addprefix build/, $(JS) $(CSS) $(ASSETS))

build/%: %
    duo $<

Would be great if I didn't have to manually specify my own copy/symlink target in the makefile, especially since duo already has that capability baked in, we just need to expand it's scope a little.

With duo wanting to be an asset pipeline of sorts, passing assets directly to duo is ultimately what needs to happen. Giving duo the responsibility to copy/symlink to those assets is a great first-step.

stephenmathieson commented 9 years ago

i'm just thinking about how much code will need to be added to duo so that your makefile can be a few lines shorter... :/

dominicbarnes commented 9 years ago

We're actually going to be removing code here, since we will be removing some of the magic from _duo. Since duo already supports arbitrary assets (#171) the only real addition here is adding code to get the list of all files within a folder, which is pretty trivial.

Also, I'm not only trying to shorten my Makefile, this is about moving duo the direction it needs to go in order to be a real asset pipeline. In addition, this makes the behavior consistent and predictable, which is a big win.