4 ms·
IMHO articles like this played a major role in Node's initial success. After years of working with ever-growing frameworks with huge learning curves, it was so
by jpalomaki 8y ago
IMHO articles like this played a major role in Node's initial success. After years of working with ever-growing frameworks with huge learning curves, it was so refreshing to get your first thing running in few seconds. Felt like basic in the 1980s or PHP in the late 1990s.
- hardwaresofton 8y agoIIRC before nodejs+express the req/resp/next paradigm and middleware paradigm had never been so accessible. Other frameworks had it of course, but it was often hidden behind layers of abstraction or little quibbly bits. Express gave you just what you needed for both middleware and handlers: app.get('/', function(req, res, next) { res.send('hello world'); }) For comparison, flask: @app.route("/", method='GET') def hello(): return "Hello World!" It's really close, but I find the NodeJS approach even simpler and easier to understand. Need to access the request? use `req`. Need to access the response to set headers or something? use `res`. Is your function actually a middleware? use `next`. It doesn't get much simpler, assuming you understand node's semantics well (as in "return"ing a value doesn't mean it gets sent). Django/Rails required whole project scaffolds and usually a separate routes and handlers files and knowing a whole bunch of stuff. I'm not even going to get into what frameworks like Spring/Struts required. NodeJS made it dead simple to get a HTTP server up and running in something like <10 lines of code. People shit on JS and NodeJS every chance they get, but innovations like the amazing standard library (and express), along with npm's ease of use really pushed the field forward IMO. While I'm praising node I might as well say that node got decent bolt-on (gradual) type system support way faster than the other popular dynamic languages as well, but they got there through transpiling which also looked (is?) ridiculous the first time it became well-known. I find Typescript much more approachable than typed python[0]. Is typed ruby even a thing[1]? I don't keep up with ruby so I'm not sure. [0]: https://docs.python.org/3/library/typing.html https://docs.python.org/3/library/typing.html [1]: https://bugs.ruby-lang.org/issues/9999 https://bugs.ruby-lang.org/issues/9999
- oweiler 8y agoI agree for the most part, except comparing node/express to Rails: node's equivalent in the Ruby world would the Sinatra, which is about as succinct than node.
- hardwaresofton 8y agoYou're right -- I didn't mean to compare them in terms of size/functionality but rather just as other options that were out there and why people might have picked node in the presence of other good alternatives.
- InGodsName 8y agoPeople love Rails/Django because of active records ORM. No idea if JavaScript has similar ORM
- Kagerjay 8y agoIts not as opinionated as rails/django but there's typeORM among others
- eropple 8y agoTypeORM exists, but I hope you really, really like having it own your schema. Its support for migrations, rather than "uh, just let us do our thing!", is sneaky-not-great. There's no documentation, for example, for how anything in a TreeRepository actually is structured in the database, and the recommendation is "let us run the DDLs on a scratch database, you can puzzle it out from there", which should make your blood run cold. I think a lot of the decisions in TypeORM are good, but I wouldn't trust it to own my schema under any circumstances (because now even if I'm doing things sanely I have to ask if a version bump is going to break compatibility in a way that would be "magically" fixed if I just let it chew on my schema directly). The least-bad NodeJS ORM I have found is Objection.js, but that's a lukewarm recommendation. Its TypeScript support--which, IMO, is critical--is acceptable, but the library itself is a little cumbersome.
- hardwaresofton 8y agoI've actually had great success with TypeORM now on various personal and client projects... Maybe I haven't used all the features you have used (like I've never touched TreeRepository...), but I've never had a problem with the migrations because I just write my own, and I write my own models, etc. TypeORM has had the best combination of fullblown ORM and just-build-my-query-intelligently that I've seen to date. TypeORMs migrations are pretty simple, just write your own migrations? I only use TypeORM to generate the migrations (i.e. `typeorm migration:create -n <name>`, then open the generated file and write `await queryRunner.query(`....`);` and craft the migration myself, and make sure the changes are reflected as need by in the related models. TypeORM is actually a better ORM than a lot of the options out there. I remember using C#'s EntityFramework (this was during the move from .NET 4.x to core/standard) and I kept wishing I was using TypeORM over it -- the annotations in EF were half-baked (to be fair they were still porting functionality), and it was just shitty all around. Then again, C# is my weakness so maybe I just didn't have enough skill.
- devxpy 8y ago> innovations like the amazing standard library Excuse me?
- zbentley 8y agoI would agree that the node standard library is quite good compared to many other scripting languages’. It’s nothing on the gold standard (python), but light years better than what is included with stock browser-side JS.
- kochthesecond 8y agoSinatra and express brought something very important and retaught me something: value simplicity. I can't imagine how a lot of projects would look like without their influence.
- devxpy 8y ago>Need to access the request? use `req` Well, I don't see what's especially difficult about this? from flask import request @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': return do_the_login() else: return show_the_login_form() I would actually argue that this is better, since I have to type "request" only once. Although I have to admitt, the middleware thing looks quite composable.
- Y7ZCQtNo39 8y agoI'm not a huge fan of decorators since they obfuscate the state of the runtime. What exactly does the call stack look like when login gets invoked? What variables are in scope? I find it difficult to reason about. I understand that this function will execute when the HTTP server receives a GET or POST request at `/login`. The semantics of the decorator is clear-- I don't particularly take issue with that. But the second my assumptions about the decorator break down (e.g., I think I've defined a decorator properly, but I have not), all bets are off on how to make it function properly. It's not as simple as going to the source code for the module and see what API's I'm calling.
- devxpy 8y agoWell, You'll be happy to know that a decorator is literally just a function that takes another function as its first argument. @app.route(...) def login(): ... Is literally the same thing as - def login(): ... login = app.route(login, ...) Hopefully that clears up the air a bit?
- Y7ZCQtNo39 8y agoIt clears it up but personally, I'd rather just write `app.route(login, ...)`. Isn't a lot clearer to use more conventional language features? What exactly is this buying me? I don't know if me saying 'Just, why?' is a good enough reason to throw my arms up and say it's an idea I'm not a fan of. I'm willing to say that it's a rather subjective attitude. I guess my retort is that, it's far more confusing to have that syntax, then explain what it meant, when I could've just used the conventional syntax. It's not like it's offering me something substantially simpler. For example, the spread operator that was introduced. It actually allows you to write clearer JavaScript code. This syntax isn't intuitively clear like the rest operator is.