
Show HN: Fez, a file-based build tool for JavaScript - isaacb
http://isaacbw.com/general/fez/2014/01/20/fezes-are-cool.html
======
jdlshore
If you're interested in file-based tools, Jake [1] has excellent support for
the sort of rules Fez of offers, and is quite mature.

I haven't dug deeply into Fez yet, but here's a few things Fez seems to offer
that Jake doesn't:

1- Automatic concurrency. Like Gulp, Fez's subtasks run in parallel. It looks
like Fez launches them in subprocesses in order to prevent conflicts, which is
a good idea. I'm skeptical of parallelism in builds, though, because race
conditions lead to nasty, hard-to-detect-and-fix bugs. I don't think the
theoretical speed boost is worth the potential of defects getting into
released code.

2- Automatic pipelining. Also like Gulp, Fez can pipe the output of one
operation to the input of another. This is useful because you can avoid
dealing with temporary files. Unlike Gulp, Fez has an extremely simple and
non-error-prone way of constructing those pipelines. I like it.

The major advantage of Fez (and Jake) over Grunt and Gulp is that they use
file timestamps to tell if a task needs to run. This can lead to major speed
benefits. I recently modified my Jakefile to use this sort of dirty checking
on my Sass compiler. I don't change my CSS that often, but the css task was
doing an expensive "shell to Ruby" command on every build no matter what.
Adding dirty checking shaved my typical build time down from 6.5s to 3.5s.

Overall, Fez looks like a really nice tool. It has a strong ideology (rule-
based transformation of files) tempered by a nice dose of practicality. For
example, although Fez wants every task to define a file-transformation rule,
it also supports "imperative mode" for tasks that don't fit that model. It's
very promising, and I'm looking forward to learning more.

