
Show HN: Nodal. Next-Generation Node.js Server and Framework - keithwhor
http://www.nodaljs.com/
======
dev360
Long time Django (and occassional rails) dev here.. I've messed with Node from
time to time but never really been wowed by the fragmented eco-system around
Express (or flask either for that matter).

This looks like a node framework that I'd really enjoy using - first time I
see a framework that feels like it fits around ES6. For me personally, having
a good ORM and models layer, coupled with migrations have been a deal breaker
in choosing a framework, and I'm very happy to see that here.

Is everything written from scratch or are there dependencies? If so, it sounds
like its actually quite an opinionated microservice architecture.. Lately I've
felt like microservice and microframeworks have gone hand in hand :)

Great job!

~~~
tbrock
It's been a while for me since I last used Django but i recall it not having a
migration framework (besides south).

Language preference aside, I feel as though rails might be a better Django
than Django is in almost all areas that you define as deal breakers.

~~~
ph4
Starting with Django 1.7, migrations have been available in the core package.

------
irregularexp
A little off-topic, but I figured the people reading the comments here would
be the best place to ask. Why use JavaScript on the server at all? I've
developed on both the front end and back end, and written non-trivial server-
side code in a number of languages, and I don't see any use-case where
JavaScript is "best-in-class." It seems like whether you're aiming for
ease/speed of prototyping, pure performance, a good concurrency model, or...
any other task I can think of, there's a better tool for the job. There seems
to be a decent number of people and companies using Node, though, so let me
know what I'm missing!

~~~
tzaman
One language to rule them all. There is no way to handle complex UIs in the
browser without JavaScript. So while you absolutely need JS developers, why
not make the API/backned in the same language so that you can hire additional
developers that know the same language your existing employees already do.
From an employer's perspective, it's easier to manage and (re-)allocate
resources if need be.

JavaScript is becoming the web darling (or it already is?), whether we like it
or not. And with some nice syntactic improvements ES6 brings, I don't mind.

~~~
moonchrome
>There is no way to handle complex UIs in the browser without JavaScript

Dart, ClojureScript, TS (technically JS superset but still a considerable
improvement) are just the ones I've used.

And I'd rather use both of them on server (Dart/Clojure) than JS.

There are other languages as well.

ES6 is a pain in the ass - no browser supports it and using transpilers +
polyfills and the JS build/package tools to set that up is a PITA that only
grows as you add dependencies and it bloats your code size to be comparable or
larger than the compile-to-JS languages without making the language
significantly better.

~~~
Wintamute
Why is transpiling ES6 any more of a PITA than transpiling Clojurescript? ES6
to ES5 is a one shell command with Babel. And TS is ES6 but with type
annotations. And ignore all of the myriad of high quality plain JS modules on
npm at your peril. I like Dart and ClojureScript too, but I've really enjoyed
working on ES6 and ES5 projects too. I don't doubt your Dart and ClojureScript
credentials, but your comment betrays ignorance of ES6 and the plain JS
ecosystem.

~~~
moonchrome
>ES6 to ES5 is a one shell command with Babel.

You still need to include core.js to polyfil basically everything from
standard library. And then you need to make sure Babel works with your
framework (like Polymer or what not), and that's just the start of the interop
hell that is using different JS libraries together. Rule of thumb - anything
you add to your JS build system = increase in the likelihood of hair pulling
when things break - and babel and core.js are two such things.

The value I get from ES6 compared to the CLJS change how much I'm willing to
tolerate the PITA factor of the build system.

In dart I don't have to do any of that, just add few lines to pubspec.yaml
with dependencies and transform directives and off I go. And every other
library uses the same build system and the same package manager and the same
standard library !

~~~
pfooti
I have not found that to be the case. I run my code through gulp-babel and
done. There is no runtime AFAIK, although there was one for traceur.

I have also had no real problems interopping with other big libraries. I think
the biggest point of discontinuity would be the class keyword vs other class-
like libraries (like coffeescript's implementation). Even that's not too bad,
I'm able to extend those using es6 class syntax, I just need to be careful
about calling super and setting up the constructor properly.

------
chvid
Great work and very good presentation.

(These comments are just from watching the first video.)

But how is this next-generation? It seems to be very inspired by established
widely used web frameworks such as Ruby on Rails. With elements such as ORM,
routing, controllers, HTML templates.

It also seems to require a lot of code generation. Is that really
constructive? (What happens if I edit the various generated files, would I
still be able to add field to a record using the command line tools). Couldn't
you have moved some of the boilerplate into the framework?

Why not use ES6 imports? (Rather than require / Nodal.require)

Why create an ORM rather than use a JavaScript-orientated NoSQL database?
(mongo, couch etc.)

~~~
brazzledazzle
>Why create an ORM rather than use a JavaScript-orientated NoSQL database?
(mongo, couch etc.)

I could be way off here (and I probably am) but shouldn't frameworks abstain
from being too opinionated about the particular technologies that you use? The
database (or type of db) you choose seems like something that should be based
on what your application's requirements dictate not what your framework
prefers right?

~~~
adrusi
My opinion differs: if you're going to package your tool as a "framework"
rather than a "library", you should integrate a large vertical section of the
technology being used. This doesn't mean you have to be coupled with a
particular database server, but you should at least have special support for
one that can be swapped out for something else.

If a framework can't offer me this kind of functionality, why would I want to
use it over a library with all the control benefits that brings.

------
voidr
The project is still 0.5 and it has a lot of cool ideas that most other NodeJS
frameworks lack. That being said, here are the things I feel would be worth
improving, based on the first video:

Writing tests for the Controllers would be a real pain, because you would have
to do a lot of ad hoc mocking, it would be better if the controllers would
return something instead of calling the this.render.

You might be able to make the the controllers into POJO's.

The file naming conventions are weird, mixing camel case coding with
underscore filenames is just unnatural.

Having a custom 'require' function in the framework, means that any code I
write, is dependent on the framework itself.

The automatic migration generation is pretty sweet.

Coupling the data models with DB configuration is a bad habit.

The use of static methods to define aspects doesn't feel natural.

Having one big routing file doesn't scale, the routings should be expressed in
the controllers.

Overall I would recommend adding in TypeScript, it would allow a lot more
cleaner code.

~~~
keithwhor
Thanks for the suggestions, but a lot of the things you dislike were choices
made very purposefully.

1\. POJOs are ugly and you must revert back to using Object.create() for
inheritance, breaking the design pattern of using ES6's class syntax.

2\. PascalCase class <-> camelCase instance <-> underscore_filename <->
underscore_tablename is a standard borrowed from Rails and easily managed
through the npm inflect module (i).

3\. It's just a shortcut. You can use normal CommonJS require(), you'll just
have to resolve the relative path yourself.

4\. Thanks! :)

5\. Models can exist without database connections and with manually defined
schemas. If you check through the commit history, I used to keep database and
model completely separate but there was way too much code reuse / smell
(passing in a db as a parameter on every function call).

6\. The alternative is setting properties with ClassName.prototype.value =
'xyz'; or ClassName.value = 'abc'; Static methods provide an easy to read +
concise way to do this for you (and take care of additional functionality).
Also borrowed from Rails.

7\. Chose that pattern because it is very explicit / ordered. How do I
determine what order the routes are hit when I specify them per Controller?
And if I define them on the Controller, that means I need to load all
Controllers globally on Application start.

8\. I'm happy with how clean the code is now. :)

------
pfooti
This looks interesting, and although I'm already committed to an ad-hoc
framework on my current projects, I'll check it out for future ideas (or to
import some of your ideas into my current projects).

Having the framework be batteries-included is nice, but also nice would be
decomposing it into modules. For a good example of this, check out the Hapi.js
server ecosystem. Lots of different plugins, and if you want object validation
outside of the hapi.js world, you can just use Joi alone. It lets me mix-and-
match stuff. A concrete thing here is the ORM layer (which hapi.js doesn't
have). If I could pull your ORM out from the server stuff, I'd be a lot more
likely to take that part at least for a spin.

~~~
pfooti
Some other minor things:

promises are rad, and I know I can just use Bluebird's promisifyAll to wrap
your code. But still, it would be nice if I didn't have to muck around with
that and async methods called without a callback returned a promise by
default.

middleware is rad, it lets me abstract out pre-processing that happens on
(say) every POST route to validate parameters. It doesn't look really feasible
to do that with this system. I'd basically just have to bake all that into the
post() method, which isn't super-modular and is probably harder to write unit
tests for.

can't say that I'm wild about regex routes by default. I dig stuff like
'items/:itemId' with named parameters in a microsyntax. Makes life a lot
easier.

~~~
keithwhor
Nodal supports Middleware for _post-processing_ controller output (gzip, etc.)
and I could do something similar for pre-processing but right now it's just
encouraged that you write your own intermediate controller, get all
controllers to inherit from it and do something like a super call. Will think
about what pre-processing middleware would look like / be called.

~~~
pfooti
Yah, I had thought about inheritance and super, but without multiple
inheritance, it'd be tricky.

Basically a lot of my routes do stuff like parameter validation (I store
specific criteria on the model class, but apply them in the route), creating a
new object from validated post params, loading from the database, storing to
the database, authorizing and authenticating, etc. Then my route definition
declares the per route middleware and the specific controller only has to
encapsulate route specific business logic.

