justjs: node.js tutorials

New here? You might want to start at the beginning.

    3/11 '13

    jslint: a tool for better code quality (and a certain amount of picky nonsense)

      Today I made the uploadfs npm module's main .js file jslint compliant (or as close as a node module can be, anyway). jslint is an extremely powerful tool for catching "lint" in JavaScript code, not just excellent at finding likely bugs but also at encouraging code that will be easy for others to maintain and teaching you things you never knew about JavaScript along the way.   jslint is also a little annoying. But as author Douglas Crockford, one of JavaScript's greatest contributors, puts it right up front: "jslint will hurt your feelings." So I guess I shouldn't be too surprised.   Here is a revealing log of what I had to change, what felt valuable or even super-important, what felt unnecessary but ultimately kinda helpful, and what just seemed over the top.   But first I should clarify something that was confusing for me: jslint is frequently used to check (partially) for compliance with JavaScript's new-ish "strict mode," and indeed jslint insists you turn strict mode on. But strict mode and jslint are not the same thing. jslint enforces many things, like indentation conventions, that strict mode doesn't care about. And strict mode, because it is in…

    12/31 '12

    Creating reusable Express modules with their own routes, views and static assets

    Every developer eventually creates something nice they'd like to reuse in other projects. And Node is generally great at that, thanks to the npm repository. But there is one area where things get sticky. While you can release any code you'd like as an npm module, it is more difficult to package up a collection of Express routes, template views and static asset files in such a way that other developers can just drop your module into their project, initialize it and go. Adding Routes: Finding A Strategy That Works Express has a somewhat under-documented mechanism that sounds really useful. I was excited when I first found it: you can make a second app and "app.use" it from the first. This seems a natural way to add routes specific to a module. var express = require('express'); // My main app var app = express(); app.get('/', ... home page ...) // A second app object created in my cats module var catApp = express(); catApp.get('/', ... main cats page ...) // Mount the second app into the first one at the prefix '/cats' app.use('/cats', catApp);   Unfortunately, this doesn't work as well as you'd hope, because routes of the first…

    12/30 '12

    Singletons in #node.js modules cannot be trusted, or why you can't just do var foo = require('baz').init()

    Today I realized that singletons in node.js modules cannot be trusted in a project in which several npm modules depend on each other. Most Node developers have figured out that if two files in your project require the same module, like this:   one.js: var shared = require('shared'); two.js: var shared = require('shared');   ... Then they will get back the same object, because Node caches requests for the same module.   But you might not realize (I sure didn't!) that if your project is based on npm modules that both require the "shared" module as a dependency, like this: node_modules/one/index.js: var shared = require('shared'); node_modules/two/index.js: var shared = require('shared'); ... And you install their dependencies with npm, there will be two copies of "shared/index.js" hanging about:   node_modules/one/node_modules/shared/index.js node_modules/two/node_modules/shared/index.js   The cache mechanism of "require" does not consider these to be the same file. In my tests, the two modules get different objects back from require('shared').   Yes, there's a way around this. If your main project also requires "shared," and that copy is installed with npm first before either one or two is installed with npm, and they depend on the same version, then npm will be clever and install the module only once at the main…

    10/20 '12

    npm link: developing your own npm modules without tears

    You've started creating your own npm modules, giving code back to the open source community and getting it debugged and improved for free in the bargain. It's fun and easy. But it's also a hassle, publishing your module over and over just to use the latest version in your own project. In this article I'll explain how to use "npm link" to develop npm modules without pain in tandem with the projects that inspired them - and how to avoid doing it all with root privileges. Creating npm modules: being famous and awesome isn't hard Just about everybody in the Node community is developing and releasing npm modules for everyone else to use. Node was born well after the simplest business case for open source was well-understood: other people using your stuff "for free" are also debugging and improving it "for free." Whether to open source those tricky bits of readily reusable code isn't even a question in the Node community. Creating an npm module is ridiculously easy. Create a free, public github repository, clone it to a folder on your computer, type "npm init," answer some questions and you're up and running. Type "npm install --save underscore" in…

    10/1 '12

    Node lessons from Startup Weekend Philly

    (Or "What I Did On My Summer Vacation")   Hey, did you miss me? Sorry, I've been busy and haven't written much about node lately. But this weekend I attended Startup Weekend Philly. I was tasked to build an interactive website with a lot of data entry needs in a hella hurry. I wanted to make sure I learned something and had fun, so I built it in node and deployed it to Heroku. And here it is.   Some things I learned from the experience: Mongoose is a big win with table-like data Sometimes I recommend going straight to MongoDB. But if your data has a clear schema and you don't need inheritance, Mongoose is absolutely worth using. It adds exactly the right amount of schemasauce to MongoDB and no more. You can write this:     var company = new db.Company(req.body); company.save(function(err, company) { res.redirect('/companies/' + company.slug); return; });   ... And rely on Mongoose to validate 'req.body' and only use the properties that are in the schema to populate the company. That's so good.   Even better, you can do this when editing an existing object:   req.company.set(req.body);   Only the fields that are actually in…

    7/28 '12

    Chrome extensions: how to enhance Google Calendar and other web apps

    You can do just about anything with JavaScript these days. That includes altering the behavior of your web browser to suit your needs - not just on your own sites, but on any site you care to improve. And anyone who shares your definition of "improvement" can get the same benefits if you package your work as a Google Chrome extension and make it available via the Chrome store. My friends are in a band. The band is called Hot Breakfast. They are "Delaware's premier acoustic dork-rock power duo." I heart them and their silly covers and clever original songs. But the point of this love fest is that, last week, they tweeted: "We would like it if someone wrote a snap-in for Google Calendar, so when you click "Today" you hear Neil Diamond's voice. @boutell? :)" I am not one to shrink from a challenge! Getting Started: The Manifest Here's how to create a Google Chrome extension that enhances Google Calendar - or any website - even if that site insists on constantly re-creating its buttons with different IDs (I'm looking at you, Google). Start by creating a folder called "chrome-extensions", then create a folder called "today" (or…

    7/18 '12

    @synomat: a Twitter thesaurus, powered by node.js

    @synomat is a Twitter-powered thesaurus. It's easy to play with: tweet a word to @synomat and she tweets back a list of synonyms. Simple enough, but how does it work? node.js and the ntwitter module to the rescue! It might surprise you to learn that not every node.js app is a website. Fundamentally, node.js is not a webserver, although it contains modules that are stupendously good at it. At its core, Node is an engine for doing work asynchronously as the need arises, responding to events as they happen. Node is good for pretty much anything that meets that description. And running a Twitter bot - an automated Twitter account that provides helpful services to the public - definitely meets that description. ntwitter is a Node module that provides access to the Twitter API. That includes lots of things: logging in, tweeting, searching, and monitoring "streams" of tweets by particular users or groups of users. That last feature is really, really great for writing automated Twitter clients or "bots." Rather than using the http module (either directly or indirectly via Express), @synomat uses ntwitter as its main point of departure. Of course, it takes one more thing to make…

    7/14 '12

    Deploying node.js and mongodb in production with stagecoach

    Folks have asked me how I deploy the justjs blog, as well as the vidmood sample app. Fair question. I've explained how to run node apps on your own computer, using silly URLs like http://localhost:3000/, but http://justjs.com/ and http://vidmood.justjs.com/ require reliable hosting and a way to respond on port 80 (the standard HTTP port) to take that ":3000" business away. Even more important, deployment to a production server requires a solid strategy for pushing code to the production server after you've tested it... rather than hacking on your live site and crashing it as you go. But why stagecoach? There are several cloud hosting options out there. Heroku and, yes, Microsoft's Azure are cloud platforms that support Node. And Nodejitsu is the up-and-comer as well as being a major contributor to Node. But you're not limited to cloud platforms. You can also run Node yourself on any Linux server. The Linux VPS (Virtual Private Server) market is highly competitive, and you can easily run many node apps on a single VPS, so there's an opportunity to save a lot of money here. Hosting your own also allows for the possibility of an Intranet site not accessible by the outside…

    7/12 '12

    vidmood, Part II: behind every great browser app, there's a great node service

    In the previous installment, we checked out vidmood, a JavaScript-powered social web app contained in a single HTML file. Of course, that's a little bit of a lie. To be social, the app needs to share data with other users. And it also needs to find appropriate YouTube videos to match your mood, which requires talking to the YouTube API. JavaScript in the browser can't do either of those things on its own. We need a backend server to talk to. And that's where Node comes in. Unlike previous projects, this time I've kept the server code in a single server.js file, just to demonstrate how manageable that can be for simple apps. Especially when we take advantage of npm modules like Express and Mongoose rather than reinventing wheels. (Remember, the complete source code is on github. No need to type it all in or copy and paste snippets unless you like doing it that way. You'll need to install various modules with npm, as we previously discussed.) Keep Your Development Chocolate Out Of My Production Peanut Butter Enough prologue! Let's check out server.js. We begin by loading our options from a separate .js file (hey, it doesn't count…

    7/10 '12

    vidmood, Part I: when the web page becomes the web app

    Earlier installments of justjs focused on building a traditional model-view-controller web application, in which the server renders HTML pages via ejs templates and sends the finished product to the browser. JavaScript was sprinkled in, here and there, but essentially each page was static. Many web applications take things a step further by empowering the webpage to refresh part of itself, or to submit a form in such a way that it only refreshes the part of the page that needs to change. But the server is still responsible for assembling the page and returning fragments of HTML that replace parts of it. This approach was popularized by Ruby on Rails, which provided "helper" functions to dynamically update pages in a few standardized ways, without asking the programmer to actually learn JavaScript. But this approach is limited, and based on outdated assumptions about the limitations of web browsers. These days, we can finally count on a decent degree of smarts in a web browser, and call upon it to do more interesting things. New Wave Web Apps: it's all in the browser (almost) That brings us to the new wave approach: where the webpage becomes the web application. Rather than…

    7/8 '12

    vidmood: a new wave web app

    After a long wait, we have a shiny new sample project: vidmood. vidmood lets you share your moods in the form of wacky YouTube videos. It is (or will be) social, it's fun, and most importantly it demonstrates a different approach to building web apps with node. The blog application was a traditional web app, in the style of Ruby on Rails or Symfony 1: a big web application server rendering lots of HTML for each individual URL the user can access. vidmood is different. vidmood follows the new wave approach taken by web apps like twitter and gmail. When you visit the home page, you receive a web page... and that's the last time you receive a new web page (except for the Twitter login process). Instead, that web page contains a JavaScript application in its own right, perfectly capable of asking the node app server for the resources it needs. When the JavaScript code in the browser wants to post a new "mood" to the site, it does that via an AJAX request. Updates to the live feed of "moods" are also received via AJAX. And rather than sending "fully baked" HTML for these AJAX updates like…

    7/1 '12

    Tanned, rested and ready!

    I'm back from my honeymoon, newly espoused and ready to write about node. I was surprised to discover that justjs went down during my absence. My VPS was rebooted, 11 days ago. And it seems mongodb won't restart from an unexpected shutdown without a little manual intervention when journaling is not in the mix. Speaking of which, I really should be running MongoDB on a 64-bit system; but for the justjs app it isn't really necessary, so long as I understand its quirks (like this one). Sorry about the interruption. I'll be writing more soon!

    6/12 '12

    Hey, where did you go?

    Just checking in to give folks an update on what's happening with justjs. Three things are going on, in descending order of importance: I'm getting married on Saturday! I'm busy getting ready for that long-awaited occasion and the honeymoon to follow. So justjs is running a bit behind schedule. The next installment will use Backbone... which means a complete rewrite of the blog. This is exciting. It also means it's taken a bit longer than the average installment. I am ready to throw CKEditor out the window of a very, very tall building. If I never see the words "Cannot call method setHtml of null" again, it will be much too soon. So when I get back from snorkeling in Ambergris Caye, I will be ditching CKEditor, probably in favor of jWYSIWYG, and wrapping up the next installment of justjs. In the meantime, I suggest you check out backbone.js. Because as fast as node is, there's still no reason to make your users wait for the browser itself to create a new universe on every page of your application. Backbone is where sanity and AJAX meet. I'm excited. But not as excited as I am about Roberta Susan Petusky.…

    5/31 '12

    Let's be bold: rich text editing and validation

    We've got a blog... if you call being able to type in a single run-on paragraph with no line breaks a blog. Let's fix it so we can style blog posts any way we like. We could tackle this the old-fashioned way... one of several old-fashioned ways, actually: We could let users type in HTML, and just trust it. We could let users type in HTML, and validate it to remove scary stuff like XSS attacks. We could offer users a more convenient alternative markup language, like Markdown. We could just convert newlines to <br /> tags and URLs to links. We've all seen sites that use each of these strategies. And honestly they have their place. For comments and status updates, the last one can be a good choice; fancy formatting is probably just a distraction when folks are writing short comments. And Markdown is pretty awesome if you know what you're doing. Making people type HTML just to get line breaks is obnoxious, but it's not uncommon to mix that strategy with the "convert newlines to <br /> tags" strategy. So which one are we going to pick? None of them! We're going to give the user…

    5/28 '12

    Are these the droids we're looking for? Finding out with gmail authentication

    Since the last installment, our blog is looking a whole lot nicer. But right now, anyone can post. They don't need jedi mind tricks. We have no security whatsoever. Let's fix that by taking advantage of the passport module and gmail authentication. We can easily lock the "New Post" feature down either to one person or to anyone with an email address in an entire domain, as long as that domain is hosted with Google Apps for Business (aka "gmail for domains"). If you're already logged into gmail, all you have to do is check a box to grant permission. Logging in separately is not required. "Hang on there. Are you telling me I can only use gmail authentication? I don't even use gmail." No, not at all. Passport actually supports many, many authentication methods, including Facebook, Twitter, and yes, an old fashioned local database of accounts just for your site. Using gmail as an authentication provider is just one example. So why did I pick gmail for this demo? Because so many individuals and companies do use gmail accounts or host entire domains with gmail. And because in the latter case we can easily grant access to everyone…

    5/24 '12

    Page Templates With EJS: Finally, We Can Have Nice Things

    Page templates, partials, and other attractive concepts So far, we've been sending web pages to the browser with the following marvelous technique: var s = "<title>Oh come on</title>\n"; s += "<h1>Oh come on!</h1>\n"; s += "<h2>You have GOT to be kidding.</h2>\n"; Yeah, not so marvelous. It's too much work, it's tough to maintain, and it's scattered all over our "app" module. Which really ought to be our "controller" layer. Not our controller and view layers all mashed up like a Reese's Peanut Butter Cup. Except not yummy. Clearly, we need page templates! Folks who have programmed in almost any web framework have used templates of one sort or another. What they all have in common is that they put HTML first and code second, allowing you to write HTML with some code in it, as opposed to the other way around. Really good template systems also let you have layouts. Sure, you can write a complete HTML page - starting with the DOCTYPE, continuing through <html> and <head>, plowing through <body> and going on to that final </html> - for every single interaction. But that's a waste of effort, and it pretty much guarantees your pages will get out…

    5/20 '12

    Let's Post Something! (In which our blog becomes a blog, just barely)

    Wait. What just happened? In yesterday's installment, we did three very cool things: 1. We created a "db" module that stores and retrieves posts for us. That module happens to use MongoDB, but if we changed our minds, we could write a new module with the same methods and "require" that module instead, and the rest of our code would be none the wiser. That makes it much easier to maintain our code. 2. We learned how to do simple things simply. The async.series function lets us carry out a series of steps one at a time, even though the code that implements those features returns right away and doesn't invoke our callbacks until later. 3. We learned a lot about nested functions and closures, key features of JavaScript that make callback-driven programming (Node's defining characteristic) soooo much more pleasant than in most languages. But there's one thing we didn't do: run our app! That's because we stopped short of exploring the last new module in this version: app.js. The app.js module: controlling the action In previous versions of the blog, our code for displaying blog posts was pretty much the same as our code for fetching them. (To…

    5/19 '12

    Models, MongoDB and Modules, oh my!

    Please note: "oh my" should be read in George Takei's voice for maximum effect. Previously, on Nodes of Our Lives... Last time out, we refactored our code to map URLs to functions in a much more elegant way, using Express routes. But we didn't add any new features to the blog. So in this installment we'll do something a little more tactile: we'll store posts in a MongoDB database, so that we can actually add new posts! This blog is just getting more real all the time. Separation of Concerns: Breaking Things Up Into Modules Our app is getting bigger. And as it gets bigger, the code gets harder to grapple with in a single file. It's time to break it up into several Node modules. Readability isn't the only reason to split code up into modules. An even better reason: code for unrelated purposes shouldn't be jumbled together. Ideally, code that performs a particular function is best off in a separate module, relying as little as possible on knowledge of the outside world.  One can take this too far, but it's a good guiding principle. For instance, the route callback that displays a post to the user needs to fetch…

    5/18 '12

    Classy routes with Express

    Edit: brought back the notFound() function so we can use it when a reasonable-looking URL doesn't match an actual post. When We Last Saw Our Heroes... In the last installment, we built our first node app. And we learned that every node app is a webserver, deciding what to do with every incoming request from a browser entirely under its own power. Which is pretty cool actually. But it can also get messy. Consider this code from the previous example: var server = http.createServer(function(req, res) { if (req.url === '/') { // Deliver a list of posts index(); } else if (posts[req.url]) { // Deliver this particular post post(req.url); } else { notFound(); } }); Here we have the beginnings of what could easily become a very, very long "if... else if... else if... else if... else if... [deep breath]... else" block. Those can easily become difficult to maintain. What happens when our app is a little less trivial and we have 100 different actions to deal with? Fortunately, there's Express! Express is an optional Node module that bills itself as a web framework, and it offers many things: user sessions, templates, file downloads, parsing of form submissions, routes…

    5/16 '12

    Now That's REALLY Basic: The Simplest Blog Ever

    And It Really Does Something! For our very first node app, we'll create the simplest blog ever. And I do mean simple! There's no database, no layout, no stylesheet, no template language to make it easier to render things... and all of that will change in later examples. But for now, this is a great way to explore the basics of creating a web app in Node, without resorting to a meaningless "Hello World" application. I really hate those. To get started, create a folder inside your home directory called "node-apps", create a second direcory inside that called "blog-1", and finally create a new text file there called "server.js". And if you want, cheat: pop over to github to copy and paste the code. Or just follow along as I explain. By convention, Node applications begin life in a file called server.js and starts executing at the top of the file. And the first thing we usually do in a Node application is pull in a few other JavaScript files that do useful things.  Unlike PHP, Node isn't already baked into a webserver like Apache. Instead, every node web application is a webserver, listening for connections from web browsers…

    5/15 '12

    Getting Started, Part II: Discovering MongoDB

    Storing Stuff: It's Kinda Important! Node is up and running already. So I could skip along and start showing you things node can do. But I have this terrible, old-school habit of writing apps that store stuff. And storing stuff requires a place to put it. And I like to be able to store that stuff close by, especially when I'm developing a new app and testing lots of changes. I don't want to wait for some far-away cloud database server to respond sluggishly to an app that's running on the Mac in front of me. So before we dig into Node, let's finish assembling our new toys by installing the MongoDB database. Why MongoDB? First: MongoDB speaks JavaScript. Note the title of this blog. 'Nuff said. Second: MongoDB is much faster than old-school SQL databases. Third: MongoDB has a more robust set of features than most "NoSQL" databases. When you consider how flexible and friendly MongoDB is, it's really more of a "NewSQL" database. Folks who have experience with MySQL and other old-school databases will be more comfortable with MongoDB than with most other alternatives. I would sum up MongoDB's personality thus: "we like delivering cool features. We…

    5/15 '12

    Getting Started, Part I: Installing Node

    I've sung the praises of node.js, but I haven't yet explained how to actually bring this goodness into your life. Fair enough. Time to install node. Famous last words maybe, but I'm going to devote just two short posts to the semi-interesting topic of installing things. It's all levitating outer space kitten games after that, I promise. So just bull through and you'll be glad you did. I'm going to make a few assumptions: 1. You want to be able to try out node sites on your own computer. Yes, you could do everything in the cloud... and wait for Internet lag every time you want to test something. But would this completely defeat the purpose of using an environment as fast and fun to work with as node? Yes! It totally would! 2. You've got a Mac- or you're reasonably comfortable with the computer you do have and can use my step-by-step instructions as a rough guide to what you need to do. Both node.js and mongodb have installers for Windows, MacOS and Linux. (Actually, if you're on Ubuntu Linux, you can skip to the head of the class with a handy installer script I wrote at my awesome job.…

    5/14 '12

    Frustration + Motivation = Excitation

    Welcome to the first installment of justjs.com, a highly autobiographical blog about full-stack web development in node.js, MongoDB and JavaScript! I've known lots of web development languages. Trust me... lots. So why code in JavaScript? It begins with one word: Frustration This blog is motivated by my own frustration with the constant "context switching" that comes with the use of separate backend and frontend programming languages. And not only that, but also a profusion of configuration file formats and templating languages jostling for space in my skull. Taken individually, they all add value. Collectively, they make programming a frustrating exercise in remembering the rules of the environment you're in at the moment. Meanwhile, all of these tools slow everything down! In the name of making it friendlier, speeding it up, or both. In the name of making things friendlier, many web frameworks and programming languages sacrifice performance. And in the name of speeding things up again, many frameworks try too hard to cache everything magically behind the scenes - creating tools that are fast in production but painfully slow in the "dev" environment. Motivation These are gripes. Gripes don't normally motivate people to tackle entirely new paradigms. But for…