[1] Jake: [https://github.com/mde/jake](https://github.com/mde/jake)

------
robert-wallis
I'm suppose I'm in the minority of developers that _don't_ think we need to
learn more build tools.

make, configure, automake, autoconf, MSBuild, Apache Ant, rake, gradle, jake,
grunt, gulp, fez

Sorry, I'm sure your system is nice and organized. But now you've introduced
one more build dependency that will make projects based on Fez just a little
more difficult to on-board.

~~~
jdlshore
I couldn't disagree more strongly. Sure, make is a fine (if quirky) tool, but
I would hate to live in a world where that was the only build tool available.
There's good reasons people choose not to use it.

Fact is, people want different things from their tools. Each of the ones you
mentioned has its own strengths and weaknesses. They tend to be better than
their predecessors in some way, for some specific need. And this is how
progress is made... via a thriving marketplace of [ build tools, languages,
frameworks, libraries ]. I wouldn't have it any other way.

~~~
robert-wallis
One of the great things about open-source, is when you discover a weakness in
some tool you like, you can modify that tool and submit a patch. Or you can
learn from the source of one tool and add another tool to the marketplace.
When the marketplace is saturated, patching or modifying the popular tools is
preferable to me.

Also, I would prefer developers spend more time making general applications
and less time making tools for other developers. I'm not saying people
shouldn't make great dev tools, I'm saying more people should make great
applications, and less people should make great dev tools.

~~~
couchand
I agree, it's great to be able to fix problems with open source projects. But
there's not always one tool to rule them all

 _Fact is, people want different things from their tools._

------
scribu
I wonder what the pros/cons are for Fez, compared to Gulp:
[https://github.com/gulpjs/gulp](https://github.com/gulpjs/gulp)

~~~
jdlshore
Fez looks a lot more promising than Gulp to me:

1- Fez is more pragmatic. It has a strong ideology, but it also tempers that
with escape hatches for when your needs don't fit that ideology.

2- Fez's pipelining is really simple and elegant. Gulp's pipelining is verbose
and it's easy to forget to return the stream, which leads to race conditions.

3- Fez has dirty-checking so it won't run tasks on files that are up-to-date.

4- Task functions look much simpler to write (and thus, less error-prone).

I haven't tried Fez yet (and I have tried Gulp [1]), but I like what I see.

[1] My review of Gulp (wait for the comments to load):
[http://www.letscodejavascript.com/v3/comments/lab/1#comment-...](http://www.letscodejavascript.com/v3/comments/lab/1#comment-1197581116)

------
c4n4rd
I am in the process of creating a build tool too (for a different language:
Java) I noticed that you have some magic variables (%f), like make ($<,
etc..). I am trying to avoid that, but I cannot come up with a clean way
without 'magic' variables (e.g. When using wildcards, one would need to know
the set of files that have changed. Mine is something similar to

    
    
      classes/**/*.class -> src/**/*.java:
          javac [WHAT TO USE IF NOT A 'Maigc var'?]
    

Also:

1\. Will fez support different dir for target and recipes? (like above example
I gave) ?

2\. What about targets that do not have a file dependency (e.g. .PHONY in
make)? How does fez deal with it?

What I am trying to avoid is a big learning curve (or have a user need to read
a book) :-)

Thank you and success in your project!

------
ilaksh
I don't understand how to use it. Can I just write this:

    
    
        *.less → %f.css
        *.css → %f.min.css
        *.min.css → dist.min.css
    

in a file and then run the command "fez"? And if not, then why not? If that
was how you used fez then I would strongly consider using it.

If you are looking for a build tool, I strongly recommend you first consider a
bash script.

Or if you are still looking for a build tool, like you collect them or
something, I made my own too (lol):
[https://github.com/ithkuil/bild](https://github.com/ithkuil/bild)

Mine uses yaml files like this:

    
    
        - coffee:
            files: src/*.coffee
            out: lib
        - uglify: 
            files: public/js/*.js
            out: public/js/min.js

~~~
sintaxi
This is exactly how harp works. If you don't want to deal with configuration
harp implicitly does what you just suggested. You can run it directly as a web
server or compile your project to HTML/CSS/JS. It might be what you are
looking for.

------
possibilistic
This could turn out to be incredibly powerful tooling for Javascript
compilation.

I'm not a fan of Require-type systems because they introduce additional
runtime behavior. With the proper dependency graph tools available at compile
time, we could remove the need for AMD completely. This will reduce client
overhead and boilerplate. (Granted, AMD boilerplate will be converted into a
dependency graph spec. But it would be there regardless, and I am of the
opinion that this is a superior form.)

Exciting times ahead...

------
oakaz
Similar to Bud: [http://github.com/azer/bud](http://github.com/azer/bud)
([https://medium.com/p/6a4c74b4bd90](https://medium.com/p/6a4c74b4bd90))

See how Bud approaches building and watching changes;
[https://gist.github.com/azer/7819664](https://gist.github.com/azer/7819664)

------
CGamesPlay
Cool! I have two questions: does this support watching files to regenerate
them?

Second, one of the main features from my similar project (npm install webapp-
builder) is appending a socket.io connection to generated HTML to force a
browser refresh when files have finished building. I view webapp-builder as
too monolithic, so I'm curious how difficult it would be to implement a
similar feature in Fez?

~~~
isaacb
1) Since it only does the work that needs to be done, you can safely 'watch
node fez.js' and if there have been no file changes, nothing will be done!
This won't work on Windows, of course, but then I'm not sure if anything else
in Fez works on Windows anyway. I'll have to get that going here soon.

2) You can do pretty much whatever sort of transformation you want in an
operation. In fact, if you want I can take a look at your code and implement
that socket.io appending feature with Fez myself just to show how it can be
done.

~~~
CGamesPlay
Thanks for the info. It's not super hi-pri for me right now, but I've starred
the project and I'll drop by the IRC channel once I decide it's time to do
more work on webapp-builder. Seems like the auto-refreshing bit might make a
nice Fez builder (or step, or whatever the lexicon is).

------
delinka
Can someone compare and contrast this with Make?

------
jkrems
Pretty cool! Does it track dependencies of build steps that have "require"?
E.g. if I have a javascript bundle being built using browserify - will it
track the files that browserify is loading? Also: Did you consider reusing the
Grunt ecosystem? E.g. enable loading grunt plugins and treat this as a
potential alternate runner?

------
mmwtsn
Looks interesting. A note to the author: that post is very difficult to read
on mobile. Setting a width on your container will go a long way to improve
readability (e.g. .wrapper { max-width: 90%; margin: 0 auto; }).

~~~
isaacb
Fixed! Thanks for the heads up.

------
mikewhy
How does this compare to something like Brunch?
[http://brunch.io/](http://brunch.io/)

~~~
isaacb
I haven't seen Brunch before, but it still seems to suffer from the same major
flaw as Grunt, which is no sense of file-file relationships:

"Brunch recompiles and concats all your stuff automatically on any change,
headlessly. No more need in compicated Makefiles and watchers."

Perhaps I'm wrong, but Brunch just seems like a variant on Grunt with a lot
more out of the box for building front-end web applications.

Still, it _does_ look cool. Thanks for the link!

------
pencilcode
BTW, fezes is faeces in portuguese ;)

~~~
isaacb
Hah! I should probably change it to Fezzes then.

~~~
dgallagher
Also, there's a popular video game also named "Fez" which uses the same fez
hat in it. It probably won't lead to confusion since the game isn't a file
based build tool, though it'll be something you might have to indirectly
compete with in search results. :)