I could do that just by putting it all in a utils package and calling
loadItem(), validate params() etc at the top of each handler, but that feels
less elegant.

It may be that I've just been using hapi.js for too long, the modularity and
composition in that framewrok.is quite elegant, IMO.

------
xixixao
You'd save yourself one line of indentation if you encouraged module.exports =
Controller; at the end of the file instead. Node already puts a closure around
the module, no need for another one.

~~~
keithwhor
I like the IIFE because of the way it reads. A developer new to Node.js It's
impossible to miss. Putting your export line at the bottom is begging for
silly bugs. Even if they're quick fixes, still annoying.

~~~
curun1r
Seems like:

    
    
      export default class ...
    

would be the clearest and least bug-prone and satisfies the "no extra
closures" complaint. Considering you're buying into other ES6isms, why not use
that one too?

~~~
keithwhor
Will definitely be changing the module system to ES6 in the future. For now I
prefer this pattern. :)

------
janjongboom
That is one blatant ripoff of the Nordic semiconductor logo...
[http://www.nordicsemi.com/extension/nordic/design/bootnordic...](http://www.nordicsemi.com/extension/nordic/design/bootnordic/images/NordicS_smarter-
things.png)

~~~
keithwhor
Haha! Wow! A friend I've known since 5th grade made a bunch of different logo
variations and I chose that one. Swear neither of us have ever seen / heard of
this company. Hilarious (?). I liked it because it reminded me loosely of the
N64 logo.

~~~
icebraining
For what it's worth, I prefer your friend's version :)

------
amelius
Perhaps it is just me, but I much prefer functionality broken down in small
packages, rather than offered as a complete framework. The advantage is that
module boundaries are more clearly defined, and that parts can be more easily
understood, and, most importantly, they can be more easily replaced.

~~~
seivan
That only works if they are made by the same "team". Otherwise you end up with
the current mess that is the JS-ecosystem.

------
freshyill
If the developers are lurking, here's some feedback on the site: please fix
the light blue on light blue text.

Edit: I'm on my phone and I zoomed all the way in, and I see that it's
actually white text, which is still bad.

~~~
PuffinBlue
Yeah, I know not everyone puts much stock in accessibility but this is
actually really hard to read thanks to the contrast. Hopefully if the devs do
see this they can check their colours here:

[http://webaim.org/resources/contrastchecker/?fcolor=00E1FF&b...](http://webaim.org/resources/contrastchecker/?fcolor=00E1FF&bcolor=ffffff)

~~~
keithwhor
Thanks for this. I'm not a (visual) designer by nature so I often miss things
like this. I've made a small adjustment, but I'll make a bigger one as soon as
I can!

~~~
dbattaglia
I would check it on mobile when you update it. I usually do the majority of my
HN browsing on my phone, and I don't think I'm alone.

Good job btw, this looks very nice as an alternative to the micro-framework
world of Express.

------
fcanela
I honestly prefer developing the application from ground and having more
control. The framework may be handy for short time to market requirements.

Anyway, I found one or two interesting things reading the source code, so even
not being a Nodal user it delivered value to me.

~~~
keithwhor
Understand completely. I share the same feelings, which is why I built Nodal.
I was building my Node applications from the ground and building the same
things each time ;), felt I wanted a standard set of tools.

I'm really flattered you found things you thought were interesting! Would you
care to share?

------
antjanus
It seems like Node is steadily advancing toward being more enterprise-ready in
terms of its frameworks.

~~~
voidr
enterprise-ready would mean that it is well documented, stable and mature,
which it is not.

------
seivan
I'm slowly starting to genuinely understand DHH Omakase rant. The whole
"modularity" part of Node doesn't seem to work out so well. Constantly have to
look for third party support for simple but necessary things. Eg Strong
Params, json builders or a Mailer. I wish there was JS framework that offered
everything out of the box as a first party support or at least a decent API
libraries could use. Like ActiveModel is used by various NoSQL gems.

~~~
dev360
I think it depends on what you do. I spent first half of my career ordering a
la carte.. In hindsight, I ended up building a lot of crap that the framework
should have provided for me.

This is the major reason why I have learned to be cautious with getting wowed
by the apparent simplicity of micro frameworks.

At the very minimum, I want a framework to have an opinionated model layer
with migration support, and chances are you will get trickle down benefits
from frameworks that have opinionated M layer..

Look at djangos form abstraction for instance. Or the way validation is
handled in Django models, which in turn opens up for the possibility of
creating a neat REST abstraction. These are the types of abstractions that you
end up writing yourself or not writing at all when you go the 'light
framework' route, but they are almost always handy and will save you time.

