Skip to content

Instantly share code, notes, and snippets.

@mikekellyio
Last active August 29, 2015 14:21
Show Gist options
  • Save mikekellyio/674671f80a0cf942d36d to your computer and use it in GitHub Desktop.
Save mikekellyio/674671f80a0cf942d36d to your computer and use it in GitHub Desktop.
availity-day1-morning
it can do some things that you can't do with normal html. But just remember -- if Amazon can do without JavaScript, so can you. So this was from a post titled JavaScript is evil. A lot of designers think it's their god-given right to annoy the hell out of visitors with bulky JavaScript effects, so turning off JavaScript is almost a requirement when visiting some websites. It was true at the time. This is from stupid JavaScript security tricks. A little bit older, but still relevant. Blindly accepting a high level of security risk on the web by enabling JavaScript is as shaky as a ride on the Canadian space shuttle made of birch bark and gum. I'm Canadian, so this really resonated with me. Woo, represent. So this is what people were saying. JavaScript was not a thing. But despite the fact that it took years for Gmail to... Whoops. Uh-oh. My computer died. I'm going to have to plug in. Okay. I don't need internet. But... Sorry about that. So... Computers fail sometimes. Not only is the mobile web broken. Batteries are broken too. Yeah. Oh, thanks. You're the best. See? Community. This is what makes JavaScript better. All right. Let's boot up. Sorry. It was the Gmail curse, honestly.
(Never Going to Give You Up playing)
>> Oh, gosh. All right, we're booting, we're booting. I'm really sorry. Phones were super different?
>> Phones were super different in the '80s than they are today.
>> Yeah, they were.
>> In the '80s, I had Jenny's number, and now I have 8675309 apps on my phone.
>> It's true. It was really different back in the 2000s too -- people assumed email could only be done native. But we're about to find out why... Yeah, it's just going to take a minute. Okay. Should have plugged in. Yeah, it's true. Oh, we're good, we're good, we're good. Sorry, sorry. All right. We're back.
>> Let's hear it for the hibernate feature on computers, everybody. As opposed to rebooting from scratch.
(Never Going to Give You Up playing)
>> We're back. No, we're not back. Now... Which one was the right one? Probably this one. Let's find out. Yes! Okay! So... We're back. We're back in the immersive interactive web. Awesome. Still in 2004. So despite all of this weird stuff, and the fact that JavaScript was terrible, and it was a total hack, Gmail was a total hack, it was living proof that you could write something in JavaScript that people actually loved. And that's awesome. And, you know, it wasn't long after this that developers started getting excited about the XML-HTTP thing and using it all over the place, and before we knew it, great rich client experiences became something that was essential to the web, as the promise of interoperability itself. Fast-forward to 2006, and all of a sudden XML-HTTP thing has now been standardized by the W3C, and JavaScript is moving towards the process of standardization and universal acceptance. Hurray! Clap for JavaScript! So the point is this: you're not here at this conference about to learn about knitting and making music and driving robots because someone intended or designed to make JavaScript or the web to do these things. You're not here because of the standards body. You're not even here because of a browser. Well, you're kind of here because of a browser. But not entirely because of a browser. You're here because someone wanted to do something cool and found a super hacky but somewhat compelling way to make it happen. So my proposal to fix the mobile web is this: stop relying on browsers to reimplement the DOM or land device APIs or do whatever it is you want. Stop thinking about what the web is or what the web was. Maybe this is totally naive, but I don't think that rich app-like experiences are something we're going to be able to pass over, no matter how compelling and awesome the URL is. And if you want to talk to me about URLs, I will talk you to about URLs. If you want to be here, talking about JavaScript, in five years, it's time to hack. So in order to demonstrate some of the ways you might do this today, I would like to use a model I've devised called the three levels of hack. Where we start in a place that most people would kind of agree is not that weird, and then end up with something that's really weird. So start small. First level of hack. Test new features before their time. That's a great way to push the platform a little bit. To use new browser language features, right? That haven't made it into production. So one way to do that is to turn on stuff that's there and use it. Easy, right? One thing I'm personally really excited about is the service worker -- which is going to help out with offline in a huge way. And I'm not going to talk about it in detail, but if you've ever used appcache or are thinking about taking your app online, you should definitely check it out. There's already an implementation. Chrome, you can check it out today, and I think the Firefox implementation is coming out in the summer sometime. So that's super cool. You can also polyfill the features that you want to make them work for features today. One of the things we do on my team is transpol ES6 using babble. And Sebastian is speaking about that later this afternoon. So I highly recommend you attend that session. And doing this kind of stuff is not controversial. But I'm mentioning it because if you're not doing it, you should. And the other thing you should do is -- if you find bugs, or you have opinions about how things should be changed, you know, the implementation teams that are building them really want to hear from you. The Gecko team, for example, working really hard on service workers right now, is really interested on getting feedback on the service worker and how you want to use it. So if you're interested in joining that conversation, just talk to me after and I can hook you up with the right people. Okay. So let's do the second level of hack.
Building new abstractions. So beyond things that are being implemented -- cool stuff really comes out of people thinking in completely different ways with the tools that are there. So, you know, one area we're seeing a lot of innovation -- I'm sure all of you are aware, probably using this stuff -- is DOM abstractions, like reacts, virtual DOM, famous engines DOM and web GL abstraction, flip board did a cool thing with react and canvas. For the most part, they don't replace the DOM. They augment and reoptimize particular areas of it by building an abstraction, and that's pretty cool. It's a total hack. Let's be honest. But it's awesome. Another thing you can do with abstractions is build things that already exist, but don't yet exist -- have a counterpart on the web. So going back to the offline use case, a pretty cool example I've seen in the last few months is some colleagues of mine have been working on something called Filer, which is basically a posix compliant file system interface in the browser. It doesn't actually use a file system. It just abstracts one on top of index DB or web SQL or even in memory. So that means that any modern browser who has access to those things can actually do file operations and store them offline, which is amazing. There's a group of super smart people working on a code editor that takes advantage of Filer at Seneca College in Toronto, so you should check that out if you're interested in Filer. It's super cool.
So... Okay. We talked about some fairly... You know, things that are exciting. But not exactly controversial. Because we're still building on top of existing APIs, and mostly doing things in a web-like way. But what if we could go actually further than that? You know, if the browser is the thing that holds you back, why not just hack on that? Cool, right? And in this case, I'm not talking about, like, submitting a patch to Firefox for Android, although if you would like to do that, there's a link. You know, totally awesome. You totally can and should. What I'm talking about is basically hacking together your own user agent inside of a native environment. And this is also known as hybrid app development. Right? And maybe you haven't heard hybrid app development described quite like that. Hacking together your own user agent. That's essentially what it is. And there's some frameworks out there that can take care of the dirtiest part of that hack. If you want to try them out, I would highly recommend Cordova, which is a really brilliant project that feels the closest to actually still developing with the web, but getting APIs from the native device. But I do actually think it's valuable to do yourself. You know, are you going to implement a better browser for all mobile users? You know, are you smarter than the people who work on Firefox and Chrome, and Windows? Absolutely not. You're not. I'm sorry. Maybe you are. I don't know. Come work for us if you are. But you're probably not. But... You know, personally, for what I'm working on... No, seriously. Come talk to me. For what I'm working on, I found that building a custom hybrid architecture, while it's not the solution for all of the web's problems, it allowed me to experiment with solving the exact problems that we were having with the mobile web, and understanding that connection much better than I would, you know, using something like Cordova, or just building within the browser. So to put this into perspective, I'm going to talk a little bit about what my team at Mozilla is working on. We're interested in what web authoring tools might look like, primarily for new users of the web in Bangladesh, Brazil, India, and Kenya, using only a mobile phone. So that's, like, what our problem is.
And the first iteration we experimented with was a client side single page app. We didn't target iOS, because it's not a huge part of our market. But we had specific issues that were major blockers. Obviously we needed to make something work really, really well offline, and in 3G or less. That was a huge requirement for us. We tried using appcache, but it wasn't doing what we needed it to do. We were seeing a lot of issues with memory leaks popping up in client side memory architectures, particularly when building or destroying new views. Especially when people are idling the apps on their phone for three or four hours. That was a huge issue for us. Another big issue was UI perf. It's an editing interface when you touch. And 50% of our user were still using Android phones before 4.4. Anybody develop for the stock Android browser? Nobody? Oh my goodness. You think IE is bad. You should try developing for the Android soft browser. It does not autoupdate. It's pretty horrible. So these were problems.
Let's figure out how we fix some of these things in a custom Android environment. So... Actually, any Android developers here? No? Oh, we've got one. This is good. This is good. All right. This is going to be interesting to you. So I was going to skip past this part. If you guys all do Android. But... All right. So the basic architecture -- how do we build this custom hybrid app? And by the way, this is really similar to how Cordova works or any other hybrid architecture. I want you to understand how you do it yourself. So the first thing we do is we start with an Android activity, which is like a basic view in Android. And that may or may not contain some UI, like a back button or a header. Or it might just be like a frame to hold the web view. All right? So how do we do that? We write some Java. We create an activity. We create the layout in XML. Then we add it to the manifest, where we can specify things like the name and the parent view, the view hierarchy, stuff like that. It's kind of weird, but not so weird. Inside that, we instantiate a web runtime. That can be Chromium or even Gecko. There's a project to do that, but it's not ready yet. That's super cool. And Android makes it easy to do. In 4.4 plus or web kit -- you just implement the class instantiate. Super easies, right? Like us, you probably want to support the most modern version of browsers. Instead of using the built in webkit, you can use this, which is crosswalk. Lets you embed the latest version of Android as far back as 4.0. And it exposes the same JavaScript Java bindings -- it's great. Crosswalk project.org. So the last thing we're going to need in this architecture is a communication layer that binds our JavaScript and our Android code together. Some of that is provided by the web view class or the crosswalk class, so you can load external URLs, you can load packaged assets inside your app. And if you're wondering -- yes, even if you're using the file protocol, you can do XHR, because this is your own user agent, and you can do what you want.
All right. But the real magic that happens, though, is you can expose a custom Java interface into your JavaScript by attaching it to the window object, and that kind of lets you do whatever you want. So what does that look like? We've got -- we add JavaScript interface to our web view, we basically attach a class to it, and we can add some methods on that class. And those methods that are declared actually show up on window.Android, or whatever -- we can call it whatever we want. I called it Android. We can just call those Java functions. Of course, you're fairly limited in what kind of data structures you can pass through. You're going to want to use primitives like strings and stuff. You can't pass full objects or functions around. Sorry. But... It's still pretty powerful.
And that's basically it. So... Yeah. That's how it works. If you remember from our example, one of the major issues we had was that the client side routing caused a lot of unexpected memory leaks. Long lived processes were kind of not so great in our client side app. So what we did -- and this is something you couldn't do in Cordova, but we could, because we were hacking something together -- in order to fix the issue we had, we actually moved the routing into Android, so we could take advantage of the more sophisticated memory management and life cycle events, and we instantiated each page of the app as an isolated view with its own activity. That's really similar to server side routing, and it actually has the same benefits, like encapsulation of each page, but in Android, we also get the added benefit of super smooth transitions, layout hierarchies, we can get the back button to do what we want, so we get the best of both worlds. Pretty cool. What did we do about shared state? This is where the JS Java bindings come in. Because we're using React to render the web UI, it's pretty trivial to send parameters into React and take the state out of React and cache in Android. So what does passing rooted params look like? You stringify the router params, get an initial state function, and all of a sudden you have all the information from your router. That's pretty simple. And to cache state, we create a JavaScript interface called setstate, that allows us to pass in a stringified JSON object, so it can be cached in the shared preferences in Android. And our React code, we just need to hook into it. So every time our component updates, we set the state in Android, so it's cached, and when the component mounts, we just pull it down and then restore the state. So super simple. But it solves a problem -- we can restore things in an offline context, we can get around using that Android-based routing, without having to sacrifice our User Experience. So what about device integration? This is something actually if you're going to do it, you should look at the Cordova code base. There's a lot of things that looked at device integration. Here we write some of the typical code you would write in an Android app for dispatching the camera intent, looking at whether you want a camera or gallery, we create a URI out of our image, or we could do something like upload it at that point in time. And then we actually post it in this super awesome hacky JavaScript window thing.
We actually post it to a method in JavaScript, we post the URI, and then all of a sudden we can use it in our JavaScript. So it seems totally terrible, but hey -- you get an understanding of how Android is receiving the camera intent. You get an understanding of what you can do in terms of compression. You get to be a lot closer to your device than you ever would be using some web API or just saying... Well, we can't support camera. So what else? There's lots of things you can do. You can bind to Android's offline network caching utilities. You know, if you want to do that -- before service workers are available. You can hook into some native gestures, so you could actually read gestures on the Android side and post them into JavaScript. If you want to do things like pinch zooms or swipes that are much better architected in the Android platform. And of course, you can do lots of device integration, like push notifications or whatever you want. And really, it's up to you. Because it's your browser. Well, it's your user agent.
So... The truth is I'm not really sure any of this is going to be actually successful. Or even that it's reasonable or possible to make fundamental changes to the mobile web in this way that works. But what I am certain of is if you don't try bold, native things -- naive things, and develop a better understanding of the platform you're building for, you know, if all you're doing is pushing up against the edges of the browser, things are not going to change. No one is going to fix the web but you, and your understanding of your real problems. So I want to end with something inspired by my dad. This is my dad. Because one, he was pretty much the coolest engineer I've ever met in my life. And two, because Friday would have been his 71st birthday. So happy birthday, dad. Thanks. So my dad was totally self-taught. He was an amateur radio hacker, and he also designed some really, really cool radical electronics equipment back in the '60s, '70s, and '80s. He worked with a lot of people who had engineering degrees, and one of the things he said all the time was -- for all their education and understanding of theory, a lot of people just didn't really get what good engineering was. Good engineering. Because to my dad, really good engineering was finding adequate solutions to problems that really matter to people. In a way that someone in the future, who's smarter and better than you can understand and improve on. And as long as you're okay with the fact that the web is always going to be this patchwork, open, weird, somewhat hacky, totally imperfect thing, as long as you're willing to think about it and build for the real world around you, and not for what the platform tells you to do, you're probably going to make something great. You know, for the 500 things that suck and are terrible, you're going to make something great. And if the talks we have lined up... You know, in the next few days, are any indication of what people think about that, I think we're going to be fine. So hack the good hack, my friends. Thank you very much.
(applause).
(Weird Science playing)
(Hi-Fidelity playing)
(I Only Want to Be With You playing)
(One Step Further playing)
>> All right, everyone! Take your seats, because we're going to start the next talk! I have here Tim Griesser, who comes to us from Philadelphia, and he's going to be speaking to us about making relational cool again. Parentheses... Or JavaScript on ACID. Everyone give it up for Tim Griesser!
>> Thanks. So yeah, I'm really excited to be here, talking about making relational cool again, and the subtitle is... Or JavaScript on ACID. And like I said, my name is Tim Griesser, Tgriesser on Github, and I'm here really excited to be talking about SQL. Or is it Ess-que-ell? I know it's an issue that really divides programmers. So I Googled it, and the first result I came across was this English language and use in Stack Exchange. Which I thought was fitting, given that we're at a programming conference. And the first thing you'll notice is I'm not a member of the English language and usage, so if I make any mistakes up here, you'll know why. But the answer was that it was in fact first called the structured English query language, and so that acronym was SEQUEL. And then that was abbreviated as SQL. Now it's a matter of preference. And there's an urban legend that it came after the structured query language, which is the worst urban legend I ever heard. So I learned something new, and now I'm a member. It was a big day. But it's appropriate that we're talking about relational databases at a JavaScript conference, because I think there's a lot of similar features between the two. At a language level, maybe not so much. Relational, SQL is static and strongly typed, declarative, and in some ways procedural, and JavaScript is as loosely typed as you can get while still being a programming language, and it's object oriented, which leads to some interesting debates as to how to write the code correctly, and it shares some of the same operators, but we know in JavaScript the operators don't do what we want some of the time. So what do I mean when I say is theres a lot of similarities between SQL and JavaScript? They both sort of share this similar quality that is not often attained by all languages, which is what I like to term -- languages that will probably never die. As much as people try to kill off JavaScript with different other languages that will supersede it, it sort has this monopoly. It's the language of the web. It's the language that runs in web browsers. And similarly, SQL has so much momentum. It's been around since the '70s and it's been around forever. This is a slide that we often show when we're talking about JavaScript, just sort of illustrating that it runs everywhere. In the browsers, but also your television and your server and your nodebots and copters and also on your phones, and I think the same could be sort of said about SQL. Is that it powers the largest websites in the world. It's behind Facebook and Wikipedia, and also down to SQL-lite, flat file storage, which is in more places than you would imagine on your phones. So coming to node.js a couple years ago, I was sort of surprised. It seems like these two would be such a great fit. They're both everywhere. Why is there not more support for it? And I think the reason is that node starts with no, and no is the beginning of NOSQL, and around the time that node came out, it was like -- let's rethink the entire way that we're writing server side applications with this evented IO model. And at the time, it was sort of like -- let's rethink the standard relational database, because we're hitting web scale and we need to get past that.
And so around the time that sort of the height of the NOSQL phase or moment -- it's still going, of course -- is when node came out, and that's why there was so much of this. So all the tutorials I felt like for node were node and Mongo, getting started -- they have literally taken the software and web industries by storm. You've got Mongo express angular node, which everybody has heard of, and then my favorite, the Lebron stack, level DB slam dunk. And what happened to relational algebra? Right? This is proven and time tested. And SQL works great for a lot of things. And this stack overflow post that I came across sort of summed up what I was thinking, coming to node from outside.
Are relational databases a poor fit? And this is sort of long, so let me just pick out a few things. There's a degree of antipathy toward relational databases, is an observation you could make of the node community. And that they're poorly supported, compared to non-relational databases. I sort of agree with this. Listening to the node up podcasts, listening to couch DB and Mongo, I guess it was like -- relational databases aren't cool anymore. I dug a little and found there actually are really great libraries for working with SQL in node. All the popular Open Source, and Oricle came out with another one. But there's not a common API all of them. Node didn't assume that a relational database was a given. In all other language systems, there's a standard for how you're interacting with common patterns of a database. How you connect, how you disconnect. That doesn't exist. So what that lends to is that all the different clients have a different way of dealing with these things that should be pretty common. And there's also, I guess -- the next thing I noticed was that the higher level abstractions were lacking a little bit.
And what I mean by that is that a lot of them were database-specific. So there was a great query builder, but it works for postgres, specifically. Another great one for another language, and no way to use the same for both. Different APIs. Or there's a mix of an ORM layer and a query layer, so there's no ability to drop down and use just vanilla SQL if you need to. One that was big for me is the lack of transaction APIs. So there wasn't any mention of transactions. In any of the higher level libraries that I had seen at the time. And that is sort of what the second subtitle of the talk is that I'll get to in a little bit. And then there was the jack of all trades, where it's sort of like -- hey, you can use the same save API to save to Reddis or Mongo or relational database or the file system. It's like... If you have the same API for all these different specialized data stores, you're really not taking advantage of the best use cases for each of them. Or there's sort of what I call the DIY. Like, it gets you most of the way, but modularity. So you have to assemble all these. The pooling, the construction, the abstracting the database API. So the ecosystem -- I would definitely agree with the Stack Overflow post, that there's a need there, that needs to be filled.
But I really wanted this to happen. I really love writing JavaScript. So I was like... Maybe we can do something better. And at the time, I had been writing a lot of PHP. This was back in 2012, in a framework called Larva, which some might have heard of. And it makes writing PHP pretty tolerable. And I was also using a lot of backbones. So I was thinking... Maybe I can take some of the ideas from both of these, and I sort of translated the query builder from Larvel into this project called connect.js. And this sort of illustrates what pieces were taken from each, but the eloquent ORM from Larvel and some of the ideas from backbone into bookshelf, and mix into promises -- and so I'm going to talk about these two libraries that I have put together, connects and bookshelf. The first is connects. If you're not familiar with where the name comes from, it's this toy that was popular in the '90s. It's sort of like a cheaper version of legos. You can assemble all these pieces together and build pretty cool-looking things. And actually, it's really great if you're procrastinating, making conference slides. I decided to make this little motorcycle here. All right, JSConf. But the reason that I think... What Kinex tries to do is standardize some of the inconsistencies in SQL. So SQL is a language -- an ANSI language specification. But it's not like it is, what we're used to with, like, ES5 or ES6 and beyond. Where we sort of have this compatibility table, and we see that Babel is in ahead of everything else, in terms of implementing all the different features. But it feels more like the can I use. Sort of like a language guideline. There are features that exist in some dialects but not others. It doesn't fail, or it fails sometimes, or -- different inconsistencies that K'nex tries to paper over. This is an illustration of the different pieces as they're coming over internally. Have things like connection pooling, to make sure you're getting connections that you don't have to continually reconnect to the database every time you reissue a query, mixes in different grammars from the different dialects, and creates a client that's used in the schema and normal query building, as well as transactions. Which I sort of break out entirely, because I'm going to spend a little bit of time on those, and on top of that, we have higher level APIs for doing some familiar migrations and seeding as you would see for something like Rails.
So how you get started with Knex is just give it a connection string. If you want to configure the pool, you can do that. And it works against a number of different databases. Including Oracle, which is pretty cool. Somebody just opened a pull request. And it's like -- oh, I don't use Oracle, but it's awesome that you opened a pull request. Yay, Open Source. And it also supports web SQL, but I don't really recommend that, because that's deprecated. Browsers killed that off. So you can select all from accounts, where activated is one, and then you call then on it, and it has the familiar promise chaining API, so it issues that query and returns the result of the query and then you can catch the error if that happens in the standard promise -- it's actually great that I don't have to argue too much in favor of promise, now that they're actually in the spec. But when I was starting out, that was a thing, whether it was -- it was still up for debate whether you should use that.
Also it does joins. I don't have to read it out too much, but joins with multiple clauses, and then subqueries, so anywhere -- so here we have a where in clause, and anywhere you might want to use a subquery, the general rule of thumb is that you can pass a function and then use the context of that closure as a new subquery. And then from there, I'm not going to dive into all the features, because that's what documentation is for. But you can do raw queries, like if you have a specialized query that you don't want to... That maybe does some things that aren't supported by Knex, you can issue those, aggregates, subquery aliasing, and it tries hard not to let you screw up. It tries to catch different errors or paper over things for you, so you don't make too many mistakes. And so the subtitle of the talk, as I mentioned, is JavaScript on ACID. So this is not the ACID test, which... Some are probably familiar with.
I've mentioned this to someone, and they're like -- oh, you mean the browser suite? No. Let me look that up, though. It's good to know that Chrome is passing the ACID 3 test, as of today. But I mean atomicity, consistency, isolation, and durability. I'm not going to go into each of them, because that could be a separate talk about each of the individual terms. But transactions -- I sort of sum up that. What they do is give you the ability to have a snapshot state of the world as you're working with your database. So what it allows you to do is roll back to a certain point in time, and also prevent other connections that might be working against your databases, from altering rows as you're working within a single atomic unit of state. And this is kind of difficult to do in node. You have to think about this API in advance, because in order for this to work, you have to have the same database connection passed to every single query that you're working against. So it's not like in synchronous languages, where you could just sort of say -- okay, start transaction here, and then all of these will run right here, and then end it right here. Because you sort of... With the event I/O model, you sort of lose that context as you go with the callback. You don't really know what's happening. So the connection explicitly has to be passed to every query. So let's think about a situation where we would actually want to use transactions.
So here's a simple user flow situation, where someone is registering for a website. And they register, and you give them an ID and you have to send that to a third party service and then you have to create maybe some other rows for that user, and then it's all done. They're all registered. So let's think about what could go wrong in these four steps. So first you might depend on a module which doesn't follow semantic versioning. So something breaks, and it's completely out of your control, or the third party API that you're working against sort of shuts down, and your data gets into a bad state. So in order to deal with that, then, after step 2, if that fails, then you would have to undo what happened in step 1. Or in step 3, where you're creating additional rows to deal with that new user, maybe one or a few of them failed, so then you have to make sure the ones that did go through get rolled back, and then you have to unregister the user, and then say -- hey, something messed up. And that ends up pushing a lot of logic into your application code that you have to deal with. All of these potential bad states.
Or you just don't deal with it, and then you have potentially bad data in your application. Because you want this whole register user flow to happen as one atomic event. Or here's another situation that can't be handled by the last one. Your servers just catch on fire halfway through registering the user. And actually... I created these libraries so I would one day have the ability to use this graphic in a keynote. No. But... So what Knex tries to do is you can say knex transaction, and then it creates an instance that you treat as a normal query builder instance, but it knows what it's supposed to be on and the fact that it's inside an transaction. So you can pass that to other functions that can utilize it and work with it as if it's a normal API, but behind the scenes, you have a transaction that you're dealing with. And originally, the API was that you would just have to pass this explicitly to every single query that you built. So you had the transaction object, and then you could call commit or rollback at the very end. But that seemed to be kind of error-prone, that users would sort of forget to pass it to every single query necessary, and then they would have sort of queries not working on the same connection, and it caused all sorts of errors. So this is the new API. And like I said, knex tries to make it hard to screw up, I guess. And so this is a little boilerplate here -- every time we call commit and roll back, this is a promise, and then we return the promise into the transaction, and we know if the entire promise chain fulfills, the transaction should be committed, and if it fails, the transaction should be rolled back. So that's pretty simple. Nesting transactions is new. And it's the idea that you shouldn't have to worry about whether the client is already inside a transaction. So if you call knex transaction on something that is already a transaction knex, it should just create a save point. And so a save point is sort of like a save point in, like, a video game. Where you get to a certain point, and if something fails beyond that, you don't go back to the very beginning, but you go back to just right here.
And so it does this transparently. You know, for you. And you don't have to worry about it too much. So knex likes to take what I call the batteries included approach, where it does a lot of this for you, and also provides a lot of different interfaces, like callbacks and streams and events, and two string -- the different things you would want to work with in a nice manner. So that's pretty much just a high level overview of knex. And now I'm going to jump into bookshelf. Which is an ORM, which stands for object relational mapper. And in short what that tries to do is take care of standard SQL queries for you, especially in common app operations. So when you're building an app, there's a lot of things that are pretty standard. Like insert, return, fetch, save, dealing with -- relating different rows of data. And you don't want to have to write all of this by hand. So it sort of abstracts that a little bit for you, and takes a little bit of the flexibility away, but gives you a nicer, higher level piece to work with. So the different association types -- pretty familiar if you've ever worked with an ORM in another language. One to one, one to many, many to many. Polymorphic -- I don't know if these are necessarily a great idea, but sometimes they can be useful, I guess. So it supports those. And it builds on top of knex. So that's where I was talking about having a separation between a query building layer and an ORM layer. You should be able to write raw SQL when you want and have something that works on top of that and also allows you to drop back into it when you need. So this is sort of what it looks like, to create a few models with associations. And you can also sort of filter with... So here we have comments, which is has many to a comment, but we also have moderated comments, and we can add in the wheremoderated is true. And it also supports loading where you're trying to add data to a collection of data, if you have 26 items, you have 26 extra queries, so it tries to do one and then another query for the extra related results. An example here is to find an account with all the posts in the account, and then all the comments under those posts and all the accounts that actually made the comments on the posts for the account. So that's what that it would look like, to provide withrelated, and this is all in the documentation. So I'm going to jump through this a little bit.
Also, as you constrain your loads, you can dynamically constrain relations, and then load things after the fact. So if you want to fetch one row or a collection of rows and then only load onto one, it allows you to do that as well. And then as I was mentioning earlier, it allows you to tap into the query chain, to dynamically add things that are maybe a little more SQL-specific under the hood, as you're building the select statement or other statements for the model. And so transactions in bookshelf aren't quite where they are in knex, where you still have to pass the explicit object to each of the async calls. Turns out it's a little harder to retrofit that, where you have a transactional bookshelf object. That's where it's going in the future. But transactions are absolutely supported in bookshelf. And just a little bit of where bookshelf sort of came from -- I mentioned that it came from some of the ideas from backbone models and collections. And ultimately the idea was to see if we could reuse some of the same models on the server and client. And this was back in, like, 2012, back before I even knew there was a term for doing this. Which I'm not going to say. Because he already covered it last year.
And I actually sort of got there. I was able to swap out bookshelf models and collections for, like, the backbone todo MVC and use it targeting webSQL. Which was kind of cool. I don't know. I built a to-do list. And that's pretty special. But really, I think, shared models sound great, but it's not really as great in practice, because you have to know a lot more -- or there's sort of a limit to what you can do. You have to load all the data, and lose out on a lot. Because you don't need as much of what you would need on the server on the client, if you're just displaying it. So it sounds great. Not as great in practice. And it's something that I'm sort of moving away from, some of the model and collection conventions from backbone, based on some of the things that I've learned, having been out there for a little while. So you can read more in the docs. I'm not going to go too much further into it. But I think one thing I would like to point out is that knex and bookshelf are not the first to do this. So I mentioned earlier there was already higher level SQL abstractions in JavaScript that I saw, and I was like -- oh, I'll build these instead.
And hopefully it's not the last to do this. So a few other projects -- openrecord is a really great project that's using knex under the hood, and it provides more of an active record syntax. And SQLize is the big one, and is still a big one. And it didn't have support for transactions. It had a really... The APIs were sort of rough. And since then, it's come a long way. I've been really impressed with a lot of the development happening with SQLize. So if you haven't looked at it for a while, take another look. They're doing cool things, especially around the new postgres features that are coming out. A new one that I just saw recently, by someone who had been frequently commenting on bookshelf and knex projects, and I guess maybe had some opinions that were different, created this ZuulJS. And it's really impressive. It does transactions, doesn't have quite the separation between the query building and the ORM layer, but does a lot for you at the ORM layer. That's worth checking out. SQL bricks is pretty similar to knex, but with different opinions. NodeSQL, by the guy who does the postgres driver. Even the drivers have come a long way since I looked at them in 2012. The node my SQL driver has a ton of documentation and a lot of features added. It's really impressive how far it's come in the last few years. knex query lab allows you to demo this in the browser and have it spit out SQL. Bookends does nested data loading and querying really well. It's on top of bookshelf. And there's endpoints, a JSON API compliant library, which has knex and bookshelf under the hood, and larger stack implementations like Sails, which has their own ORM, but they were potentially talking about using knex as the query builder under the hood. So they're targeting all the different SQL drivers. That's just some of what's out there. But I really don't think this is enough. So... We're still sort of like... At this stage where node is a really young ecosystem. And a lot of times, you'll hear -- don't reinvent the wheel. Like it's already been done. But I sort of disagree with this. I think that people should absolutely be reinventing the wheel. With an asterisk. Just not on the client side. Because React already did this. No, I'm kidding there.
But, like, we should have more experiments out there, because I think the types of conversations we're having since React are really different, about... Just the web in general. Because they questioned a lot of opinions. So I think that -- take a look at other libraries. Take a look at other languages. Which is what -- you know, a lot of what JavaScript is about. JavaScript is sort of late to the party of being on the server. And a lot of the great ideas coming out around async and ES7 and ES8 are looking at the best of what's around in other languages. So I think it's really important -- like, as I mentioned, these were adapted from the Larvel query builder in PHP, and I would like to move a lot further toward SQL Alchemy and query builder. But I would love to see node become more of a target for traditional web applications. Prove that Stack Overflow question wrong, and get more awareness out there, that you can do this type of boring traditional website development in node, and I think the more that that becomes something that's well known, the more people will be writing JavaScript, and then more goes into the ecosystem. So that was sort of the goal of creating these two libraries, to sort of say -- hey, you can do this. And hopefully there's a lot more that comes out of this.
So that's everything.
(applause)
>> Woo! Thanks, Tim. So as y'all know, the next subject of our conference is lunch. Which is a meal eaten in the middle of the day for sustenance. Is Elliot Cable in here? Got him. Okay. Great. Well... That's all we got. I think we are still setting up lunch. So... You know, just mingle and stuff. Or go see if there's food out there. Be on the doors. Lunch is ready! Get out of here! Orderly...Ly... In an orderly fashion. We'll see you back here at 12:45. Thank you very much!
(Ghostbusters playing)
Event is not active
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment