What do you want to learn?
Leverged
jhuang@tampa.cgsinc.com
Skip to main content
Pluralsight uses cookies.Learn more about your privacy
Meteor.js Fundamentals for Single Page Applications
by John Sonmez
In this course, you'll learn about the Meteor platform and how to create a single page application using it.
Start CourseBookmarkAdd to Channel
Table of contents
Description
Transcript
Exercise files
Discussion
Learning Check
Recommended
Introduction
Introduction
Hi, this is John Sonmez from Pluralsight, and welcome to this course on Meteor Fundamentals for Single Page Applications. In this course, we'll be exploring the open source platform for building single page web applications, called Meteor. Meteor is still in the preview version at the time of recording this course, but it has the potential to make a big impact on the way we develop web applications, as you'll see in this course. When I first saw Meteor, I was very impressed by how easy it was to use, to create a real-time web application that didn't require me to think so much about the differences between the client and server. By the end of this course, you'll learn the basics of Meteor and how it works, and how to create a complete web application in Meteor, and how to deploy that application.
Who This Course is For
The goal of this course is to equip you with the basic knowledge you need to start developing Meteor applications. We'll be going beyond just the basics of Meteor though, and getting into how Meteor actually works and utilizing a pretty sizeable chunk of the features of the platform. So, whether you have a basic knowledge of Meteor, or you are just getting started, you'll probably find this course to be valuable, as it will take you from the very basics to actually deploying a web application built with Meteor. It doesn't really matter if you're primarily a .NET, Java, Ruby, or even Python or PHP developer, if you use JavaScript to create web applications, you'll probably find this course will make sense to you. But, you really should have at least some familiarity with JavaScript to get the most out of this course, since Meteor uses JavaScript on both the client and server sides and we won't be going over the basics of JavaScript in this course. I will try to keep the JavaScript as simple as possible though.
What This Course Will Cover
So let's take a moment to talk about what we're going to actually cover in this course, and we're going to start off in the first module that you're watching now, where we will talk about the basics of Meteor; what exactly is Meteor, how does Meteor work at a very high level? And then we'll also see how to create a basic Meteor application. We'll get set up with Meteor, which is very simple, and we'll create a simple ‘Hello World!' application using Meteor. Then in Module 2, we'll dive deep into the details of Meteor. It's really important to understand exactly what's happening inside of Meteor, so that you can better design your applications and you're not always wondering how things are going to work. Once we understand the deep details of Meteor, we won't have to visit them very often after that, because we'll know that what's happening in the background is going to work and we'll understand the principles behind it. So we'll be dissolving some of the "magic" behind Meteor and we'll also see how a real Meteor application works as we observe it inside of the Chrome Developer Tools Window. Then in Module 3, we're going to start creating our application. We will be building a basic Meteor application and we'll be hitting on some of the key concepts of the Meteor application, starting with things like templates and then getting into collections and even publishing, which is the heart of the Live updates that happen inside of Meteor. In Module 4, we'll extend our app and we'll build some more functionality onto it, including some user accounts, and we'll be working with things like sessions and computations, which also will help us to be able to create a more fully-functional application using the platform. Then finally in Module 5, we're going to go a little bit beyond Meteor and we're going to see how to get Meteor set up on different platforms, as well as how to deploy the application that we've created. There's a few different options for deploying and we'll cover those in this module. We'll also look at some package management and an open source tool that we can use to actually get other Meteor packages and different modules that we can add on to Meteor.
What is A Spa
And before we can really talk about Meteor itself, we have to understand what a Single Page Application is, because Meteor is a platform for building single page applications. Now, Single Page Applications are a pretty big buzz word right now around the development community, but I find that there is still quite a bit of confusion about what exactly a Single Page Application, or SPA, is. A SPA is simply a web application that works with a single page load. Everything the application needs to do after the initial page load is handled without having to load a new page. You can imagine that there's a large amount of variety in SPAs, because the definition is so broad. Flash applications and Silverlight applications could really be considered SPAs, as well as applications that use AJAX to dynamically update the HTML in a page, or more specifically the DOM in your web browser. A great example of a SPA is the ever-popular Gmail app. When you load up Gmail in your browser, you go to a single page, and from that single page you can view your emails, manage your inbox, and do just about anything else you're allowed to do in the app. What is actually happening to make this possible is that the JavaScript running on the page is making calls back to the Google servers to fetch and send data through XML HTTP Requests, also known as XHR Requests. Meteor helps us build applications like this by providing us all the infrastructure, so we can worry more about creating our applications than the technology behind them.
What is A Meteor
Okay, so now that we know what a SPA is, what exactly is Meteor? Well I already gave you hint, when I said that Meteor makes it possible to create a single page application without having to think about all the infrastructure involved in creating one. And that is really one of the big goals and values of Meteor. This doesn't mean you never have to worry about how the browser and server communicate with each other using Meteor, but it does mean that, unlike building your own framework or polling in pieces of different JavaScript frameworks, you don't have to be so involved in the technical details of what's going on. Once you understand how everything works, you can relax a bit and let Meteor do the heavy lifting for you. I specifically called Meteor a platform, because it's more than just a JavaScript Library, or set of JavaScript Libraries. You can really think of Meteor as a package containing everything you need to build a single page application. For the most part, the technology itself behind Meteor is nothing new or revolutionary, but it combines all the things you may have already been doing and creating a rich, JavaScript-based single page application in a very simple and easy-to-use way. For instance, when you use Meteor, you don't need to write your own AJAX code, you don't have to manipulate the DOM, and you can access your database directly from the browser.
Key Characteristics
Here are some of the key characteristics that define Meteor and tell you what really Meteor is about. So first of all, Meteor uses just one programming language, and that programming language is JavaScript. Now you can view some packages to use CoffeeScript or something like that if you want to, but the basic idea behind Meteor is that it just uses JavaScript and it uses the same JavaScript on the client and the server, and for the most part it uses the same APIs. So you don't really have to write specifically server code or client code, although you can and you may want to in some instances, but instead you can focus on using an API and not have to worry about whether or not that API exists on the client and the server, because for the most part, as long as it makes sense, it does. Next is the automatic updating of pages. So, one thing that you'll notice as soon as you create a Meteor application is that the Meteor application seems to update automagically. As soon as some data changes in the database, you see it reflected in your Meteor application and it even works across multiple browser windows. So this is one of the key things that makes Meteor really unique and is really a neat part of the Meteor platform, because it's real easy to create applications that work like this. In fact, by default, all Meteor applications have this capability. Next, we don't have the need to make AJAX calls to REST APIs. So we have the same type of functionality, but it's treated just like a regular function call inside of JavaScript. We don't have to make a specific call and handle and parse data that's coming from a REST API. This makes things a lot simpler and we can focus more on the application and less on creating a perfect REST API for our app and then trying to consume that API. Next we have latency handling that's built in automatically. One thing that you'll see with Meteor applications is that when you click a button or do something, you can immediately show a result without having to go to the server first. What happens with Meteor is that it will go to the server eventually and then return a result, and it may update the data in a different way, but you can by default create applications that have some kind of latency handling built into them and they know how to basically handle these different scenarios that can exist. And then finally, Meteor produces self-contained application bundles. What I mean by this, is when you create a Meteor application, you can bundle it into a single compressed file and you can deploy that anywhere that Node.js and MongoDB exists. It's all contained in one place and you don't have to worry about a particular type of server or environment for running it; you can basically run your application just about anywhere.
Technologies in Meteor
Let's talk about some of the technologies that make up Meteor. It's important to understand what technologies make up Meteor, because if you do have to troubleshoot something inside of Meteor, you want to know at least what you're dealing with, and also, you may want to actually swap out different parts of Meteor. And it turns out that Meteor actually allows you to change your database or your templating engine. So for example, if you don't want to use MongoDB, you can use a different database; and if you don't want to use Handlebars, you could use a different templating engine.
JavaScript
Now it's probably no surprise that at the core of Meteor is JavaScript. JavaScript is the programming language that you use to create a Meteor application, but I did want to talk about some of the ways that Meteor uses JavaScript, because it's sort of unique. So first of all, because JavaScript is being used in the client and the server, it means that you only have to learn one single programming language. This greatly simplifies web development. If you think about web development on many other platforms, you have to learn a lot of different technologies in order to be able to build a simple application, but with Meteor you just need to know JavaScript. And on top of that, you don't really need to know a lot of different JavaScript Libraries. Sure you can pull them in, in Meteor, but for instance, you don't need to use jQuery to directly manipulate the DOM because Meteor takes care of that for you. So, even though Meteor is using JavaScript, it's not using all the baggage that usually comes with JavaScript from generating your own JavaScript, and injecting it into the right part of the page, and importing all the correct libraries. Also the JavaScript in Meteor runs on both the browser and server. In fact, by default, any JavaScript you add to your application will run and exist in both of those locations. We'll talk a little bit later about how to separate it out and how to make certain JavaScript only appear on the client and certain JavaScript only appear and run in the server, but it is nice that you can have an environment in your Meteor application where you're only using just one programming language and you don't have to concern yourself so much about where that code is going to run.
Node.js
Now it also may not surprise you that Meteor uses Node.js to serve your application. Since you have a purely JavaScript-based application, Node.js is probably a very good way to serve that application up and Meteor uses Node.js. Now it is important to realize that Meteor uses Node.js in a different way than a lot of other Node applications do. What I mean by this is that one of the big things about Node is that Node uses an event-driven, non-blocking, I/O model. So what this means is that usually a Node application will handle requests on a single thread and it will basically do those operations asynchronously. In Meteor, even though Node.js is being used, different instances of Node.js are being used to handle different requests, so there are different threads running. But, Node.js is the underlying technology, which means that it's really easy to create a Meteor application and run it somewhere else, because it is basically just a Node.js application. This style of running an application is called a single thread per request as opposed to Node's default style of running an application, which is an asynchronous callback style. The other thing to know about Meteor's use of Node.js is that Meteor uses its own packaging system, it doesn't use the NPMs that you would find with a typical Node application.
MongoDB
Now by default, Meteor uses MongoDB as its database. MongoDB is a very popular NoSQL database that has a very easy-to-use JavaScript API, so it makes a good fit for Meteor, which is a JavaScript-based platform. MongoDB is actually used by Meteor in an interesting way. Meteor uses both MongoDB on the server, as well as a special abstraction over MongoDB on the client that basically allows a client application to write to the database and then that data is replicated down to the actual real database on the server. We'll talk more about this when we get into the details of how Meteor works, but it's important to realize that when you're actually writing to MongoDB on the client, it's not exactly the same thing as writing on the server.
Handlebars
The last major piece of technology that Meteor uses is a templating library called Handlebars. Handlebars is a pretty popular library for creating template that makes it so that you can separate your HTML and JavaScript so you don't have to have all of your JavaScript mixed in with your HTML and try to generate HTML on the fly using something like jQuery. Meteor uses Handlebars and it knows about Handlebars, so it can automatically update the DOM in your page, and this is part of some of the magic that happens when you see Meteor automatically updating a page. We'll talk more about how this works when we get into the details of a Meteor application a little later on, but it's also worth noting that you don't have to use Handlebars; Handlebars can also be swapped out with another templating engine if you want to.
Meteor Versions
Meteor actually has a few different versions; two that are officially supported and one that is not officially supported. Meteor is officially supported on both Mac and Linux, but it's not officially supported on Windows, although there is an officially supported version for Windows that is supposed to be coming shortly after the 1.0 release of Meteor, at least it's on the schedule. Now if you use Mac or Linux, you can immediately get the newest version of Meteor, since it's officially supported there and have access to all the capabilities of Meteor, but if you want to use the Windows version, which works pretty well, it might just be a little bit behind. So let's talk a little bit more about the Windows version of Meteor, because that's what we're going to be using, at least for the start of this course. Since there's really not a huge difference between the Windows version and it's probably a little bit easier for most people watching this course to get the Windows version set up, we're just going to start there, but feel free to use the Linux or Mac version if you want to as you follow along with this course. Now there's a few different choices for getting Meteor working on Windows; many of them involve a virtualized machine, which you're welcome to use as well, but we're just going to use the unofficial version of Meteor, which is just a little bit behind the latest released version of Meteor. The only other drawback to using the Windows version of Meteor that's unofficially supported right now is that we don't have access to the Meteorite application, which basically wraps Meteor and adds a package management system that allows us to get open source community contributed packages from a library called Atmosphere. But don't worry, we will cover both Meteorite and Atmosphere. We'll just be doing that at the very last module in this course when we actually use the Linux or Mac version of Meteor. For now, though, with what we're going to be learning about the basics of Meteor, we don't need to worry about that and the Windows version will work just fine. I'm going to show you how to get that set up next.
Setting up Meteor
Okay, so I'm at the meteor.com website, this is the main site for Meteor, and here, if you do want to use the Linux or Mac version and I just want to show you real quick, if you click on the Documentation, it is super easy. You just do a curl and then you just do ‘meteor create myapp' and then you can go in there and you can run Meteor right from there. This is basically all you need to do to get Meteor installed. Now, if you're using the Windows version, which we're going to be using for the most part of this course, you can just go to win.meteor.com, and here you can find a couple of downloads. We're just going to choose the ‘Latest Meteor for Windows', this exe bootstrap, but you can also download the MSI installer if you want, but I'm just going to choose this ‘Latest Meteor for Windows' and you can see that it just gives me an exe that I can run. And when I run this exe, it'll get Meteor set up, and you can see here on my machine that I already have Meteor installed, so it's actually running the Meteor command, which it wants me to be in a Meteor Directory in order to be able to run this. So, we can see now that Meteor is working, and on your machine when you run this, you should see an install script flash by and then Meteor will be set up and ready to run. It's pretty simple.
Hello Meteor
Okay, so once you have Meteor installed, all you need to do is basically type ‘meteor' to start using it. Now Meteor has this command line interface that allows us to do a lot of what we need to do as far as setting up Meteor and creating new projects just by using this Meteor command. In fact, you should be able to type meteor and you should see this following output here. If you don't, you might have a problem because the exe on Windows should have set up Meteor in your path. You might have to reopen your Command Window if you had already installed it from the Command Window. Now let's go ahead and go to whatever directory you're going to create your Meteor application in and we'll just create a very simple ‘Hello World!' application. So I'm just going to go into here, into WIP, and then I'm going to go into meteor, and then inside here, I'm just going to do ‘meteor create' and then whatever I want to call my application, so let's call this HelloMeteor. Now, you can see that it's created a directory called HelloMeteor, so we can actually cd into here. And then if we type meteor, it's running our application, and you can see it's running by default on localhost port 3000, so all I have to do is go to localhost:3000, and this is my Meteor application. You can see it doesn't really do much at this point, but I already have an application that's being served up by Meteor.
Looking at Hello Meteor
Now before we move on, let's take a quick look at that directory for the project that was created by Meteor. So if we go into that HelloMeteor directory, you'll see there's a CSS file, there's an HTML file, and there's a JavaScript file, and we'll talk more about this later when we get into the details of Meteor, but you can see here that this CSS file is blank, the HTML file is actually a template file. So if we were to look at this in an Editor, you can see that it's using that Handlebar's templating, which we'll talk about more when we get into the creating our own application, and then our JavaScript file is here as well, and you can see there's actually some JavaScript happening inside of this simple application already. And when we look at this JavaScript, you can see here that the same JavaScript is going to be running on the client and server. In fact, there's this if(Meteor.isClient) and if(Meteor.isServer). We only really have code that's operating on the client at this point, that's where we're getting this HelloMeteor for our greeting, it's filling it in in the template. And then, there's something interesting here, we have an event hooked up that we didn't realize when we looked at this in our browser. When we clicked that button, we thought nothing was happening, but it was actually doing a console log. So let's go back to our browser now and take a look at that and see what's actually happening here. Now if I open up the Chrome Developer Tools and I click the button, you can see it's actually saying ‘You pressed the button'. So that's your basic ‘Hello World!' Meteor application. We'll get more into the details of how everything works in the next module.
Up Next
Well that's it for this first introductory module on Meteor. Hopefully by now you have a good idea of what Meteor is and what Meteor is about and some of the technologies that make up Meteor. And we've seen just how easy it is to create a Meteor application, as we've created our first Meteor application with the HelloMeteor default application just by running a simple command. Now everything we do from this point forward won't be quite that simple, but creating web applications with Meteor is a lot simpler than using many other frameworks and technologies you may be used to. Now up next, we'll be diving a little bit deeper into Meteor and seeing how exactly Meteor works and how the magic that is Meteor happens. We'll also explore some of the demos and example projects that come with Meteor itself and see how those work inside of the Chrome browser, as we use the Chrome Developer Tools to analyze what's happening behind the scenes. Thanks for joining me and take care.
Understanding Meteor
Introduction
Hi, this is John Sonmez from Pluralsight, and in this module, we'll be diving a bit deeper into Meteor, as we learn exactly how Meteor works. Probably the biggest challenge you'll find in developing an application with Meteor is having enough faith in how Meteor works to be able to let go of some of the control you might be used to in developing an application and let Meteor do much of the hard work for you. We have to demystify a big portion of the magic of Meteor in order to understand how best to use it. In this module, we'll take a look at how exactly Meteor works. We'll start with the basics and talk about how Meteor actually manages to synchronize data almost seamlessly between different clients connected to the same application. We'll also look at the project structure of a Meteor application and take an in-depth look at Meteor in action, as we watch the data going back and forth, using the Chrome Developer Tools. By the end of this module, you should have a good understanding of how Meteor works and be ready to build an application using the technology.
Looking at An Example
So let's actually take a look at Meteor in action, just so we can see what Meteor can do with a very, very simple application. So I actually have an example application that you can get from Meteor directly that sort of ships with Meteor and the Meteor Tool and we'll look at a couple more of these later on, but this basic application is a leaderboard application, and I have two windows open, two different Chrome windows, and you'll notice here I can select a person and then I can click this ‘Give 5 points'. And watch the other window when I click this. So you can see here that it's actually updating very, very fast in almost real-time, pretty much in real-time, and it's synchronizing between the two. So, for example, if I ‘Give 5 points' here, you can see that these are changing as well. So, either way, this communication is happening back and forth, and this is one of those things that seems like magic, especially when you see how simple this application is. Let's take a quick look at this actual application and then we'll discuss how this is working.
Looking at The Code
Okay, so if we look at the directory that this application is in, this leaderboard directory here, you can see that there's basically three files that make up this application, and then this .meteor folder, which contains the Meteor information. It's not really part of the actual application, though, it's just part of the data that Meteor uses to run the app. So really these three files. And let's take a look at these files here. So you can see that the first one is just a CSS file, so just styling, nothing really fancy here, so it's not really contributing to the application functionality itself, so we could pretty much discard this file and our application would still work. And then the two main files are this HTML file and this JavaScript file. So if we look at this HTML file, it's a bunch of HTML and it's using some templates here, which we'll talk about a little bit later on, but there is not a whole lot here, it's not all that complicated, and then when we look at our JavaScript file, again, not a lot of code here. I mean, really this is pretty amazing, what is this -- 48 lines of code, 47 lines of code here, and we have all that functionality of synchronizing between the two browsers and having all this work in real-time. If you can imagine, how much code it would take you to create this similar functionality using another JavaScript framework that you might already be using or just trying to implement this yourself with jQuery and WebSockets, it would be pretty difficult to do. So, this is really the magic of Meteor. And now we're going to go and demystify some of this magic and explain how can you possibly get this much functionality with this little code.
It's not Magic
Obviously, you didn't really think that Meteor was magic. Well, if you did, don't worry, I won't tell anyone. When I first saw Meteor in action, I thought there had to be some kind of magic going on. But anyway, everything that Meteor does is already possible with other technologies. The big difference, and one of the main reasons why I like Meteor so much, is that Meteor takes these fantastic things and pushes them to the background so you don't have to think about them so much. In that regard, they sort of act like magic. In the new few slides, we'll take a look at the three main areas of magic in Meteor; communication between the browser and server, data synchronization between many clients, and updating of HTML live in the browser without manual DOM manipulations.
How Meteor Works
First let's talk about how Meteor is able to achieve real-time communication with your browser When you request a page from a Meteor Server, the Meteor Server really delivers you a page that is a pretty empty skeleton, along with a bunch of JavaScript responsible for setting up a real-time connection with the server. By default, Meteor will try to set up a WebSockets connection, which is a newish protocol that allows for sending data back and forth between a server and client. Using WebSockets, the server can actually push data to the client, which makes it much easier to do real-time communication. Now, if WebSockets are not available as an option, Meteor can use XHR Requests and SockJS to emulate the behavior of WebSockets using polling. Once a connection is established, the browser and client communicate with each other using a protocol called DDP, which we'll take a much more in-depth look at later, but it basically allows for publish and subscribe style messaging and remote procedure calls. This allows the browser and server to share data in a very similar way that a native application communicates with the server over a protocol like TCPIP. It's also worth mentioning here, that Meteor is able to directly access the MongoDB on the server using this communication mechanism. A JavaScript Library, called minimongo, is loaded in the page and the JavaScript in the app can call MongoDB using the same MongoDB API you would use on the server. The communications are basically just proxied through this communication channel.
How Meteor Works Synchronization
Okay, so now you know how Meteor apps running in the browser are able to communicate with the server in real time. But, how do Meteor apps communicate with each other? The magic here is a Publish/Subscribe model of messaging that you may have seen before if you've used a technology like Microsoft Message Queue, or JMX, or any number of other implementations of messaging. What happens to make this work is that each client will subscribe to some events that happen to data on the server. Let's say you have a bunch of customers stored in your database on the server, well, each client could subscribe to be notified when that customer data changes. Then, one of the clients ends up changing the customer data. The Meteor Server sends a Change Data over to all the subscribed clients and they update their display to reflect the new data. It's surprisingly simple how all this works.
How Meteor Works Updating
The final piece of magic is how the web page automatically gets updated when the data actually changes. If you've written JavaScript or applications in the past, you've probably used something like jQuery to manipulate the DOM to reflect any data changes manually. Meteor does this for you so you don't have to worry about it. In Meteor, you create templates of HTML using a templating engine, like Handlebars. If these templates utilize some data from your database, Meteor automatically wraps the data that the template uses in some code that watches for any changes on the data and creates new HTML markup that represents how the data should be displayed. This is done through a Rendering Function and then that Rendering Function generates a Document Fragment that is part of the loaded HTML page in the DOM. Because Meteor is watching the data for you, it recalls the Rendering Function when data that the Rending Function uses is changed, and the Rendering Function regenerates the Document Fragment, which is swapped out in the page. All this happens very automatically if you're using templates with Meteor, but you can also utilize this reactive style of programming yourself by using some of the APIs built into Meteor. We'll see how to do this a little bit later on in this course. Again, this isn't magic. You might actually write similar code in your own JavaScript application, to do this using the Observer pattern or using a framework like Knockout.js or Angular, but here Meteor does most of the work for you automatically.
Meteor app Structure
Now that we've demystified Meteor as magic a bit, let's talk about some of the other technical aspects of Meteor that you need to know. First, we have the app structure. Meteor is pretty flexible with app structure. You can actually structure your app however you want, but there are a few rules you should be aware of that govern how files in your application's folder are handled. All of these folders are optional and would be placed at the root of your application's main folder. First, we have the /client folder. If this folder exists, Meteor will run the JavaScript in this folder only on the client, so it will only run in the browser and not on the actual server. The /server folder will likewise run any JavaScript that's in this folder on the server only and it won't run on the client. Then we have the /private folder, and this is a folder for assets, so this would be things like images, fonts, images, and this one is only going to have assets that are accessible by the server. You might put something in there that you don't want the client to have, maybe you have some data file or some other type of file in the private folder that your server code is going to use, and you wouldn't want to expose that to the client. Then we have the /public folder and this is similar to the /private, except this is really where you'd put all of your static assets, like fonts and images, and things like that, that you would serve up, and anything in the /public folder can be accessed. Then we have a /lib folder. This folder, if it exists, will run before everything else. So you can utilize this folder if you have any code that you need to make sure that you run first, and remember, since this is not in the client or server, this is going to run on both the client and server, anything in this /lib folder. Then we have the /test folder. This is just where you might put your tests. It doesn't actually run anywhere, so any JavaScript in there is not going to run by default. And then you have anything else. So if you don't put something in one of these folders, it's just going to run on the client and server. So you might have to put in some conditionals in your code to decide, when it's on the client that a certain section runs, or it runs in a certain way; and when it's on the server, it runs in a different way; or perhaps, the code will work fine in both locations. Then finally, we have this convention here. So any files that begin with main.* will run after anything else, so you can control the order in which your scripts run, and that rule applies to any files in any of these folders.
Meteor Packages
Meteor has its own packaging system, which allows for creating component ties to a Meteor application. By default, all Meteor applications use a package called the standard app package, which is the core stack that makes up Meteor. This core package contains all the other packages that you need to get a basic Meteor application up and running. You can disable this package and manually add your dependencies, but unless you have a really good reason to do so, I'd recommend against it, since many of the packages included are needed for most applications. There are actually quite a few useful official Meteor packages that you can utilize in your application to do things like, have the ability to log in to your app using Facebook or Twitter, write your app in CoffeeScript instead of JavaScript, and even add Backbone or Bootstrap. There's also an unofficial community contributed package platform called Atmosphere, but we'll talk more about that one a little bit later on. Let's take a look at how to find and use Meteor Packages from the command-line next.
Using Packages
So I've got a command-line window open and I'm in the directory of that leaderboard example application that I showed you at the beginning of this module. Now from here, I can actually use Meteor to do more than just run Meteor itself. If I run the Meteor command in here, it will start up that leaderboard application and host it on Port 3000, but if I do, meteor list, it will actually list all of the packages and give me a description of them, so you can see here that there's all these accounts packages that are really useful for being able to add this kind of logging in with another service functionality to your app very easily. We'll look at a little bit of this later on, but you might want to check out some of these on your own, instead of trying to implement some of this stuff by yourself, which can take some time and be difficult. You can see all these other packages in here, including CoffeeScript and D3 (D3 is a charting library that's really good), we have email capabilities, jQuery, a bunch of different things in here, and I'm sure that more will be added over time, but you can list all these here, and then you can also do ‘meteor add' and then whatever the package name is, whatever the name is here, and you can add that. So, for example, I could ‘add htmljs' and that's going to add ‘htmljs: Easy macros for generating DOM elements in JavaScript'. I can also do ‘meteor remove htmljs' and it will remove that package. So you could utilize this in your application and then, like I said, there is another place that you can find the community-contributed packages, but for now we're just going to be sticking with the official Meteor packages.
Examples
Okay, so now let's take a look at a couple of the demo applications from Meteor so we can get an idea of the Meteor capabilities and then we'll actually use one of these demo applications to really look inside Meteor and see the data going back and forth when we're manipulating data inside of a Meteor app. So if you go to meteor.com and then you click Examples, you can see there's four main examples here that I'd recommend that you check out and play around with the code some, just to get familiar with Meteor, because it's so easy to get these things set up. So, all you have to do is basically just call this ‘meteor create', and then ‘--example', and then, in this case for example, you would do ‘leaderboard', and then you can see like for parties, it's just ‘--example parties', and then todos, we have one as well. So let's take a look at a couple of these. We've already seen leaderboard, but let's go ahead and take a look at, we're just going to go to the todos and the wordplay, since those are some interesting applications, let's do that next.
Getting The ToDos Example
Okay, so I'm here in the directory that I created for my Meteor application and I'm just going to type here, ‘meteor create --example todos', and this will go ahead and create that example and you can see, it's real simple to get started with this, we just cd into todos and then we just run Meteor. And we have this example running, so if I go and open up my web browser, and then I go to 127.0.0.1.3000, it will take me to this Todos app, and then here you can see that we've got a pretty good Todo application that you can sort by the different Todo Lists, you can check things off of the list, you can delete something from the list, you can change the tags, so pretty good amount of functionality here, and let's take a quick look at the code behind this next.
ToDos Code
So if we look at the code for this application, you can see that project structure that we had talked about. It's got a client folder, a public, and a server. So if you remember the client folder has some code that's just going to run on the client, and then this public folder is going to contain the public assets that will be available that the application's going to use, and then in server, this is going to contain the JavaScript that's just going to run on the server. And so, if we take a look at some of this code, it's of course going to be a little bit more complicated than the code from the Leaderboard application. But really, still it's not that complicated. So we're looking at the two files in that server directory, the Bootstrap.js and the Publish.js, and you can see this Bootstrap.js has some basic data that it's bootstrapping with and then this Publish.js doesn't contain much code in here at all. Now I'm going to take a look at the other code we have, which is in the client directory. We have this Todos.js, which again, not a lot of code here. This definitely has more code than the previous one, looks like we're at about 323 lines of code, and then we have an HTML file that has all of our HTML in the templates in here. So, definitely more code, but that's a lot of functionality for that little amount of code in that application.
WordPlay
Okay, then I went ahead and did the same thing and I got the wordplay application, this example application, and I'm just going to start this by running Meteor inside the wordplay directory. And then let's go ahead and open up a browser window and we'll just check this out real quick. So, if I go to the Port on my localhost, Port 3000, I can type in my name and then click this ‘Play solo', and now I'm supposed to find words in here, and I don't really see many words, here's one, IN, so I can hit Submit and I get some points for that, and you can see how this works here. If you try to type in a letter, it'll show you where that letter is. It's got a decent amount of functionality, a countdown clock. So, you can play around with this example app; in fact, I'd encourage you to play around with all the example apps and just get a feel for how Meteor works. But, now let's take a look and see what's going on behind-the-scenes with these type of example applications and just with the Meteor app in general, but before we do that, we do need to talk a little bit more about that protocol that's being used between the client and server to communicate.
DDP
Meteor uses a protocol called DDP, or Distributed Data Protocol, to communicate between the clients and server. The protocol allows for doing two things; first, publishing and subscribing, and second, remote procedure calls. Once a DDP connection is established, the client can subscribe to some data on the server by sending a subscribe command and the server can publish changes to the clients as well. A client can also use DDP to make a remote procedure call to the server and get back a response from it. DDP is actually pretty easy to read, because it sends the data via EJSON, which is just a JSON implementation that supports a few more types. Let's take a look at this communication in action next.
DDP In Action
Okay, now I've got two browser windows open here with our Leaderboard application and we're going to use this to see exactly how this communication works between the different clients and the server, so we can see this real-time in action and see what data's being sent. Now, I do have to caution you; if you want to use WebSockets, (you'll notice that I don't have localhost here, I have 127.0.0.1, which is pretty much the same thing as localhost), there's a bit of a problem if you have IPV6 on your network, or your PC, which I do, it won't work unless you use the actual IPV4 address. So, localhost would normally go to the IPV6 version, which doesn't quite work right now with Meteor, so just make sure that you type in this if you want to use the WebSockets. Otherwise, it'll actually default to the XHR, or the SockJS implementation, which uses polling. So let's go ahead and open up our Chrome Developer Tools, I'm going to open this up on both windows, and I'm going to go to Network, and then from here we want to go to WebSockets. So this is actually a little bit difficult to read, so what I'm going to do is expand this, I'm going to click on the WebSockets, and then I'm going to reload this page, and you can see that it then opens up this Socket connection. I'm going to click on this and then click on Frames. And already you can see some data, let's go ahead and put this one back, and then let's do the same thing with this other side. We're just going to go over here and go to Network, and then WebSockets, and then let's reload this so we can see the initial connection happen, and then we're on the Frames here. So now, what we should see is any data that's coming across here. So, let's say I click on Grace Hopper, and then I click this ‘Give 5 points'. And you can see it updated here and I can do this again, and so now it's at 90, and I have to click here to see, and we can look at both sides of this. If you look on the one side, what ended up happening was that you can see that we sent some message data, we basically sent this method, players/update, and then some parameters, and it passed in some id here. And then, this basically did an update to that specific player, it didn't increment by 5 points. Then we got back a result and then we actually got back a message that said that that data had changed for that player, the score field had changed, and then it basically ended up doing an update here. Automatically, Meteor was able to detect that. Then we sent another message when we updated the score again and the same thing happened again, the same occurrence. So you can sort of read this data here, and you can see that this data is coming across from our client to the server. Now, if we look at the other side here where we're not sending data, we're just displaying the results, you can see something similar. The only difference here is that you're not seeing us actually send data, because we never changed anything here; you're just seeing these added and changed notifications that are coming across. Really these two changed ones are the ones that happened. We see that the score changed from 85 to 90, it went ahead and updated this once to 85, and then once to 90. And then if we did something on this side, we would of course see that the changes start from here. So, you can see that already updated there when I did the ‘Give 5 points', then you click on here, and you can see what's happened here. And there's also a little bit of data that's just being sent to keep this connection open, kind of like a ping here, you notice this every once in a while. But that's the basic way that this is all happening. So, hopefully this demystifies things a little bit here. Remember that we're using this Publish and Subscribe mechanism in order to make this happen, so both of these clients, when the page loads up, they're subscribing to this data here, which we'll talk about in the next module that's called a Collection. And then, whenever there's a change, the server is going to push this out. So, what's happening when we change the data is we're sending the server some information, we're making a method call that changes that data that says ‘increment this value by 5'. It, in turn, responds back by publishing out an updater, letting us know both of our clients that the data has changed, and then Meteor is able to use the Template Engine and the data that it got back in order to replace this portion of the HTML that has the score here for this person with the new HTML that represents the new score.
Up Next
Okay, by now you should have a pretty good understanding of how Meteor works and the basics of the structure of a Meteor application. You're probably ready to get started building a real application using Meteor, though. Don't worry. Up next, we'll be doing just that. In the next module, we'll start building our Protein Tracker application and learn some of the basics, like how to use collections and templates. Thanks for joining me, and take care.
Creating Our App
Introduction
Hi, this is John Sonmez from Pluralsight, and in this module we'll be creating our first real Meteor application. Now that we have a good understanding of what exactly Meteor is and how it works, it's time to build something with it. In this module, I'm going to take you through a step-by-step process of building a pretty simple Meteor application. And along the way, we'll learn about three important concepts in Meteor; templating, collections, and publishing. We'll learn how to apply each of these concepts as we use them to create our application. By the end of this module, you should be able to use these concepts to build your own simple Meteor application.
What we are Going to Build
If you've watched some of my other Pluralsight courses, you're probably familiar with the Protein Tracker application. I like to use this simple example because it's easy to understand and can be used to utilize some of the basic features of a platform like Meteor. The idea behind the Protein Tracker application is pretty simple. It's just an application that a user can use to track how much protein they consume in a day versus their goal. In our first version of this application, we'll only have a single user, and that user will be able to enter an amount that gets added to their total for the day. We'll also track a history of the entries that user makes. Later on, we'll extend this application to add more functionality, but for now this will help us to understand the basics of Meteor.
Breaking it Down
Before we jump right into coding the application, let's break things down a bit so we can understand how we are going to build our application. I always find it useful to break a seemingly large task into small steps to make it more clear what needs to be done and the effort it will take. Our first step will be to create a new Meteor project. We've already done this before so this step should be pretty easy. Then, we'll create the UI, but we'll create it as plain hard-coded HTML. We'll do this so that we don't end up trying to create the UI at the same time as we're trying to deal with templates and other parts of the application. Once we have our UI created, we'll figure out the best way to divide up the UI into parts that will serve as templates. We'll use some hard-coded values to fill in the values for these templates at first. Then, we'll use collections to actually represent the data that will populate the templates we created. We'll create a collection that will hold user data and another collection for the history of the user. Next, we'll add the ability to actually add protein using the Amount field and Add Protein button by hooking that button up to increment the total value in our collection of the user data. And finally, we'll remove a feature called auto-publishing that's useful for helping us quickly get our app running, but can be a big performance problem in a real production application.
Creating The Project
Okay, so the first thing we need to do is to create our project. Now this is pretty simple to do; all we have to do is run ‘meteor create' and then we'll name our project, and let's call this project ProteinTracker. So now you can see that we have our new app created, so we should be able to cd into ProteinTracker, and then if we just run meteor, it should set up Meteor server on our Port 3000 on the localhost, and we should be able to connect to this. So let's go ahead and just verify that this does work. So if we go to, and I'm going to put in that 127 address to make sure that I've got WebSockets working, then we can see we're at ‘Hello World!' and we've got our ‘Welcome to ProteinTracker' . And when we Click, it is getting that pressed. So now, we will need to create our actually user interface for our ProteinTracker application.
Creating The UI
Okay, so now that we have our project, we want to go ahead and create our user interface for our Protein Tracker application. So you can see in the directory where our ProteinTracker project was created we have the standard CSS, HTML, and JavaScript file that came with our basic ‘Hello World!' example. I'm just going to modify this HTML file and I'm going to open this up in Visual Studio, but you could of course use whatever editor that you want to. A lot of Meteor developers use something like Sublime, Text, or just Vim, but I do like the syntax and the color coding in Visual Studio, so that's what I'm going to use. Now you can see here in our current HTML for our application that we've got template already in place, but we're going to ignore the templates for now; in fact, we're just going to get rid of this template code. And what we're going to do is we're just going to put inside of our body, our actual page that we want to create here. And we're just going to make a very simple user interface; it's not going to be anything fancy. I'm just going to start off by creating an h1, and we'll just call this Protein Tracker. And then from here we're going to add some h2's for our mains parts here, the Total and the Goal. So we'll just say Total and then we're going to add a span here, so we'll just do a span and we'll make this contain our Total. So, for now let's just put inside this, a hard-coded value of a 100, and we'll fill this in later when we start to actually use Templates. Then, we'll go ahead and add another h2, so we'll say h2, Goal, and this is going to be pretty much the same thing so let's just copy this code and we'll make the goal be 200; we'll just hard code that value in there. And then let's make an h3 for Enter amount. And then we'll go ahead and do an Input and we'll give this one an id called amount, because we actually will need to get a value from this later on. So, let's make the type of this text, so this'll be where you can put in that text input for the amount and then we'll need another input for our button, so let's do an Input, and we'll give this one an id as well, addAmount. And then this type will be submit and we'll set the value here to Add Protein. Okay, then let's go ahead and add a section for our history. I'll go ahead and space this out so we can see where this is at. So we'll add an h2 here and we'll just say Last 5 Entries and then we can add some entries here. Let's just add a couple of sample entries. We're going to say 9/10/2013 11:37 AM and then we'll put a dash and then we'll put the actual value, let's say that they entered 20. Okay, so that looks pretty good, and now we're going to test this out in a minute and I just want go over what I'm doing and why I'm doing things this way. You notice I'm hard coding a lot of values here, I'm just creating the UI, I'm creating the mockup for this first because it's going to make things a lot simpler. If you start trying to create all the templates in here and then making the values update and building the UI that way, what ends up happening is things get a little bit more complicated. Now you don't have to follow this approach, you can of course just jump right in if you want to, but I do find that it's a little bit easier to get the user interface how I want it to look like first, or get all the elements there at first, and then go back and fill it in and make it actually work. And again, I'm not talking about styling here, this is not going to look great, but I am going to make sure that I have all the elements I need and then they're all in place and that this hard-coded data looks appropriate on the screen. You can always style it later, but you do want to get the layout and the format set up first.
Meteor Updating
So now if you happen to have that window open, that we had initially opened to view our Protein Tracker application while you're typing this in and saving your file, you would have noticed that the page was updating automatically. This is one cool feature about developing in Meteor is that, by default, Meteor will automatically push changes to the client. So when you change the HTML, it automatically changes here. So you can see what our user interface looks like, this looks pretty decent, we've got all the elements that we need here. We are getting an exception here because some of that JavaScript is not running. So we'll fix that in minute here, but I do want to show you this feature really quick. So let me go ahead and put this side-by-side, and then I'm just going to make a small change to this HTML, and then we'll watch as Meteor basically updates this page for us automatically. It's a pretty neat feature and it's really useful in development. So, let's say that we change this to 150, and then when I Save this, if you're looking at the Meteor server, you'll see that it basically reboots, or restarts, and then you can see that that value automatically changed here. So, this is a pretty neat feature that you can utilize to see how things are changing as you're changing them inside of your application. I use this all the time when I'm working in Meteor, I just keep a window open, and point it at my application.
Fixing The JavaScript
Okay, so now let's go ahead and fix those JavaScript errors real quick. I'm just going to take our .js file and drop it in here, and then what I'm going to do is I'm basically going to get rid of this code that was in here before. I'm going to leave this ‘if (Meteor.isClient)' and this ‘if (Meteor.isServer) so that we have this template here, but I'm just going to save this. And again, you'll notice it reloaded the page; that JavaScript error is gone at this point. And just to show you real quick, if we look at the console here, you can see that it says, ‘Meteor server restarted'; basically every time that we Save, it restarted the Meteor server.
Templates
If you've written JavaScript code to create snippets of HTML that you insert or remove from the DOM in your browser, you'll probably find Templates to be a much simpler way to accomplish the same task. Meteor has built-in support for templates and by default uses Handlebars, which is a templating engine we'll be using for our application. Here, you can see an example of what our code will look like when we add the templates. We simply take portions of HTML and put them in a template element with a name attribute to name the template. Then, we can use the double curly bracket syntax, that you can see here, to do things like insert a template at a specific point, loop through data, and insert data into the final rendered HTML. Using this approach, we can very clearly define the structure of our HTML and have our code fill in the blanks.
Creating The First Templates
Okay, so now that we've got our basic user interface, let's go ahead and chop this up into some templates. And we're basically going to have two main templates; you can divide things up however you want, whatever you find easiest, but I basically want to have a template for this section, which I'll call the userDetails, and then one for the history, which I'll call the userHistory, or the History template. So, what I'm going to do is I'm basically going to create a template inline here in this same HTML. Now you can divide your templates up into different files if you want to. Like I said, the file structure of the Meteor application is pretty flexible. We're going to keep things pretty simple, we're not really organize our file structure a lot here, because I want to have everything in the same files to make it easier for us to demonstrate and to see our code, but feel free to divide things up how you see best and to use that folder structure that we talked about earlier if you want some code to run on the client or just a server. You'll notice here that we can have one file where we can have our code for client and server by using this technique here, but you could also just use different folders, a client folder and a server folder, and put any code that you'd put here in your JavaScript or code that you'd put here in your JavaScript into the corresponding folder in a file. But let's go ahead and create our template here, so we're just going to do a template and we're going to name this userDetails. And then inside here, I'm just going to put all this code. And we're going to leave this hard coded at first, we're going to take this one step at a time. And then what we do here to use this template is that we can basically use that double curly brace syntax here, and I'm actually going to take the h1 out because this isn't really part of the actual user detail. So let's leave that there and then let's do this syntax and then we can do this greater-than sign to basically say call this template, insert this template here. So, we're going to give the template name, which is userDetails. Okay, so now at this point, we should have that template working, and if you bring up your browser, you should see that it should've reloaded and nothing really should've changed here. In fact, if we just want to test this out to make sure, we can Save, and we shouldn't get any errors. So, we're still good, our application is working. Now, let's create a template for this second part. So, we're just going to go down here and do a new template, and we're going to give a name for this one, we'll call this one history. And then inside here, we're just going to put this code. Okay, so now we have two templates and we want to use this second template, so we're just going to go ahead and add some code here to say, call this history template. Okay, now we'll Save and we want to verify that this is still working. Looks good, we don't see any error. And the next step will be to actually templatize this data in here.
Adding more Templating
Okay, so now let's go ahead and templatize the actual data here for the Total and Goal, the userDetails first. And if you can imagine, what we're going to eventually have is we're going to have a user object that's going to have some fields, a field for Total and one for Goal, and we're going to use that and save that data on that user. So, what we're actually going to do is we're going to use a special syntax in this templating language to allow us to utilize an instance of an object, in this case a user, and then to be able to get data from it. So what we're going to do is we're going to say, ‘#with user', and that's going to make it so that everything inside here is going to be in the context of this user. So, it'd be like if you said user.Total or user.Goal when we add further templates inside here. We also have to end this, so we can tell it where that this with basically ends, and we do this with just a /with. So now, everything is in the context of user here and we're going to have, of course, a total and then a goal. So what we'll want to do is we'll want to basically have a user object that will have a total and a goal on it, and then we'll get the data from there to populate this template. Now eventually we'll make this come from a database, from our MongoDB, but for now we're just going to hard code this with some JavaScript to create this initial structure. Again, I'm working step-by-step; I created a UI first, then we went to the template, then I'm going to templatize this data with some hard-coded JavaScript. And by doing that approach, I'm keeping things as simple as possible. And we're going to do the same thing with our history here. Now with history, what we're going to do is we're actually going to use an each to loop through this, because there's actually going to be multiple history items. With our user, there's just going to be one user right now; we're not going to have a list of users. So, by doing this each in our template, so we'll do #each, we can do historyItem. It's basically like a for loop in another programming language, and so what we're going to do here is we'll end this, just like we did with the other one, /each, and then what will happen is that we're going to pass into our template some history. And then for each historyItem in that history, we're going to pass it basically a list of history items. It's going to perform what's inside of here, so it's going to create multiple rows, multiple paragraphs in here that will have this format. And then what we're going to do here is we're going to have this be the date and then this part will be the amount or the value, we'll just call it value in this case. So we want to create a structure in JavaScript that will mirror this as well. So, the next thing we're going to do is create our user, we're going to create our history items, and then we're going to put some dummy values in here and make sure that this will work.
Populating User Data Template
Okay, so now we've got everything templated out, but if we want to populate these templates, how are we going to do that? Well in Meteor, we can use what's called a helper for a template and we can basically set that up to populate that template. This is pretty easy to do, but the syntax is a little bit strange. So, if you've followed along at this point and have saved your file, you should see that we actually don't have most of our UI displaying. And that's because we have a bunch of errors here, we're not actually filling in our templates. So what we're going to do now is we're going to go into our JavaScript file and I'm going to leave this open just so you can see our changes happing here. And what we're going to do is we're going to put some code in the client-side. Now, like I said, we could create separate folders and have a client folder and just put our code in there, but just to have everything in one place, for now we're going to use this format of having this isClient or isServer. And remember, this code is going to run on the client and the server, it's just going to run the different section depending on whether it's running on the client or server. So, what we're going to do first is let's do the simple thing, which is to populate the userDetails. So, I'm just going to start off by creating this Template.userDetails.helpers. And then inside here, I'm going to pass an object, so this method is going to exist off of userDetails, which is our template name, right, we called this userDetails. And then we do helpers, and then here, we're going to pass an object. So let's go ahead and pass this object, and this object is basically going to have a function or a property on here that will be a function that will return our data. There's a couple of different ways to set this up, but this is a pretty easy way. So, basically this userDetails template is going to need to get user. So the way it's going to do that is it's going to read a user property off of this helper object and what we can do with this is we can return a function. So, this might be a little bit confusing, but bear with me here. We're going to create this user property on here and then we're going to say that it is actually equal to a function, and let's define this function. So, we'll go ahead and put in this function, I'm just going to create a variable called user, and I'm going to create an object here that is going to have a total, and the total will be, let's do 123, so we'll know that this is working, and then the goal will be let's say 251. Then I'm just going to return this user. So, now I'm going to Save this and you can see immediately that we're getting our values and that's because we're filling in the data for that template. So just to go over this real quick here, the HTML right, we have our template, it's named userDetails. We have this with user, so that's basically the property that we're going to be using on our template, and then we have a total and a goal. This ‘with' is telling us to basically use the sub-properties of this user. So now in our JavaScript, we've defined this helper for userDetails that's basically just an object, and this user maps to this #with user here. So now, because this user object that we've created has a total and a goal, it's going to fill in those values in that template. And like I said, there are some other ways to set this up, this structure in here, but I'm setting this up so that it'll be easy for us to fill this in with some actual code later, because we're going to use a function to build a return data from the database.
Populating History Template
Okay, so our next is to get this other template working. So we have our history, it should display the ‘Last 5 Entries'. Remember, we're actually looping through history items here, so this each is going to be for whatever we end up returning back, which will, in our case, it'll be an array of historyItems. And then we're going to get the properties from here. It's going to work very similar to how we had user, except user was just a single object, here this will be an array of objects. So we can do the same thing, we're just going to go in here and then we're going to say Template. and remember the name of this template is history, and then we're going to say helpers, and then we're going to pass into here an object. And on this object, we're going to have a property called historyItem and this is going to return a function, and this function will have our historyItems. So, I'm going to go ahead and just copy this to save us a bit of time here. And all I'm doing is I'm just creating an array here using literal values. Let me go ahead and format this, make things a little bit easier to read. And so you can see, inside this array I just have a bunch of anonymous objects that have a date and a value. And so with that, we should be able to populate this data. So we're going just return back that array, we're just going to say ‘return historyItems'. And then when I Save this, you should see this data populate, and you can see it's populating right there. So again, real quick, same exact thing here. We have our template, it's named history, so that means that we're going to be doing Template.history. Then we have our helpers, and then we have historyItem here, we're doing an each on historyItem. So, we have a property here called historyItem, it's returning a function, this function is setting up the data, and then returning that data, pretty simple.
Collections
One central concept in Meteor is Collections. Collections represent data that is used in our Meteor application. If you come from the relational database world, you might think of Collections in a similar way as you think of tables. In Meteor, a Collection is a data structure that Meteor knows how to synchronize between the client and server. In our application, we'll be creating a collection of users and a collection of history items for a user. We'll store that data in our MongoDB instance, but we'll be able to access that collection data from both the server and the client. Meteor handles collection data in a special way to make it very easy for us to do this.
Adding A User Collection
Okay, at this point we have hard-coded data that we're returning back to populate our templates, but we don't want to just return hard-coded data. We want to use some real data, we want to get the data from a database, eventually we want to make it so the user can enter the data or manipulate the data themselves, but the next step is to push this down one layer deeper. So we're still going to be somewhat hard coding the data, but we're going to be using collections so that we're going to be getting this data from the database. And again, I like to take this approach where I'm pushing the data down each layer instead of starting at the beginning trying to get everything working together. So, what we're going to do is we're going to start off by creating a collection for our users and we're just going to have one user for now, but eventually we'll make it so this application could use multiple users. So we're going to create a variable here and we're going to do this at the global scope and this is going to be necessary in order to build accesses from multiple places. This is really the convention that you should use when you're creating collections in Meteor. Notice that this is outside the isClient and the isServer, so this is going to run on the client and the server, which you need to do because it needs to be initialized on both sides. So we're going to say new Meteor.Collection, and then we're going to name this collection, and we're just going to call this one users. So now we have a collection to work with, and again, this is going to be represented in the database as a MongoDB collection as some users documents. So now that we have this collection, we're going to want to populate this collection with some initial data. So what I'm going to do is I'm basically going to check to see when our Meteor Server starts, when our Meteor code starts on the server-side. I'm going to say if(Users.find), this is how we search a collection, it's just a MongoDB command basically for finding some data in the database. So, we're going to say (Users.find().count() === 0). So, if there's no users currently in our database, then let's go ahead and add some dummy data, we'll add a user. So we'll just do Users.insert, and again I'm executing a MongoDB command when I'm doing this insert. I'm just doing an insert like you would with MongoDB. If you're not familiar with MongoDB, that's okay; you can do some research later on if you're going to use Meteor a lot, you're probably going to want to learn some about that database in order to really maximize your usage of Meteor. But you can just follow along for now and it's pretty straightforward. So, I'm going to insert an object that has a total of let's say 120, and a goal of 200. I'll go ahead and Save this and we'll make sure we add our semicolon there. Oaky, so now we'll definitely have some data in our database. I'm going to go ahead and make it so we can see what's going on here. You can see our old data is still showing up, even after I've saved this, because we haven't changed this helper, but now what I can do is instead of returning this hard-coded user inside of this function, what I can do is I can search the MongoDB essentially. I can basically get out of our user's collection, the first user. So I'm going to do this return Users.findOne, that's going to give us the very first user. We're only going to have one in there right now, we're just going to count on there only being one. I'm going to save this, and nothing's happened at this point. Occasionally you have to go and check over on your server and see if it's stopped. Sometimes it seems like maybe it's just a Windows version, but there is a problem where it will stop on you, so you might have to restart your server, but that's pretty easy. So I've went ahead and restarted this, and now you can see that this actually updated, the Total is 120, the Goal is 200. And that object exists inside of the client. So, for example, I can do Users.find, let's say find or findOne. And if I execute this, I'm going to get back the result, which is going to be that user. Notice that it's given an id automatically. We're going to use this a little bit later on, but we have access to this. We could even insert users here, or insert data directly. This is a useful way to work with your Meteor application is you can basically insert your data and try things out because you can manipulate that MongoDB directly from the client using that minimongo API we talked about earlier.
Adding A History Collection
Okay, so now let's go ahead and do the same thing with history. We're just going to create our collection called History = new Meteor.Collection, and we'll call this history. And then we're going to insert some dummy data just like we did before. So, we'll say if, and this time we're going to look for our history. So, instead of Users.find, we're going to say History, and then inside here, we can go ahead and do an insert, so we can say History.insert and then we can go ahead and insert some data. So we want to have a value, so let's just make the value say 50, and then we want a date, which we're going to do a new Date().toTimeString, and then we'll go ahead and add couple of these inserts. So we can make a value 30 and let's say 10. And then what we want to do here is just replace this code. So, now we can just do return History.find, which will go ahead and return back all of our history, if I save this. Okay, so now you can see that we have our data, we have our three items showing up here. And so now at this point, we do have hard-coded data still, but we are getting our data using the collections API and we are just hard coding this into our database at startup. So, now we've pushed things all the way down and we're ready to take things to the next level and actually make our Add Protein button here work.
Making add Protein Work
Okay, so now let's get this Add Protein button working. In order to do this, we are going to set up an event handler for our template. Remember that if we look at our HTML, this button is inside this userDetails template. So we need some way to hook up to this to tell our Meteor application to do something when someone clicks this button. So we're going to go into our JavaScript here and we're going to create some more client JavaScript. And we're just going to do Template.userDetails, so we'll be operating on our userDetails template. And then events, and here we can specify an object that will contain our basic event handlers. So the way that this works, it's a little bit strange, but you'll get used to it, is we define the event name here as part of the property name and then the selector for this. So, in our case, remember we had called this addAmount, that's our ID, we could use any kind of selector, a CSS selector that you want to use. In this case, we have our id, so we're going to do addAmount, and then we're going to say for this, here's the function, and we're going to use e because that's event that will be passed into that function when you click, and then we're going to do e.preventDefault, first of all. This is just going to make sure that the default wiring of that button click doesn't happen, we're going to prevent the browser from doing whatever the default action would be, which would be to submit. And then we're going to go ahead and get our amount, so we're just going to do var amount = and we're going do a parsInt because we want to get this as an integer. And we're just going to use JQuery here, because we want to get the amount, this is just the simplest way for us to get that amount, and we'll do val here. So that's just going to give us the value that's in this amount box here and then we'll store that end amount as an integer. Next, what we want to do is we want to update our user's total. Remember we have that dummy user we've inserted. So, let's do Users.update and then we're actually going to do (this._id), because we need to specify the id of the thing that we're going to update in our Users collection. And we can get that just by using this (this._id) and then we're going to actually do an increment, so we can specify that by doing this $inc and then we're going to increment the total by the amount. Now the syntax is a little bit confusing, but this is the way that you can do this update. If you take a look at the MongoDB documentation, or if you're already familiar with MongoDB, this might not be as foreign, but we're essentially executing MongoDB command here to basically do an update on our user that has this._id and we're going to do the increment operation on the total by the amount. So, that will go ahead and update that total. Let's go ahead and Save here and let's give this a try. So, if I put in let's say 12 and click Add Protein, you can see its updating. Let open up another window just to see if this works. So, I've got two instances open and it doesn't matter which one I update on, they both update. So, we have that publish/subscribe model happening here, where it's automatically saving the data between the two.
Finishing add Protein
Now we're not quite done yet, right, so we're updating the User, but we need to insert a historyItem. So let's do History.insert and we're going to add a historyItem every time, so we're going to say value is equal to amount and then we're going to set the date equal to new Date().toTimeString. And then we're actually going to do one last thing, which we're not going to utilize at this point, but we want to track the userId because we want to know what user actually did this, or added an amount. We only have one user in our system right now, but we need to make sure our data is complete, because at some point if we have multiple users, we need to know which history belongs to which user. So we're just going to put in the this._id to keep track of that as well. Now I'll go ahead and Save this. And now if we enter an amount, you can see that it's showing up here. The sort order looks a little bit wrong though, so let's go ahead and fix that, and we probably only want the ‘Last 5 Entries'. So, the way that we can do that is we can just change this find on our history and we're going to add a couple of parameters here. This first object is filter criteria, we're not filtering based on anything. Next, we're going to set up our sort and we're going to sort on date and we're going to do -1 to say what direction that we're sorting. And then we're going to say what our limit is, we're going to say the limit is 5, that's going to make sure we only get 5 entries. So I went ahead and Saved this and now you can see that there's just 5 entries and our newest entries are appearing on top.
Publishing
Up until this point, we've been using a feature called auto-publish that has made the collections we have on the server and client's synchronize with each other automatically. If we change some data on the server, the client would instantly see the changes and vice-versa. Meteor does this by using a publish and subscribe model that we talked about earlier, and using auto-publish, it automatically adds some logic to our collections to publish themselves in their entirety when they change. But, while this auto-publishing may be convenient, because we always have all the data we need accessible from our client, it isn't very efficient and can represent a security problem. We don't necessarily want to sync our entire MongoDB with all its data to every client connected to our application. Instead, we can turn off auto-publish and manually decide what collection data gets published and manually subscribe to that data in our client's. This is a bit more work, but it gives us much more control over our data.
Turning off AutoPublish
So up to this point, we've been auto-publishing our data. So as we had mentioned before, we've basically been taking our entire MongoDB and copying it to each client. That's why we could see all the data from each client; whenever we change anything on one, it showed up on the others. Now we still want this functionality, but we want to have control over this data. Right now it's not a big deal, we don't have much data in our database, but when we have a lot of data and we have different user's data, we will care more about this, especially if you can imagine, we don't want to necessarily send all of the history details for a particular user to every other user. So the way that we're going to do this is we're going to turn off auto-publish and we can do this in our application by doing ‘meteor remove autopublish', so now it says autopublish: removed. So now if I start up Meteor, you'll notice that our application is not quite going to work. In fact, we're missing all of our data here, our templates are not working because we don't have any data to operate on. If we type in Users.find, we get back our collection, but let's do a .count on it, and it actually has nothing in it. Same thing if we do History.find().count, we've got no historyItems. So we need to manually set up our publishing and subscribing for the data that we want.
Manually Publishing
Now this isn't very difficult to do; all we have to do is publish our data manually at this point, which is really simple to do. We're going to publish from the server. So what we're going to do is, inside of our isServer code, we're going to set up our publishing. So, I'm just going to go ahead and put some code right in here and we're just going to do Meteor.publish and we can give this a name of the data that we're going to publish, we're going to call this allUsers. And then we give a function that actually is going to do the publishing. So, in this case, we're just going to return Users.find, that'll be all of our users. Okay, and we're going to do the same thing for our history; I'm just going to copy and paste this and modify this to be allHistory, and we could actually publish just a portion of the history. Like I said before, we might want to take in a userId and just publish the history for a particular user, but for now we're just going to publish it all, so we're just going to do History.find. So all of that data is going to be synced over, and we need to subscribe to this data. So, let's go back to our client-side and then we're just going to set up some subscriptions. So on the client, we just want to say Meteor.subscribe and then we're going to subscribe to both of those channels, so we had one called allUsers and I'll go ahead and Save. And then we'll do Meteor.subscribe and this one is called allHistory and I'll Save. Now we're not seeing our data update because Meteor is not running, so let me go ahead and run Meteor real quick. And now you can see all our data is back; we are manually publishing and subscribing to this data. And so if we add entries, our functionality still works, but this is much better. Instead of passing all that data back, we are basically passing back just the data we want. In our case, it's still all the data because we have set this up to manually do that, but we're not using auto-publish anymore, and this is going to be critical, like I said, if you can imagine, if you have a really big database, you have a lot of data, you don't want to send all that data to the client, especially if there's sensitive data in there.
Up Next
Congratulations, we've created our first real application using Meteor. Hopefully, you found this whole experience wasn't very hard at all. Meteor does a large amount of work for us and helps us to blur the lines between client-code and server-code, which I find to be a bit of a relief, but we aren't done yet. We've only really scratched the surface of what Meteor can do. Up next, we'll expand our Protein Tracker application as we add a few more features, and along the way, learn about some more important concepts in Meteor. Thanks for joining me and take care.
Extending Our App
Introduction
Hi, this is John Sonmez from Pluralsight and in this module we'll be extending our Protein Tracker app in Meteor to add some additional capabilities as we further our knowledge of the Meteor platform. So far, our app is pretty neat, but it isn't really that impressive. We can add protein and see the amounts updated in real time on multiple browsers, but we're missing the ability for a user to log into the application and we haven't really thought much about security. In this module, I'll take you through the process of building out our application with a bit more functionality and we'll hit on more of the key concepts in Meteor, like the built-in account support, Sessions, Computations, Latency support, and Meteor Server Methods. By the end of this module, you should have all the tools you need to build a real Meteor application and have a good idea of the capabilities the Meteor platform provides.
What we are Going to Build
From the outside perspective, we aren't going to be doing that many changes to our application. The big cosmetic change we'll be making is to add a Login button, where a user can log into the application, but don't let the small amount of UI changes fool you. We'll be doing a lot of work under the covers as we explore more of the capabilities of the Meteor platform. For our Protein Tracking application, our main goal will be to be able to support different users and keep their data separate. We'll also make it so that those users can sign in using their Google credentials. We'll also add support for keeping the last amount entered box populated even after the app reloads and add a bit of security to make sure a malicious user can't just type commands into the JavaScript console in Chrome to do whatever they want with our application.
Breaking it Down
Let's break down the steps of what we're going to do in this module as we build more features onto our application and explore more of Meteor. First, we'll add the ability to log into the application. This is actually pretty easy to do by itself; Meteor gives us a really easy way to add login capabilities and even use Google Authentication without us having to do hardly anything. Then, we'll need to switch our user information to a new collection we'll call protein data. Before we were managing the one user we had ourselves, but since we'll be relying on Meteor's Accounts framework for our users, we'll want to repurpose our user's collection to just contain protein data for that user. Once we have these two things done, we'll have the ability for multiple users to log into our application and be able to store their data separately. Next, we'll tackle the problem of saving the amount that was entered last so that we can repopulate the field when the app is reloaded by the server or user logs in or out. We'll do that by using Meteor's Session capabilities. Then, we'll add some debugging support for logins, as we explore the powerful Computations capability in Meteor that allows us to write code that automatically re-runs when data changes. And up until this point, we've been executing most of our logic on the client itself. This can be insecure and poses a potential problem if someone enters bad data. We'll use Meteor Server methods to move the actual adding of protein to the server where it probably belongs anyway. Then, we'll take a quick look at Latency Support as we add some experimental data to simulate how we could handle real latency situations in an application. And finally, we'll add another button to our application to subtract some protein and we'll use permissions to add some security around it to prevent user totals from going negative.
Adding Users
One of the most impressive things I've seen about Meteor so far is how easy it is to add the ability for users to log in to an application. This is such a basic requirement of most applications, yet I find myself time and time again scratching my head, trying to figure out how best to add user account support to a new application. With Meteor, it's very easy; all we have to do is add one package for the user interface support, which will give us the ability to add a functioning Login button to our HTML using a template and an authentication package, which we can use to add support for this standard user name and password or authentication. Or better yet, get automatic support for all of the third party authentication mechanisms you see here. In our app, I'll be showing you how to add support for logging in with a Google account, but you can easily support a different third-party authentication mechanism, like Twitter or Facebook, just by using a different package.
Adding Accounts Support
The first thing that we're going to do to add our login support is we're going to add two packages to our Meteor application. I've got a command-line console open here and you can see I've done a ‘meteor list' command inside our ProteinTracker app, and here you can see a couple of the packages that we're going to add. First we're going to add this accounts-ui, which is simple templates to add login widgets to an app, which is what we're going to want, and then we're going to use accounts-google, which will give us login service for Google accounts. So, in order to do this, remember we're just going to do ‘meteor add' and we can just say accounts-ui. And you can see that it went ahead and added that to our app, and then we're going to do ‘meteor add accounts-Google', and now that's added to our application as well. So now we have the capabilities, we just have to utilize them.
Fixing A Conflict
Okay, now when you restart your application, we're going to go ahead and do that here, we're going to just say ‘meteor', you'll probably see an error and this error basically says that users/insert is already defined, a method named users/insert. The problem here is that actually the accounts package ends up using the user's collection, it has its own user's collection. So, this is actually pretty easy to fix. If we just go into our code here, what we can do for now is we can change the name of this collection; instead of users, we're just going to call this protein_data and we're actually going to convert this over later, but for now we're just going to change the name. I went ahead and saved this and you can see as soon as I saved this, it said ‘Meteor server restarted' and so we should be up and running. We can test this out by opening up a new browser window and just going to our application, and you can see our application is here and it does work. So, now we need to actually add a Login button, so we're just going to add it right here.
Adding The Login Button
Okay, are you ready to add a Login button to our application? I've got our side-by-side window here, so we can see what's happening when we do this. Now this is a little bit difficult so make sure you stay with me here. Put down your IPad and pay attention, unless you're watching the video on the IPad. So, what we're going to do is we're just going to put in here two curly braces, we're going to type in loginButtons, and then end it with two curly braces, and then save our file. And there you go, we have the Login button. Now we still have to configure this and one really neat thing about Meteor is that it allows us to configure this with this button. So this will actually turn into a Login button once our configuration is created for logging in through Google, but before we do that, let's do one other thing. Let's make it so that this data does not show up unless user's logged in. So the way that we're going to do that is we're just going to use our templating engine and we're just going to do #if and we're going to use this current user. This is a variable that is set if there is a user logged in. So, if there's not a user logged in, it's not going to be set so we can just do a /if here, and let's go ahead and format this file. (Typing) And I'm just going to go ahead and indent that here. So, now I'm going to go ahead and Save this. And now you can see that everything disappears because we're not logged in, but once we login, this should all appear again. So now the next step is that we're going to configure this with Google.
Adding Google Authentication
So this is actually pretty easy to do, all we have to do is click this button and then it'll give us some instructions here and I'm just going to expand this out so we can take a look at these instructions. Basically, we need to have a Google Client ID. I already have one, and I already have some of this set up, so you can set this up through the Google API's Console. You can see here that it says if it's necessary, you'll Create a Project and then you go to the "API Access" tab on the left and then you create another Client ID and then Choose "Web application" as a type, and it gives you the steps here. We'll go ahead and take a look here. So I'm just going to go to this apis/console. And then here you can see that I have API Access, we'll click here. And I've already created this Client ID for web applications, but I'm going to go ahead and delete this one and we'll just create a new one here. And what we're going to do is just do a Create another Client ID, and then we're going to follow our instructions here. So, it says to set the Authorized Redirect URIs and then it gives us what we need to set this to on our local host, so I'm just going to go ahead and go in here, it's web application type, I'm going to do more options, and then let's copy this Authorized Redirect URIs to here. And then we have this Authorized JavaScript Origins. And we can Paste this into here. Now the nice thing about this is that you don't really have to know how OAuth and all of this is working, which it can be kind of complicated, especially if you're just trying to set up an app and you just want authentication to work, you don't have to be an expert in security and OAuth in order to do this, you can just follow the steps and put that in. So I really like how they did this, they made it really simple, you can just set this up very easily. So I'm just going to go ahead and click this ‘Create client ID'. And now we can go ahead and refresh this to make sure that we're getting the updated version. So now you can see I have this Client ID for web applications, and what it's asking for here is just the Client ID and then the Client secret. So I'm just going to take my Client ID, Copy this, and Paste it in here. And then make sure you get this Client secret and we're just going to Paste that in here as well. So now I can just click Save Configuration, and now you see that button changes to this nice ‘Sign in with Google'. So now I can actually click this and I'm signed in as my Google account. It says the app would like to view your email address, view basic information about your account, that sounds okay, it's not trying to do anything too nasty, so I'm going to click Accept. And now you can see it even shows my Username, I'm signed in, and I have this Sign Out button, and our UI is displaying again. I can Sign Out just as easy, everything disappears, Sign back in.
Renaming to Protein Data
Okay, so now the next thing that we're going to want to do is we're going to want to convert this over so that we're actually associating our Google account, or our logged-in account, with the data that we're going to be displaying. Right now, our application just has one user. The user's not related to the logged-in user and it's just displaying the data for that user. So, for example, if I log in with another account, which I'll show you in a little bit here, it would have this same data, it would update that data, but we don't want that. We want our data for our Protein Tracker application to actually be associated with the user. So, we're actually going to get rid of our user's collection, and to be more precise, we're going to be repurposing this. So, what we're going to do is we're going to call this ProteinData instead, we've already changed the collection name here, but let's go ahead and change this everywhere else. And this is just going to represent the data portion; it's not going to represent the user itself since we're using that account's API for the user itself, but this is going to be the data associated with this user. So we're basically going to have for every user account, an instance of this ProteinData inside this collection that's going to be tied to that user account. So, let's go ahead and go through here and I'm just going to search for Users, and what we want to do is we what to replace that with ProteinData. We want to find all the instances here and let's call this allProteinData. And then, we're not going to need any of this code to run at server startup, because we're going to not need the fake data anymore, so I'm just going to go ahead and get rid of this here and then this other block as well. Now let's go ahead and fix this subscribe also; instead of allUsers, we call this allProteinData. So we're going to make sure that we subscribe to the correct channel.
Adding new Protein Data
Okay, so now what we've done so far is just changed the name, but we haven't actually associated the ProteinData with the user. This is still going to be ProteinData for just one user, for all users it would be shared. So, the way that we're going to do this is we're going to add another field to our ProteinData, which is going to be the user ID, and we're going to filter it based on that. So first thing we're going to do is in our publish, with this allProteinData, we're going to actually change this so that we're going to be publishing allProteinData for a particular user. And so what we can do is we can change this so that inside of our find, we're going to use this.userId. So, we're going to add a filter, the first parameter to find is always the filter. And we can say what field we what to filter on, so userId, and we're going to say this.userId. Now, what will happen is Meteor assigns this.userId to the current user that's logged in. So, when we do this, what's going to happen is it's only going to publish the data for the current logged-in user to that particular client. So you might have different clients that have different user IDs that are going to get different published data to them. And in fact, if we look at our page, you can see as soon as I did that, our interface for the actual user information disappeared. We still have this history part because we're publishing all the history data, but the rest of it disappeared because we don't have a userId associated with any of this data that's in the database at this point. And while we're at it, we'll do the same thing with our History. So let's say that the History needs to be filtered on userId equals this.userId. Again, when I Save this, and then we look at our application, you can see that disappears as well because we now don't have any history data, because nothing is going to match that query. Okay, so what we're going to need to do is to create a new protein_data whenever we don't have one for a user already logged in. So, we're logged in as a user, we run this query here, we're basically subscribing to what's being published. We notice there's nothing, so this means that we need to create protein_data for that user and then associate that protein_data with a user. So what we're going to do is we're going to look at our helper for the userDetails template, and inside here you can see it's doing ProteinData.findOne. Well, there isn't one. So, what are we going to do in the case where there isn't one? Let's go ahead and change this a bit, so let's say var data = ProteinData.findOne. So look for the one, there should only be one associated with a particular user. In this case, there's always going to be none. So, if not data, so if there's nothing, then we want to create some new data, so let's just say data =, then we can just create a JavaScript object right here, we can just say userId =, and we're going to use this Meteor.userId method. And what this will do is it'll give us the current user ID. So, this will allow us to basically assign this field to whatever the logged-in user's userId is. Then we can set the total and we're going to set this equal to 0, and let's just set the goal to a default value of 200. We're not going to add the capability to change the goal in this particular course, but you might add that functionality as an exercise later on, on your own. So now we'll have some data, but we need to insert that data into our MongoDB, or into our collection. So, what we can do here is now we can just say ProteinData.insert and then we're just going to insert that data. We'll go ahead and save this. So now, what's going to happen is if we didn't have any data to begin with, we're going to create some new blank data, we're going to associate it with the proper userId of the logged-in user, and then we're going to Save that. So then we can go ahead and return data, and this will either return the data that it got when it got it from the subscription or it will return this new one that we created. So now I'm going to go ahead and Save this, and now if we look at our application, as soon as I saved that, it updated and we have a Total of 0 and a Goal of 200.
Associating History with A User
Now we're not done quite yet because we still have to make sure that the History data is going to be associated properly with our user. So, for example, if we use our application right now and I just ‘Add Protein', it's going to add to the Total, but it's not going to add any history because we're doing that filter on the history, it's not associated with the userId. So, this is actually pretty easy as well. We don't even have to really change this part in our update because we're updating based on this._id, and if you're curious how this works, what's happening is with our ‘with here' in our template, this #with user, we're actually using the ID inside there. This is the context in which this is operating. So, when we have the click on here on this event that this is able to get the ID from there. So that's going to update fine, that's okay because that is the actual ProteinData object, but our history, right now we're inserting an amount, we're inserting a date, that all seems good, but our userId was this._id because we're using the ID of the user when we had the users collection, but we don't want to use that anymore. What we want to do instead is we want to use the ID of the actual user itself. Now we could technically use this._id and do the filtering on that, but that makes things a lot more complicated. We should just have it all working off of this single key, just the actual userId for Meteor. So, the way that we can do that is we can just change this, instead of doing this _id, we can use that userId again. So now I'm going to go ahead and Save this, and we'll go ahead and go to our application now and let's add some protein. And now you can see that we are getting the history, it is updating. Now there is one small issue here still with the history itself. We are doing our filtering here. Now we don't have to change this if we don't want to, but if you think about it, at least the limit part, like the sort makes sense to do on the client, but this limiting part we should probably be doing on the server because what if we have a 1000 history items. We're only displaying five, so why send them all to the client. So you've got to think about these kind of things when you're building the application. So let's go down here and let's change this just a little bit. What we're going to do is we have our filter and then we're not actually going to add a sort, so we're going to leave that one blank, but we do want to add a limit. And so let's test this out just a little bit here and see if there's any more issues. Okay, so remember I said that we didn't have to do the sort on the server side? I sort of lied a little bit; it depends on what data you're dealing with and how you're dealing with this data. Since we're using a limit here, what's happening is we're getting randomly five items from the server, it's limiting on that, but it didn't sort them ahead of time. So we're sorting what we got from the server, which is probably not what we want. So, let's just fix this as well. What we're going to do is we're going to add a sort on our actual server as well, so we're just going to add this sort capability here, and now we should get our data sorted properly. And so now if I enter some data, let's enter let's say a 2, we're seeing that show up at the top. So we've got the sort in both places here because it does make sense to sort it on the client, but it also makes sense to sort it before we limit it on the server as well.
Testing Multiple Users
Okay, so we're going to call this the ultimate demo. At this point, you may be doubting that we're actually storing protein data for different users. So what I've done here is I've opened up a few browser Windows, and you'll notice this little icon indicates this is my wife's Google account and this is my Google account. So, what I'm going to do is I'm going to ‘Sign in' with her account to the application, and I've actually got a duplicate window here so we can see the real-time updating as well, and we're going to see if it tracks the protein separately for the two users. So let's go ahead and sign in here, we'll go ahead and Accept that, and now you can see that it updated on the other side, she's got a Total of 0 and a Goal of 200. I'm going to click 1 and you can see these updated, but this one didn't. And if I change some data here, let's change that to a 5, you can see mine updates, but hers does not. You don't see any of the history updating or anything like that. And let's just do a couple more here, we'll Add 23, and you can see that both of these are updating, but mine is not. So, we actually have multiple users, really wasn't that hard to do. If you tried to implement this yourself in some other framework or just using regular JavaScript libraries and implementing your OAuth and all of that, it could take you quite some time. So I really like how easy this is in Meteor. One of the key things that prevents a lot of people from creating a new application is trying to figure out the login. I've actually started up a lot of different ideas and got stuck at the Login part because I just spent a lot of time, or wasted a lot of time doing that. So, pretty neat that we can do this so easily; I especially like the integration with Google right off the bat here, pretty nice to be able to just launch a brand new application and have Google Sign-in already.
Sessions
Sessions in Meteor operate a little differently than what you might be used to if you use Sessions in an ASP.NET or Java web application. Sessions in Meteor aren't designed to persist data during a single use of a browser, but instead are designed to persist data globally during the use of a Meteor application loaded on a single page. This means if you navigate to a different page, your session data is lost, but it also means that if Meteor updates the HTML or code of your application without reloading the entire page, you can still use the session data. Using Sessions, we can create applications that are able to have their code in UI completely changed while retaining the user's state information and data. This allows us to do a live upgrade of a Meteor application while the user is logged in, pretty cool. Sessions in Meteor are also reactive. This means that if we use data from a session in a template and the session data changes, the UI will automatically update to reflect the change, also pretty cool.
Adding Session Support
Okay, so right now in our application, if I were to type in a value, let's say 10 and click Add Protein, we see the 10 stays here, but if I were to Sign Out and then Sign back in, then we end up losing that value. I don't have the 10 anymore, and if we actually change the data in our application, so let's say I've got my 10 here and I'm going to click Add Protein, and then I'm going to go ahead and make a change, let's just change this HTML, we're going to say ‘Protein Tracker!' and we'll Save this. You'll notice when this updates, this box disappears. So, using Session, we can actually fix this problem by basically storing this data into Session and then Session still exists even though the rest of our application might update, this box basically would update, so we can persist that value and then just repopulate it. Now there's a couple of other ways to do this as well, but I'm just going to use this as an example, because this is one of the useful things about Session. Another useful thing about Session is that it is global so you can use this to have some global data through different parts of your application. It can be difficult sometimes to pass data around in JavaScript and different pieces of JavaScript code, but Session is a place where you can think that you're always going to have some variables or some data that you can access. So let's go ahead and go into our app, and what we're going to do here is when we actually update this data, when we update the amount, we're going to go ahead and store our last amount inside of our Session. And you can probably guess how to do this. All we have to do is just do Session set and then the key and then the actual value that we want to set. So in our case, we're just going to do Session.set and let's go ahead and call this lastAmount and then we're going to set the value equal to the amount. So now we are storing the session data, but we want to be able to restore the value in that field. So, let's go into our HTML here and then what we're going to do is we're going to make it so that this input box value is set to the last amount and we're using our templating language here, so we're just going to say lastAmount. Now we need to provide this value, it's not going to automatically get this from Session for us, but the problem is we're using this ‘with' here. So one easy solution is just to take this ‘with' and we're going to end it here and then we're going to start another with user right afterwards. And then we're going to make sure that our amount is outside of it, so that we don't have a conflict with the user property here. If we look at our code, it'll make a little bit more sense. We do have do have to have our addAmount in the context of user because we're using that thisId like I'd shown you a little bit earlier. So, this might seem a little bit weird, but it'll make a little bit more sense when we look at this JavaScript. So, remember that we have this user on here, and this user is going to be populated by this, or this is going to be used to populate this, and then that's where we're getting the total in Goal, it's kind of like user.Total or user.Goal. Same thing here, with our button, we're using the context of user in order to be able to get --- this when we click the button. So we have this click addAmount, that's where the this._id is coming in. So we need to make sure that these have the user, but this one we need to make sure doesn't have the user so that we can do something here, so instead of just populating this user object, we're going to populate lastAmount. So what we'll do here is we'll make it so that lastAmount is on here, we'll add a comma. And we're going to give this a value of function and then we're just going to return Session.get lastAmount. And I'm going to go ahead and save this, and now what will happen is that when this template's being filled out, it's going to use the lastAmount here to populate this lastAmount that we have here. So let's go ahead and test this out real quick. We can open up our application. And then, right now we don't have anything in that lastAmount so I'm going to Add, let's Add a value that is somewhat memorable, we'll Add 21, and so that looks like that's working. Now, I'm going to Sign Out and Sign back in, and notice the 21 is still there. And then, again, now this is the really neat part about this, let's make this so we can see both of these. And I'm going to change this, so instead of the exclamation mark, we'll get rid of that, and we'll go ahead and Save, and watch what happens; the 21 is still there because that was stored in Sessions. So, this gives us that capability to be able to update our application in the code of the UI, user's still logged in, we just keep whatever data that we want to survive that update of the code in user interface inside Session, and then we restore from Session. And we're not even having to do this ourselves. If you look at our code, we're using the template, so it's automatically detecting a change to that Session data. And remember, I said Session data is reactive, so that's why this actually works, is that when that Session data changes, this template helper knows that it needs to re-update this template so it updates that template and we get the updated data.
Computations
Up until this point, we've been relying on Meteor automatically updating our user interface when data, like our user or history collection data changes, but sometimes we might want to have this similar kind of auto updating functionality in our code. We can directly access the framework that Meteor uses to do this kind of updating while using computations. A Meteor computation is just some code that's rerun automatically when one or more of its dependencies change, so long as the dependencies are reactive objects, like collections or session data. We can use computations to write code that depends on data and automatically reruns when that data changes. In our app, we'll just use this to send some log messages when a user logs in or logs out, but anywhere you would want to monitor data for changes, and templates aren't going to work, computations are a good solution.
Adding A Computation
Okay, so let's go ahead and add a dependency that's basically just going log out to the console when a user logs in or logs out. And the way that we do this is we're going to use this Deps.autorun, and here we can pass in a function that's going to be automatically run when any of its dependencies, as long as they're reactive objects, change. So, we can just add a function and then what we're going to do is we're going to say, if(Meteor.user), that'll give us our Meteor user, so if there is a Meteor user that's logged in. Then we're going to do console.log and we'll say "User logged in". And then, we're going to do Meteor.user.profile.name, that's going to give us the actual user name. Then, we'll put in else and we'll say else console.log("User logged out"). We'll go ahead and save this, and now what's going to happen is this Meteor user is a reactive object, and so if it changes, the status of this changes, so there is a user, there isn't a user, it's going to rerun this function and so it's going to behave differently whenever a user's logged in versus when they're logged out. And even if their profile name changed, it would also rerun, but that's not likely to happen. So let's go ahead and go into our application and remember we're logged into the console here, so you can already see a couple of debug messages, but I'm going to go ahead and ‘Sign Out' and we get this User logged out, then I'm going to ‘Sign in', and we get this ‘User logged in: John Sonmez'. So this seems like pretty simple functionality, and we use this in a fairly simple way, but this is pretty amazing when you think about it. We didn't have to write code specifically to respond to a user logging in or logging out. If we look at our code, what happened was, since we've put this in this Deps.autorun and we have this Meteor.user, it's automatically detecting, ‘Hey, I'm dependent on the value of this', and if this changes, then I need to rerun this code. So this is really a powerful concept. If you've used the observer pattern, or the observable pattern, you're probably already familiar with this to some degree, but you've had to implement that logic yourself, but because Meteor is handling all of this for us, it's just a simple way to basically monitor changes and automatically run code and that's really one of the key things that Meteor is built off of. Our templates are using this capability and we have the capability to manually add this to our application as well.
Meteor Methods
So far, everything we've been doing as far as the app functionality is concerned has been running on the client. The problem with running all of our logic on the client is that we have to expose the logic to anyone using our application, which we might not want to do if we have some kind of sensitive algorithm. And we also have to expose ourselves to a malicious client who directly calls our JavaScript APIs to change data without using the user interface. It can be difficult to defend against these kinds of attacks and filter the data. Often it's better to just run the code on the server instead. This diagram here shows how we are currently changing data in our application. The client is modifying a collection and those changes are syncing back down to the server, but there is another way. Instead of directly manipulating a collection on the client-side with Mini-Mongo, we can make a call to a Meteor method on the server that can do the work for us. This Meteor method can validate the input and check for error conditions. It can then modify the data, which is synced back to the client. We can lock down all the calls to change collection data directly from the client and only let certain ones through, and also move more calls over to the server itself to make sure that no one can do something funny that we didn't intend with our application.
Creating A Meteor Method
Okay, so let's go ahead and change it so that this functionality that we have, that is adding an amount, is going to use a Meteor method. So the first thing we're going to do is we're going to create our Meteor method, and I'm going to create it outside of this ‘if (Meteor.isClient)' or this ‘if server code' because we need this Meteor method to exist on both sides. And we're going to talk about this a little bit more later, but it's basically going to be executed by both the client and the server. Then the server is going to tell the client what actually happened, which might actually conflict with the client data, so it might overwrite that data, and this is really going to come into play when we start talking about latency. But for now, let's just create a simple method; we're just going to do Meteor.methods and then we're going to pass in an object, and within this object we can declare our method. So, we're going to make one called addProtein, and then here, we're going to say that this is a function, and it's going to take an amount as a parameter. That's all we're going to need because we can detect the userId ourselves. And then inside here, what we're going to do is we're going to call ProteinData.Update. In fact, let's just go ahead and take our code because it's going to be very similar to what we're doing already, and we're going to do our update and our insert. We'll leave this Session setting here because that really is part of the client of clicking the button, it doesn't really have to do with the data, we don't really need to secure that. So, let's go ahead and Paste this in here and let's fix this squiggly, and what we're going to do now is we do need to change this a little bit. We were using this this._id because we had the context, remember, in our template with this ‘with' here and this addAmount, but we don't have that anymore. Instead, what we can do though is we can just do an update based on a userId, so we can say, just like we did with the filter, userId: this.userId. We're essentially applying a filter here just like you would do an update statement in SQL and you say where, we're essentially saying, ‘where userId equals this.userId'. And remember, this userId gives us the userId of the currently logged-in user. So, that should do our update, and then our insert into History is already using that, this.userId.
Calling The Meteor Method
Okay, so now that we have our method, we actually need to call this method and we could do that from the client pretty easily. All we have to do is basically change our code here for this addAmount so that instead of where before we were actually doing the calculation ourselves, we're going to instead call the server's method. So, this is pretty easy, we just do Meteor.call and then we have to pass in the name of the method, so we're going to call this addProtein, and then we follow this up with the parameter that we're going to be passing in, so in this case it's just amount, and then we can have a function for a callback if there is an error or some kind of problem. So what we can do with this is we can just put in here, it's going to give us back an error and then an id, and hopefully there won't be an error, but if there is, then we're just going to do this if(error) and we're just going to do a standard return alert with error.reason. So this way we'll be able to tell if there is an error. Now, what this is going to do, remember, when we click this addAmount now, we're not going to be doing the change directly on our client, or that's not going to be the system of record; it's still going to execute this code, so we're going to see things instantly and we're sort of getting into the latency compensation in Meteor. This is pretty interesting because you won't be able to catch this unless there's a delay, and I'm going to show you how we're going to put in a delay in a little bit here, but basically we're going to execute the code inside of this method on the client. It's going to actually make a call to the server, the server's going to execute the method, and then it's going to return back to us what the actual data is, or it's going to make that actual change, and that'll be the permanent change. So this is a little bit complicated at how it does all of this, but the important thing to know is that we're going to see the update immediately on the client, but the server is then going to tell us, yes okay, keep the data you have or no, no, no, that's not correct; when I actually ran the method on the server, this is what I got, so update yourself. So let's go ahead and check this out. We'll go ahead and go to our application. And we shouldn't see anything really change with this. So, if we look at our Protein, we Add 2, we Add 4, you can see it's instantly happening still. We're actually making a callback to the server, but there's no change in the data. So the server's saying, ‘yeah, what you got is good, but now we've secured things a little bit better'. Now we're not going to go into the details of all of the security features of Meteor, but I do want to you an idea that right now you have the ability to modify a collection from JavaScript. So someone could type in the console, a Mongo command, and they could basically modify a collection. We can turn this off by removing a package called insecure, remember we've already removed auto-publish. By default Meteor comes with auto-publish and insecure set up, which basically allows each client to have full read and write access to the server's database. We're not actually going to do that in our example since we've actually made this work through the method, but you might want to do that if you're actually going to create a production application that you're going to deploy and you care about the security of the data. You don't necessarily want someone to be able to just modify that data however they want to just by typing into this JavaScript console window.
Exploring Latency
Okay, so let's revisit that latency that I talked about before. I'm just going to Copy and Paste some code that's going to save us a little bit of time and I'm going to explain exactly how this is going to work. So, I'm going to go into our Meteor method, and inside here, before we do anything, I'm going to add this code. What this code is going to do is it's going to figure out if it's running on the client or if it's running on the server, and the way it does this is we use this isSimulation. So, if we are running on the client, isSimulation will be true because, remember, this latency compensation, what it's doing is when we're running this method on the client, we're doing a simulation, we're trying to predict what the server's going to say so that they don't have to wait. So it seems like Meteor apps always update automatically, and hopefully the server's going to give us the same result and nothing's going to change and the user will never know that we actually had to make a call to the server. But, when we're running on the server, this isSimulation is going to be false, so it gives us this ability to do something slightly different on the server versus the client. And I've put in some code here, so if not isSimulation, so if we're running on the server, then I'm using this node fibers/future, which is basically just a way to set a timeout or to basically set a delay. It's like asleep, we're just going to sleep for essentially 5 seconds here, and then we're going to go ahead and go. And in fact, I'll set this delay to be about 3 seconds just to make it a little bit faster on video. Now, if we're not isSimulation, we're going to change the amount, we're going to fudge the amount and make it 500, no matter what it was it's going to be 500. So, what this will allow us to do is that when we run this on the client, it's immediately going to update the UI as if the answer was 500, because we'll be running in Simulation so it'll hit this else block, but then it's going to make a call down to the server. The server's going to run the same code, it's going end up having to wait for 3 seconds, and then it's going to actually give us the real answer where it didn't change the amount, the real amount. So then, the server's going to send us back its result and we're going to say, Oh wait a minute, the server says we're wrong, let's update to what the server says. So let's go ahead and test this out, we'll just go ahead and open up our application. Okay, let's say we enter an amount like 5. I'm going to click ‘Add Protein' and you can see that it says 500 and our Total went up to 623, and then automatically the server came back and corrected that. Let's watch that again. So I'm going to Add 10, and we've got 500 showing up in the history, and then 628 for the Total, and the server came back and fixed that. So there's a lot of different ways that you could use this functionality. You could basically make it so that you show some kind of a message to the client, letting them know that you're getting the data from the server; you can just go ahead and predict what the data's going to be; you can have a different result or have some kind of indicator, maybe if you're posting a message, maybe it could say Invalidated, and then when it comes back from the server, it could say Validated. There's a lot of ways you can use this, but it's really neat because it allows you to make your application respond instantaneously, even if it's having to go back to the server, which is something I haven't really seen before and I really like the way that this is implemented. So think about this if you want to make your app really responsive of using this capability.
Adding A Minus Button
Okay, so the last thing we're going to do is we're going to take a quick look at some basic, basic permissions and we're going to do this by actually adding another button to our application. So we're just going to add this button that's going to allow the user to do a quick subtract. And I'm going to Copy some of this code to save us some time. So, we're just going to put in a new button, it's going to be called quickSubtract, and it is going to have a value of -100, so it's just going to say -100 on it. And the idea would be, oops, I didn't really mean to add that protein or I want to just subtract 100. You could use this for whatever purpose you want, I'm just going to use this to demonstrate our ability to check the security because we're going to run this code on the client as opposed to addAmount, which we made run on the server. Now one quick thing before we get into any of the security, is the security applies to the client. You need to remember this because, for example, if we try to add security in our addAmount, it wouldn't work because the Meteor platform assumes that if the code runs on the server, it's already validated and it's okay. It doesn't do any kind of security checks other than what you put in place, but if it runs on the client, it will check against these security rules. And remember, by default, we're allowing all operations. So I'm actually going to put in some security that's going to not allow all operations and we'll see how to do that next. So, what we want to do is to go ahead and implement this quickSubtract real quick and I'm just going to Copy and Paste this code, so we're going to put this in our Template.userDetails events. Right here where we have this addAmount, I'm just going to put a comma, and now we're going to add another event handler for this quickSubtract, and let's go ahead and add our bracket. Oaky, so now we have quickSubtract and we have this preventDefault in here, and we're just doing ProteinData.update and we're just incrementing the total by -100. So, we can run this code as is, and let's just check this out to see if this works. We can just click this and it subtracted by 100, and I can go into the negatives here, but now let's go ahead and prevent it from going into the negative. We'll wait for this to come back and we're in the positive, so now we're going to add some very simple security to deny the action if it takes us to the negative.
Adding A Deny
So we can add this to Security, and remember it's only going to be applied on the client-side by doing our security on our collection, so we're going to say ProteinData, that's our collection, .deny, and we can deny certain operations on a collection. Remember, our security settings by default, just like all Meteor applications, are to allow everything. If you're going to create your application and actually deploy it in production, you care about your data being changed, you probably want to remove that package, that insecure package, so that it'd be the opposite. You'd only allow things that you specifically allow. So in this case, we're going to blacklist this; we're going to say, we're going to deny this specific action. We can do the same thing with allow, so instead of deny, we could do allow if we had this in reverse, but in our case we're going to say for an update, we're going to say what the operation is that we're going to apply this to. We're going to execute this function that's going to take in the userId and the data. This is going to give us the capability to evaluate against this userId in this particular data, and determine whether or not we're going to allow this. So, we're going to say, if(data.total) is less than 0, so basically if whatever's happened is going to cause this data to go below 0, let's return true; we are going to deny it. Otherwise, we're going to return false; we're not going to deny it. Now what will happen is if we go into our Protein Tracker, and we try to do this -100 button, you can see it tried to do this, but it did not actually allow it. When we click this, it tries to do it, but nope, sorry, we're denying that change to that collection. And the same thing would apply here, so if we went into our JavaScript console, and you can see the message here, if someone were to type in a manual update inside here, or try to mess with that collection in a way that we had denied, they would get that error as well.
Up Next
Okay, so now we've built out our Protein Tracker application and covered most of the major features of the Meteor platform in APIs. We can now create Meteor applications that allow for users to log in, we can manipulate data for the application, and we can use templates and reactive objects to automatically change our UI when data changes, but there is still more we can do. We haven't seen how to deploy our application yet and we haven't utilized the community-contributed projects we can find on the Atmosphere Repository. Up next, I'll take you through the process of deploying your Meteor application, installing Meteor on a Mac instead of a PC, and using Meteorite to get third-party libraries and extend our application. Thanks for joining me and take care.
Beyond Meteor
Introduction
Hi, this is John Sonmez from Pluralsight and in this module we'll be going beyond the basics of building Meteor applications and learn how to deploy our application, as well as use community-created packages from Atmosphere. So far, we've created our application using the unofficial Windows version of Meteor and that has worked out well for us, but if you're doing some serious Meteor development, you'll probably want to use a supported platform, especially when you're ready to deploy it. In this module, we'll go through the process of deploying a Meteor app to both the Meteor Servers and to a remote Linux machine. I'll also show you how to get Meteor installed and running on a Mac, where we'll utilize Meteorite to get packages from the Atmosphere Repository that will allow us to add a very important addition to most Single Page Applications written in JavaScript, Routes. By the end of this module, you should know how to deploy a Meteor application and how to utilize packages from Atmosphere.
Deploying
Deploying in Meteor is both easy and difficult. Let me explain. We can deploy directly to Meteor's own servers, which allow us to freely host an app for test purposes with a single, simple command, but if we want to deploy Meteor to our own server, we have to do a little bit of work to package the application and make sure we have all the prerequisites installed. Not extremely difficult, but not nearly as streamline as the Meteor Server Route, and hopefully this will change in the future. I'll be showing you how to do both next. First, we'll deploy to the Meteor Servers, then we'll deploy our application to a Linux machine in the cloud running on DigitalOcean, a cloud provider that I like to use.
Deploying to Meteor
Okay, so now we're going to start off by deploying our Meteor application to the Meteor Server. And this is the easier way to do the deployment, we can actually put our application right on the Meteor Servers and we can use this for test purposes, but I wouldn't recommend that you do it for more than test purposes because you'll probably get in trouble and they'll probable delete your application if a lot of users start using it and taking up a lot of bandwidth, since it is free. Now, one thing we'll need to do before we do this is we're going to need to get rid of the code that was in this not isSimulation. If we leave this in here, we'll get an error, because we can't really utilize a package, a Node package on the fly inside of Meteor in production. It's insecure and so we'll get an error here. So, but we don't really need this code, that was just a delay. You can leave this amount = 500 in this code if you want, and if we have some kind of latency issue, you'll actually be able to see this flash up to 500 real quick before the server updates it. Now the other thing we need to do is, remember, we talked about the permissions and we said that, by default, when we're developing in Meteor, we're in an insecure mode, meaning that all operations on the MongoDB were allowed from the client. Now when we go to production, it's not going to be an insecure mode, we're going to have to explicitly allow whatever we want. And if you notice here, remember we're doing this insert, we've got this insert that's still happening on the client-side, this ProteinData.insert to insert new data. So this is going to be denied if we don't add an allow. So what we're going to do is we're going to add a security declaration, we're going to say ProteinData.allow, instead of deny. And here we can do the same type of format, we're just going to say, we're going to allow an insert, and then we specify the function that determines whether it's allowed. It's going to take a userId and then the data, and then we're going to just check if(data.userId == userId) of the user trying to do this, then we're going to return true, yeah it's allowed. Otherwise, we're going to return false, no it's not allowed. So let's go ahead and save that. And then what we're going to do is we're just going to do ‘meteor deploy' and then we're going to say proteintracker.meteor.com. Now you can use whatever name you want here, this is the free hosting on Meteor's platform. You can also use your own domain name; you just have to set the DNS record to go to origin, not meteor.com. We're just going to make this work at proteintracker.meteor.com though. So, I'm just going to go ahead and run this and this should end up packaging our application, it'll do this Bundling step, and then it will upload it and run it. Okay, so now our app is being served from proteintracker.meteor.com.
Testing The app on Meteor
Okay, so let's go ahead and test this out; we're just going to go to proteintracker.meteor.com, and you can see we need to configure our Google Login. I went ahead and already created a new Client ID that has the proteintracker.meteor.com address here, you can see here, so I just need to add the Client ID and then the secret. And now if we Save this, we should be able to run our app. So, I'm signed in, I can go ahead and Add some protein, and you can see that 500 flashing up there real quick, but then the server comes back with a response pretty quickly and updates this. So this is working, all of our functionality seems to be working as well. We've got our data saved and then our -100 is actually not going to work, even if I were to put in a positive 100, because we never allowed it. We have that deny in there, but we'd have to add an allow for that if we wanted to get that to work, and that's a good test to go ahead and try out on your own to see if you can get this -100 button working. You could do it one of either two ways; you could either create an allow for it or you could move it down to a server call, which might actually be a better way, just use a Meteor method.
Creating The Server
Okay, so we finished up the easy deploy, but now we're going to do the more difficult deploy, which is we're going to deploy to a Linux server in the cloud. Now I'm in my DigitalOcean account. If you want to sign up for an account, you can go to digitalocean.com and then you can sign up there, it's pretty affordable. I really like DigitalOcean because it just gives you the ability to create a Linux server in the cloud very easily and you can only pay for what you use. So, for example, if you create a Droplet, which is a Linux machine, and then you just use a few hours, you'll only get charged by the hour of time. So, I'm going to go ahead and Create a new Droplet, and I'm going to call this MeteorBox. And then I'm just going to choose this smallest size, you can see this is less than a penny an hour, so that's pretty neat. It's not really going to cost us much to test this out. I'm just going to choose New York and let's get the latest version of Ubuntu. And we're just going to go ahead and Create our Droplet. So this takes a little while to do and you'll get a root password that you can use to log in. Okay, so now we have our box, and if you want to connect to this using something like Putty, you can. I'm just going to keep things simple for this demonstration and we're going to access this from the console directly here from the website. And so, I'm just going to go ahead and login with root, and then I'm going to put in the Password that was emailed to me. Okay, so I'm signed into the Box and now we're going to have to do some installations in order to get everything set up to be able to deploy to this Box.
Setting up The Linux Machine
So I'm just signed in as root; you probably don't want to use a Linux machine as root, but we're going to do it for this demonstration to keep things easier. If you aren't signed in as root, you probably need to do this pseudo command, but we can just get away with doing a regular command, so we're just going to do apt-get install, and we're going to install MongoDB. So, we're going to say mongodb and then we'll say yes. So now we should have MongoDB installed and then the next thing that we're going to need is we're going to need Node.js, and the way that we're going to do this is we're going to get the earlier version of Node.js, because Node.js tends to update before Meteor, so we don't want to break things inside of Meteor by using a newer version of Node.js. So, we're just going to do a couple of commands here. We're going to do add-apt-repository, and you may have a problem with this, so before we do this, let's do one command that's going to make sure that we have our add-apt-repository command. And this command is apt-get install software-properties-common. And you might already have this, so you might not need to do this, but to be sure let's go ahead and take this one step at a time. And then the next thing that we're going to do is we're going to go ahead and do our add-apt-repository and then we're going to say ppa:chris-lea/node.js-legacy and this will give us the repository for the legacy version of Node.js. So let's go ahead and add this. And now, what we're going to do is we're going to do an apt-get update to make sure we have everything for our apt-get command. Okay, so we should have the latest information from that repository, and so now at this point we're going to go ahead and install Node.js, so we're just going do apt-get install node.js. And this will install Node.js and we can also do an apt-get install npm just to make sure we have the Node Package Manager as well. Okay, so now we have all the prerequisites installed on our Linux Box.
Getting The Project
Now the next thing I'm going to do is I'm actually going to zip up our application and I'm going to drop it in Dropbox folder so that we can get it easily from that machine. There's a lot of different ways you could do this, but I'm going to basically take our Protein Tracker and I'm just going to take the entire zip of this and I'm going to Copy this to a Dropbox Public folder. And so I'm going to grab the link for this, so I'm going to Copy this public link. And it'll take a second for this to upload to Dropbox, but once it does, I'm going to use this wget command and I'm going to get that link. Okay, so now if we use wget, we should be able to get that file and it'll just get copied locally, this is just a quick way to get a file without having to use FTP. You could use FTP if you want to, but this is a little bit quicker. So now if we do an ls, we can see we have our ProteinTracker.zip and I can just do unzip ProteinTracker.zip. Now the reason why I'm doing this, if we take a look here, is because we actually are going to do our packaging of our app on the Linux machine. Now if you had a Linux machine that you were developing on, you could actually package it and just send up the package file and then just run it from there, but because we're running on a different architecture, we do need to make sure that we package it with the correct version of Node for that particular architecture. So it's a lot easier to just go ahead and take the whole project and move it up.
Installing Meteor on Linux
Okay, so the next step we're going to do is we're going to actually install Meteor on this machine, so we're just going to do a curl https:// and then we're just going to do install.meteor.com. pipe to /bin/sh. And so this will actually install Meteor, and now we have Meteor, so we should be able to just type Meteor and we're going to go ahead and cd into that ProteinTracker directory. And we're just going to run Meteor from here to test things out first, so we want to make sure that this is actually working. We're running this in Development mode so it's running on Port 3000, so I'm just going to take this IP address and let's make sure that's still running, and let's Paste this in here. (Typing) And we need to make sure we're on Port 3000. So you can see our app is up here and it's actually using our other database. So we're going to have a little bit of a problem because it's not going to connect to localhost 3000, but we're okay because we have Meteor running on our port. So let's go ahead and close down Meteor, and now we actually want to get the Production version running. So we're going to need to bundle our app and then actually launch this with Node.
Deploying to Digital Ocean
Okay, so now what we're going to do is from inside our directory, we're just going to do ‘meteor bundle', that's going to bundle up our app, and we're going to tell it to put it at /bundle.tgz. And it'll be back one directory from here. And this is basically going to turn our app into a Node application. Oaky, so now that it's bundled, we're going to back one directory. Now we can see this bundle.tgz and we're going to un-tar this, so we're just going to say tar --zxvf, and then specify our bundle. This will extract everything. So now we're going to go ahead and run this. So what we're going to do is we're going to type PORT=80 for the port number and then we're going to set up the MONGO_URL. We're just setting up environment variables here, so we're going to set this to mongodb://localhost: and the default port is 27017. And then we're going to say our app name, which will be ProteinTracker, so we'll have our own MongoDB instance there. And then we want to do node bundle/main.js. So let's go ahead and run this and you can see it says it's listening, so now we can test this out. I'm just going to go ahead and Copy this address and Paste here. And you can see our application is running. And there is one small issue, this button doesn't work, but the reason why, if we look at our console and you'll want to check this for errors, is that it's saying that our ROOT URL isn't set in the server environment. So, we can fix that real quick. Let's just go ahead and go in there and we're going to stop this, and with our run here, we're going to add one more environment variable. So, before we run our Node command, let's go ahead and add a ROOT URL. And I wanted to point this out because this is somewhat confusing. If you look online for documentation, you'll probably find some places where the ROOT URL's not being specified. So we're just going to do http and then we'll need our address, which will be 162.243.4.137, and then node bundle/main.js. And now this should work, it's listening again. And if we go in here and reload this, so now you can see, when we go to our page here, we don't have an error in our console anymore. We can reload our page, no error, and we can click this and we can configure this. So we're not going to go through the process of configuring it on here, it's the same exact as we did on the Meteor Server and we did locally, but go ahead and test that out and make sure that it works. And that's how you get this set up on your own server. A few steps here, but not too many, and it's definitely something that is doable if you're trying to get a Meteor application up. I'd recommend testing things out on the meteor deploy first because that's a lot easier though.
Install Meteor
Okay, so next we're actually going to install Meteor on a Mac and we're actually going to install Meteorite as well. So I'm on my Mac and I've opened up a terminal window. I already have Git installed, you want to make sure that you do have Git installed; if you don't, you can just do a search for Git, go to the home page, and then the install is pretty straightforward. Right after you install Git, you may need to re-launch the terminal window so that you can actually use Git, because Meteorite is going to utilize Git. So what we're going to do, first of all, is we're just going to get Meteor installed, and this is actually pretty simple, it's the same exact command that we did on our Linux Box. So we're just going to do curl and then https:// and then install.meteor.com and pipe this to /bin/sh. So that's going to install Meteor for us and what we're actually going to be doing is, next we're going to install Meteorite, which is that package manager that'll allow us to access packages from Atmosphere. And we'll talk about that a little bit more in a second here. And we'll also be installing the router package with Meteorite so that we can add routing to our application. Okay, so we've just about gotten Meteor installed here and now we're ready to move on.
Meteorite
Meteorite is a version manager and package manager for Meteor that makes it easy to run different versions of Meteor and use packages from the Atmosphere Package Repository. We haven't been able to use Meteorite so far because we've been doing things on Windows, and Meteorite doesn't run there, but now that we have Meteor installed on a Mac, we can install Meteorite and use it to get additional packages from Atmosphere. It turns out Meteorite is pretty easy to install. All we have to do is use the Node Package Manager and we can do it with a single command, NPM install-g Meteorite. We also need get installed in order to make use of Meteorite, since it uses get to get the packages we install with it.
Atmosphere
Okay, so we've mentioned Atmosphere a few times, but we haven't actually talked about what it is. So, I figured the best way to talk about Atmosphere was to just show you what it looks like. So if you go to atmosphere.meteor.com, you'll find that there's an app out here that is actually a Meteor app, because notice this is at meteor.com, and inside here it has all of the community-created packages. And you'll find quite a few different packages here; if you look through this list, there are quite a few in here, a lot of stuff. So you're going to find pretty much anything that you're going to need. Even though Meteor's not that old, it almost seems like the packages here are more mature than Meteor itself. So, you can search these packages; for example, we were going to use a routing package. So if I look for router here, you can see that there is this Reactive Router, there's iron-router, there's a few different routers that you can use in here. You can find all kinds of stuff. If you search for html5, you can find things like bootstrap, popcorn, all kinds of stuff, even chartjs in here. So all you have to do to install one of these is just use that MRT add and then the package name, and once you do that, you'll get that package added to your Meteor application automatically. Just like with Meteor itself where we did ‘meteor add' and then the package name, you can get a package that is one of the official packages for Meteor, but if you just have Meteorite installed and do MRT and then add and then the package name, you'll install that. And there is some instructions here that tell you how to get this set up and just give you an example. This ‘mrt add moment', you can also specify the version if you want a specific version.
Install Meteorite
So, now we have Meteor installed and now we need to install Meteorite. Now in order to install Meteorite, you just have to do a pseudo and then you should be able to do npm install-g meteorite. And this is going to use the Node Package Manager to get Meteorite, because Meteorite is a Node Package. And then Meteorite is actually going to wrap Meteor. So now we could actually do mrt and we're basically running Meteor through the Meteorite command. So I'm in my Dropbox folder and inside here I have another folder called WIP and then inside here I have our ProteinTracker application. So if I go in there, I can actually do mrt, and that will run Meteor from this. So you can see it's running on localhost port 3000. And I can open up my Chrome window and just go to localhost port 3000 here, and you can see that we've got Protein Tracker and I can Sign in to the app and it's got the data that we already had because, remember, this is a Dropbox folder so it's sharing that data.
Routing
So far we haven't really talked about routing because Meteor by default does not have support for it, but routing is a pretty important part of most JavaScript-based Single Page Applications. Routing in Single Page Applications usually just means replacing one part of the page with a different section. This is slightly different than routing in an MVC-based application that uses multiple pages, because when we use routing in our application, we'll just be loading up different templates based on what the route is. We aren't going to have to time to go into all the details of how routing works under the covers in this module, but coming up next, we'll get a routing package from Meteor that will allow us to add routes to our Protein Tracker application. In our application, we just need to add a RenderPage template after we've installed routing. Then, we can set up a route table that tells the RenderPage part of our page what template to use based on the route. Now when our page gets rendered, Meteor will check the route to determine what template it's supposed to load. Let's try it out and see how it works.
Install Routing
Now while we're here on the Mac side, what I'm going to do is I'm actually going install the router into our application. So I'm going to stop our application and I'm just going to do mrt add router. And this is going to use get; if you get an error here that says it can't check something out, it might be because you're missing get, but now you can see that it has gotten router, and it's gotten all the dependencies for router, you can see that router actually depends on this page js-ie support and this HTML5-History-API. So it's installed everything and so now it is in our application, we can run our app, and we can use the router capability.
Adding Routing
Okay, so now we're going to add some basic routing to our application now that we have router installed. And so, what I'm going to do is open up our files for our application. I'm going to start with our HTML file and I'm going to use Xcode to open this up; you can use whatever editor that you want. Let's go ahead and bring this into view, and then we're going to grab our JavaScript file as well. We'll open that up in Xcode as well. And I'll go ahead and bring this one into view. And what we're going to do here is we're going to add the route capability. So I'm over at the beginning of our HTML, and instead of using this userDetails template, what we're going to do is we're going to put in here renderPage. And renderPage is how we tell Meteor to use the router when we have the routing installed. So what we'll have to do with this renderPage is we'll have to actually register some routes. And what Meteor is going to do is it's going to look for any routes that we register. We'll go ahead and register some routes here. And if it finds a route, it's going to go ahead and use that particular template. So, we're going to do Meteor.Router.add, and inside here, we're going to specify what the path is, what that route is, and then the template that it'll use when that route is invoked. So in our case, we're just going to do a slash, and then we're going to say, okay, if it's a slash, then just go to userDetails. So it's going to operate exactly how it did before, there's not really going to be anything different, but now it's going to be using the route instead of using that template directly. And we'll be able to add more routes later on that will be able to change the behavior of the application. So let's go ahead and test this out now, and I went ahead and I did a Meteor reset. And what Meteor reset does it is resets our data, so that's why we have to re-fill this out. If you look at my terminal here, you can see the command. If you just type meteor reset, it'll reset your MongoDB back to the default settings. This is good in development if you're trying to wipe out your data. So, I'm just going to go ahead and quickly add this console settings here for our API Access. So first we need our Client ID, we'll Copy that, we'll Paste that in, and then we need our Client secret. And we'll Paste that in and Save it, and now we should be able to sign in with Google. And you can see our application looks exactly like it did before, but we are using routes now, instead of just having that template for the userDetails. And when we add another route, you'll really be able to tell the difference.
Adding Settings
Okay, so let's go ahead and add another route here to go to our Settings page. So, what we're going to do is we're just going to make a very simple settings screen and you can fill in the rest as an exercise. I'm just going to create a new Template here and I'm going to give it the name settings. And then we'll end this template tag. (Typing) And then inside here, it's going to be really simple. All we're going to do is just have an h2 and we'll say settings and then we'll end the h2. And here you could actually put the Goal, this is a good exercise, make it so that they can change the Goal. For now I'm just going to leave this blank and you can fill that in. And then I'm going to add an href, I'm going to do