------
foxpc
The docs do seem to be a little lacking - it's mostly technical stuff about
methods and might not be what the developer is looking for. Looking at
documentations from Laravel, SailsJS, even Django, it's easier to get the
point of what you're expected to do to get X done.

Other notes on the documentation:

* Very little info on how the templates (views) work. Can I use a different engine for them? No info about that.

* (just as an example of many) I've noticed that a scheduler is implemented and that it's mentioned in the site. It is also noted on github that there's no info on the scheduler _yet_. So, why would you include the features that no one will be able to use unless they're willing to get into the source code of Nodal itself?

I see that the project has been going for almost a year now and it looks like
it's going a great direction. Just needs a more user friendly documentation to
be fully usable, I'd say.

~~~
keithwhor
I still have _so much_ work to do to ensure there's great community support.
I've been too cautious to release software in the past and over-optimized for
the wrong things. My goal is to get this out in the wild so I can learn what
people are most interested in, and optimize from there. Everything will be
covered soon!

------
bshimmin
Nice to see Postgres as a/the first-class citizen here!

From a quick glance at the documentation, the "server types" seem very
sensible.

------
angersock
I won't speak for anyone else, but looking at the code samples, pretty much
everything I was worried about in terms of readability for ES6/silly uses of
'this' is present here. It just looks a bit arcane.

I appreciate the DSL-for-problem approach, but this is kinda exactly what some
of us were worried about.

------
seivan
The source is amazing for anyone wanting to learn how to write decent MVC
framework. Though I got some reservation about letting users write regex for
routes and middleware execution being so far late in the chain (at render).

------
johnhenry
While looking through the documentation for reasons to use this, I stumbled
upon some points regarding modularity in the "Why Nodal?" section of the
readme. I think that this should be emphasised.

~~~
joekrill
But not is inherently modular, in-and-of-itself. Wouldn't Nodal make it _less_
so? Because now I have this ORM built-in, the router built-in, the scheduler
built-in, etc. With a standard Node project, I can just pick my own ORM,
router, and scheduler, as I see fit.

It may be a great framework, but that strikes me as an odd point to make about
the project.

~~~
keithwhor
Systems modularity. Nodal is about building independent micro services which
each have their own internal consistency (the Nodal environment) but are not
tied to each other. Nodal just encourages you to optimize for systems first to
build a product / business and spend less time worrying about granular
technical decisions.

------
gisenberg
FWIW, I checked out at the "go install PostGres" pre-requisite. I'd prefer
either being less opinionated about pgsql or making the dependency transparent
via something like Docker.

~~~
mikewhy
I've not read all the documentation yet, but I'm assuming you can tell Nodal
to use any arbitrary IP:PORT for the database, which would allow for Docker.

------
p0larboy
Doesn't seem to have transaction support for the ORM

~~~
keithwhor
Not yet. Migrations are done transactionally, and it's something I really want
to have, but there are complexities I have yet to tackle.

------
chrishn
This looks awesome. The ORM itself may be the thing that makes me switch to
Node.

Are soft deletes planned in the future? I saw that cascading is on the
roadmap.

------
hitgeek
it would be great if it was called, node on nails

------
vvpan
What does "next-generation" mean?

------
xjlin0
This is awesome, how about mysql users?

------
akoumjian
This looks fantastic, I can't wait to try this.

------
GeorgeMatthews
FMIW has to say superb work to look-after form now

------
tomjen3
The framework might be good, but you need to ditch that video and replace it
with some example code. I need to know why it is better than Express or other
Node frameworks and what it is like to work with - also you claimed it was
next generation. How do you justify that claim?

It could the best framework ever, but without an example all that stuff is
useless. The video could help, but it is a) way too long and b) appears to be
pretty slow in showing the meat.

------
rms_returns
Fix problems with node and develop the library ecosystem first.

~~~
dev360
> Fix problems with node

Do you care to elaborate further?

~~~
rms_returns
Problem is that node is buggy as hell. Try and do something more trivial than
basic I/O and you are going to face lots of them. Its almost a decade since
node hype has begun and still you will hardly find any large, well-known
website being powered by node is the testament to this fact.

Also, if you read the docs of any major API implementation, you will find
examples in python, php, java, etc. but I'm yet to come across a node example.
Node ain't ready for the real world yet.

~~~
connor4312
It sounds like you haven't used Node or read API docs in several years.
Developing for Node full-time for the past few years, I've yet to find any
bugs in the standard library or runtime. And, just glancing around at a few
"major API docs" that come to mind, all that included code examples (PayPal,
Stripe, IBM Bluemix, MaxMind) included Node.js examples.

