Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Build Applications with Meteor
Build Applications with Meteor

Build Applications with Meteor: Isomorphic JavaScript web development

$39.99 $27.98
Book May 2017 388 pages 1st Edition
eBook
$39.99 $27.98
Print
$48.99
Subscription
$15.99 Monthly
eBook
$39.99 $27.98
Print
$48.99
Subscription
$15.99 Monthly

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Buy Now

Product Details


Publication date : May 30, 2017
Length 388 pages
Edition : 1st Edition
Language : English
ISBN-13 : 9781787129887
Category :
Table of content icon View table of contents Preview book icon Preview Book

Build Applications with Meteor

Chapter 1. Foundation of Meteor

Foundation of Meteor


Meteor is an open source web and mobile development platform, simplifying the process of building applications using only one programming language--JavaScript.

What is included in Meteor?

  • Server: As a full-stack platform needs a web server, Meteor runs on top of Node.js, and we get all the benefits of using the Node, such as non-blocking I/O event driven architecture, an enormous amount of open source packages via NPM, plus we don't need to switch the language from the backend to the frontend.
  • Database(s): Meteor comes with MongoDB in a universal way. We get a light copy of MongoDB on the browser called Minimongo. Both the databases are in sync in real-time out of the box, which means that the UI can be updated even before the data reaches the server, and that is one of the most compelling features of the platform.
  • Communication: How do the client and server talk to each other? The communication is done via DDP (Distributed Data Protocol), which is an RPC (Remote Procedure Call) protocol built on top of WebSockets instead of HTTP. Due to the bidirectional communication nature of the web sockets, Meteor is a real-time platform by default.
  • Frontend UI frameworks: Meteor was using Blaze as its primary template engine, which is Meteor's implementation of Handlebars; however, it also ships with support for Angular and React currently.

Now you must be wondering how all these technologies are glued together. On a very high level, the way Meteor works is that the server publishes channels and the client subscribes to those channels, then all updates from the client can update the server in real time and the other way around--updates on the server can update the client.

Now, let's look at what else is included in Meteor:

  • There is also a native for Meteor package management, called Atmosphere, where you can find tons of useful packages. Note that all Atmosphere packages will be moved to NPM in the future.
  • ECMAScript 6 or ES6 is the major upgrade of JavaScript language, and you can code in ES6 in any of your js files. There is no need for configuring anything like babel, webpack plugins, dev servers, and task runners.
  • Any changes on the server or the client create a build automatically for you, and there is no need for browser refresh or manual server restarts.
  • Throughout the book, we will be using React expect for Chapter 8Build a Chatbot with Facebook's Messenger Platform, where we will use Angular 2. With Meteor, there is zero effort to start writing React apps. There is no need for any babel presets or anything else. The support for JSX extension comes with the default ecmascript package.

In this chapter, we'll be looking at the following topics:

  • Downloading and installing Meteor
  • Installing packages with NPM and Meteor
  • Overview of React's API
  • Creating an example application with React and Meteor

Setting up the development environment


Installing and running Meteor is extremely easy.

For Linux and iOS, all you need is the terminal and cURL. cURL is basically a command-line tool that we can use to move data with URL syntax, such as a GET, POST, and more, all directly from the terminal.

For Windows users, Meteor comes with an installer. You can download it from https://www.meteor.com/install">https://www.meteor.com/install. All the commands in the book are executed in a Linux terminal; just skip the sudo command and execute the commands as administrator if you are on Windows.

If you don't have cURL installed, open your terminal and install it with the following commands:

  1. Run update as a superuser:
>> sudo apt-get update
  1. Install cURL:
>> sudo apt-get install curl
  1. Verify the installation:
 >> curl --version
  1. Once you have cURL installed, installing Meteor is easy as it's a one line command:
>> curl https://install.meteor.com/ | sh

This will download the latest version of Meteor, and it will install it globally on your machine. Node.js, NPM, MongoDB, and all other default packages will be inside the .meteor directory.

The final installation looks like this:

Meteor 1.4.4.2 has been installed in your home directory (~/.meteor).
Writing a launcher script to /usr/local/bin/meteor for your convenience.
This may prompt for your password.

In Chapter 9, Build Internet of Things Platform, we will build Node.js apps connecting to a Meteor app. If you don't have Node.js and MongoDB and you want to run them outside Meteor, here's a list of commands and installing scripts that you might find useful:

Install Node.js with cURL

curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash -

sudo apt-get install -y nodejs

Uninstall Node.js

sudo rm /usr/local/bin/{node,npm}

Update node with NPM

sudo npm cache clean -f sudo npm install -g n sudo n stable

Update to specific version with NPM

sudo n 4.4.4

Check the version of Node.js

node -v or node --version

Check the version of NPM

npm -v or npm --version

Install cURL and check its version

sudo apt-get update

sudo apt-get install curl

curl --versionc

Uninstall cURL

sudo apt-get remove --auto-remove curl

Purging cURL config data

sudo apt-get purge --auto-remove curl

MongoDB install(Ubuntu)

sudo apt-get update

sudo apt-get install -y mongodb-org

MongoDB version

mongod --version

Stop MongoDB

sudo service mongod stop

Restart MongoDB

sudo service mongod restart

Remove MongoDB

sudo apt-get purge mongodb-org*

Remove Data Directories

sudo rm -r /var/log/mongodb

sudo rm -r /var/lib/mongodb

The following are the Meteor scripts:

Install Meteor

curl https://install.meteor.com/ | sh

Check the Meteor version

meteor --version

Update Meteor to the latest version

meteor update

Check the Node.js version in Meteor

meteor node -v

Create a Meteor App

meteor create app_name

Add an Atmosphere package to a Meteor app

meteor add package_name

Remove Atmosphere package

meteor remove package_name

List all the Atmosphere packages

meteor list

Install an npm package

meteor npm install package_name --save

List all the npm packages

npm list

Run a Meteor app on a specific port;

the default is 3000

meteor --port 2000

Launch the MongoDB shell in a meteor app

in the app directory execute meteor mongo

Show all databases from the MongoDB shell

show dbs

Switch to a database

use database_name

Show all collections in a database

show collections

Reset Meteor app

meteor reset

Building a Meteor app


The steps for creating a meteor app are as simple as the installation:

  1. Open your terminal and change your directory to where you want to have your app installed. With the meteor command line interface (CLI), we can create an app with just one command:
        >> meteor create <appname>

You can name it as anything you want; I am naming mine timerapp. We'll go through the steps of creating a basic timer, updating the time from the server side to the client in real time:

            >> meteor create timerapp

The meteor create appname command installed all packages and libraries specified in the .meteor folder in the app directory. In Meteor, the packages can be installed from Atmosphere and NPM, and there are two places where you can see what is installed by default.

Atmosphere packages are specified in ./meteor/packages. All native npm packages' metadata is in the package.json file.

FoldersIf you go into your app directory, you will note that Meteor created three folders and two files: client, server, .meteor, package.json, and .gitignore:

  • client: This is for all client-side code.
  • server: This is for all server-side code.
  • .meteor: This refers to all the core functionality of meteor: packages, databases, and many more.
  • package.json: This includes all NPM installed and saved packages.
  • .gitignore: This will ignore before the commit the specified files.
    1. cd to that app directory:
            >> cd timerapp

    To start the server, run the following command:

            >> meteor

    After some installation logs in the terminal, you'll see something like this:

            => Started proxy.
            => Started MongoDB.
            => Started your app.
            => App running at: http://localhost:3000/

    Note

    You can also start the app with npm start. This will execute the start script from package.json. "scripts": {"start": "meteor run"}. You can start meteor in another port by passing port as argument, for example, $ meteor --port 2000 . in case you have the 3000 port in use.

    1. Open the project in any text editor of your choice.

    In my setup, I am using Atom https://atom.io/ with the Facebook package Nuclide https://nuclide.io/. There are other very good editors, such as Sublime Text, Visual Studio Code, WebStorm, Brackets, and many more.

    The app skeleton, created by default, is nice and minimal. In the client and server folders, there is a startup JS main.js file. All this comes by default, and you do not need to create additional configs, specify entry points of the application in different environments, dev servers, plugins, and so on.

    The frontend with React


    The best way to start with React is by modifying and extending a Hello World example. There is a basic template available in the Facebook documentation.

    For simplicity, you don't need a server to get started with React; you can load it and explore it as an HTML document by opening it in your browser.

    Create a basic HTML page and place the scripts into the head tag:

    <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
      <script 
    
    src="https://unpkg.com/react@latest/dist/react.js">
      </script>
      <script 
    
    src="https://unpkg.com/react-dom@latest/dist/
      react-dom.js"></script>
      <script 
    
    src="https://unpkg.com/babel-standalone@6.15.0/
      babel.min.js"></script>
    </head>

    With the preceding scripts, we loaded react and react-dom and the third script--babel--will make (transpile) our ES6 and JSX scripts compatible with the browsers.

    Also, we can render our first component in the body tag:

    <body>
    <div id="root"></div>
    <script 
    
    type="text/babel"> //this will make ES6 code and React Jsx compatible with the browser.
    
    
    ReactDOM.render(<h1>Hello, world!</h1>, 
       document.getElementById('root'))
    </script>
    </body>

    There are two ways to define components in React: as plain JavaScript functions or as an ES6 class that extends from React.Component.

    Let's look at a basic ES6 class component:

    class Greeting extendsReact.Component
    
    {
      render() {
        return <h1>Hello, {this.props.name}</h1>;
     }
    }

    In the preceding code, we have an ES6 class Greeting that extends from React Component class; then we defined a render method that returns HTML tags. HTML tags in JavaScript is the special thing that comes with React. In essence, it is JavaScript XML (JSX) that Facebook added to React to make it more descriptive, and it also saves typing.

    You can use plain JavaScript but many developers, including myself, find it actually easier to write HTML into the JavaScript.

    Next, paste the Greeting component just above the ReactDOM.render line:

    class Greeting extends React.Component {
    render() {
        return <h1>Hello, 
    
    {this.props.name}</h1>;
      }
    }
    ReactDOM.render(
      <h1>Hello, world!
    
    </h1>,document.getElementById('root')
    )

    If you save your file and refresh your browser, you'll see that nothing changed. To render a component, you need to attach it to an actual DOM element or add it to a parent component that can render it.

    The idea of React is that we can build components or blocks and put them together to assemble complex user interfaces. Another thing you may find different is that the data flow between components is not that well prescribed like other frameworks. React itself has no actual strict pattern on how that should be done.

    However, the intention is to have the data always flowing from top to bottom in one direction, or unidirectionally as many refer to it, like a waterfall. Top-level components can pass data to their child components in one direction; if you want to update the data of a child component, you'll need to update it in the parent and pass it down again. Let's see how this works.

    Here's how we can render the Greeting component that we created:

    ReactDOM.render(
    
    
    <Greeting name="Joe"/>,document.getElementById('root')
    );

    We added the Greeting component as a <Greeting/> element, and we also passed a parameter, called name, with the value Joe.

    Save the document, refresh the browser, and see what it does.

    The properties or the props in the components are the way we pass data to components and the parameter name is accessible from the Greeting component as this.props.name.

    If we want to render many instances of the Greeting component, for example, we need a parent component that can render multiple child Greeting components:

    class App extends React.Component {
      constructor(props) {
      super
    
    (props);
      console.log(props); // array of three children components
    }
    render() {
    
    
    return (
       <div>
         {this.props.children} // render the children components
    
    
    </div>)
      }
    }
    const Greeting = ({ name}) => (
      <div>{name}
    
    </div>
    )

    Here the parent App component wraps and renders many children Greeting components:

    ReactDOM.render(
     <App>
         <Greeting
    
    name="Joe"/>
         <Greeting name="Tony"/>
         <Greeting name="Harry"/>
    
    
    </App>,document.getElementById('root'))

    The React's state

    Besides the flexibility of decoupling your development with reusable components, another powerful feature of React is in its component state. Every React component comes with an internal state.

    If the state of a component changes, the render method will fire and re-render the component. One thing that's very different from other frameworks is that React will re-render only the changes and nothing else.

    Also, it does so in a very efficient way, and it doesn't have to touch the DOM for searching before making any changes. What is happening in the back is that JSX actually represents the DOM in JavaScript, and all the updates are happening on the script site in memory first; then it will do some checks, then batch the changes and, finally, it will commit them to the DOM.

    Adding state to a stateless function component

    What is a state in React's components?

    Components can be declared as pure JavaScript functions, and they are called Stateless, such as this one:

    function Greeting({ hello }) {
          return <div>{hello}</div>;
    }
    

    Alternatively, you can write the preceding code as an ES6 arrow function:

    const Greeting = ({ hello }) => (
        <div>{hello}</div>
    )

    Every component can hold internal encapsulated data, and we call this a state of the component. If you want to add a state to a stateless component, you should define it as an ES6 class.

    Before adding an ES6 constructor and super methods to the stateless components, we can overview what an ES6 constructor is and what the super method does in ES6 classes.

    In ES6, we can create a class, such as the following:

    class Component {
    constructor(props){
       this.props = props;
      }
    }

    The names of the parameters and methods are named as React's once. This is not from the React library source.

    We can add a method called render, as mentioned in the following code:

    class Component {
       constructor(props){
       this.props = props;
    },
    
    render() {
       return this.props;
      }
    }

    In an ES6 classical way, we can extend the base/parent class Component:

    class Greeting extends Component{
    constructor(name){
        super(name) // passing the value to the parent class which gets
        assigned to the props
        console.log(super.render()) // with the super method we can call the  functions from the parent class      
        console.log(this.render()) // or directly as this.render
    }
    }

    In a classical way, we can create a new instance of the Greeting class, like this:

    let greet = new Greeting('Joe');
    console.log(greet.render()) // have an access to the parent method render

    We can create a render() method with the same name in the child class:

    class Greeting extends Component{
         constructor(name){
         super(name)
         this.name = name;
         console.log(super.render())
    }
     render() {
       return 'Hi ' + this.name;
      }
    }
    let greet = new Greeting('Harry');
    console.log(greet.render()) // child overrides the parent

    Inheritance versus composition

    Facebook and the React community encourage the use of composition over classical inheritance. It can be said that any other pattern to reuse code is considered anti-pattern in React. A lot more can be said about that, but React has been heavily used in production at Facebook without using inheritance for sure. In such a large-scale application, the advantage of building independent pieces and combining them to form a complex functionally is what made React so popular. Components can be moved around, organized by common functionality; they can be well tested and refactored without much of a risk of breaking other parts of the system.

    Extending from the React.Component:

    class Greeting extends
    
    React.Component {
      constructor(props){ // ES6 class constructor
      super(props) // ES6
     }
      render() {
       return <h1>Hello, {this.props.name}</h1>; //local
      }
    }

    Instead of creating a new Greeting instance, we are adding it as a <Greeting/> tag:

    ReactDOM.render(
    <Greeting name="Johny"/>,document.getElementById('root'))

    Some components can be strictly presentational; others may not know who can be their children components in advance. Many namings later came from the community, Smart and Dumb components, Containers and Components, functional and classical.

    How React is used it's all up to the developers, the team, and the organization. It's a very powerful and unopinionated library and can be used along with other frameworks.

    Adding a state to a component

    One can say that React barely has any API. It has about 9-10 methods and that is all we get.

    The State is one of the main APIs in React. The best place to define the initial state of a component is in the class constructor.

    Create a class component and initialize its state:

    class Button extends React.Component 
    
    {
       constructor(props){
       super(props)
    this.state = {text: 'OFF'}
       this.handleClick = this.handleClick.bind(this)
    }
      handleClick(){
    this.state.text === 'OFF' ? this.setState({text: 'ON'}) :
    this.setState({text: 'OFF'})
    }
     render() {
      return (
        <button type="button" onClick={this.handleClick}>
      {this.state.text}</button>)
      }
    }

    This is an example of an internal state of a button that changes its text on user click (it toggles between ON and OFF).

    A few things are required for that component to maintain a state:

    • We defined the state in the class constructor method. This is the first entry of the class that will be executed. We can think of that definition as the default state of the component.
    • We created a handleClick() method and bound it to the this class in the class constructor. It will fire when the user clicks on the button.
    • In the handleClick method, we used one of the React's APIs--this.setState--and based on the comparison of the current state, we set our new state.

    Note

    React is built with functional purity in mind, and if you set the state directly as this.state.text = 'OFF', the component will not re-render.

    • In the button, we added a simple JavaScript event--onClick. Here, React has a slightly different syntax on events; it uses camel case. onClick becomes onClick.

    The second form of the setState() method is passing a function in the state instead of an object; in the callback, we get the previous state:

    this.setState
    (function(prevState) {
    return {
       text: prevState.text === 'OFF' ? 'ON' : 'OFF'
      };
    });

    Alternatively, an arrow ES6 function can be used:

    this.setState((prevState) => ({
      text: prevState.text === 'OFF' ? 'ON' : 'OFF'
    }));

    Other React methods.

    A few other important React APIs are the component life cycles methods:

    class Greeting extends React.Component {
        constructor(props) {
        super(props);
        console.log('constructor');
    }
    componentDidMount() {
       console.log('componentDidMount');
    }
    componentWillUnmount() {
       console.log('componentWillUnmount');
    }
    render() {
       return (
       <div>
          <p>{this.props.name}</p>
            {this.props.children}
       </div>)
     }
    }

    Let's test these life cycle methods by adding a simple button to the body of the HTML:

    <button onclick="umountComponent()">Unmount</button>

    Also, we can define that function in the JavaScript tag, as follows:

    function umountComponent(){
    ReactDOM.unmountComponentAtNode(document.getElementById('root'))
    }

    When the app is loaded, the order of the events is as follows:

    1. Constructor method is called.
    2. componentDidMount() is called when the component is mounted to a parent or directly to the DOM.
    3. componentWillUnmount() is called just before the component will unmount from the DOM.

    A simple use of these events can be as shown:

    1. Constructor: Initialize the component's default state in the constructor.
    2. componentDidMount(): The component is ready. You can perform any actions at that point.
    3. componentWillUnmount(): The component will be detached from the DOM; here, you can clear any resources that may cause memory leaks.

    Meteor with React

    Starting from the client, let's create our simple app:

    1. Delete all the content of the client folder.
    2. Create the index.html file with the following content:
    <head>
       <title>Timer</title>
    </head>
    <body>
      <div id="root"></div>
    </body>
    1. Meteor will take care of the missing HTML tags. It will compile it as a template rather than serve it as an HTML document.
    2. It will throw an error if you try to add the <!DOCTYPE html> and html> tags:
          While processing files with <cdpcomment data-comment-id="2521" 
          data-comment-text="Sounds incomplete. ">">templating-compiler 
          (for target web.browser):
    
          client/index.html:1: Expected one of: <body>, <head>, <template>.

    Since we are using only React, we don't need to have the blaze-html-templates package installed.

    Adding and removing atmosphere packages in Meteor

    There are two ways to add and remove atmosphere packages in Meteor: directly add it in .meteor/packages or use the meteor add or meteor removecommands.

    We will remove blaze and jquery for this example:

    >> meteor remove blaze-html-templates

    This will result in the following terminal:

    blaze-html-templates removed from your project
    caching-compiler removed from your project
    caching-html-compiler removed from your project
    templating removed from your project
    templating-compiler removed from your project
    templating-runtime removed from your project
    templating-tools removed from your project

    Now if you run your app, you will note that nothing is loaded. You'll need to install the html-static package to let Meteor load a static HTML file.

    You can install it with the following command:

    >> meteor add static-html

    It will add all the needed dependencies:

    caching-compiler added, version 1.1.8
    caching-html-compiler added, version 1.0.7
    static-html added, version 1.1.13
    templating-tools added, version 1.0.5
    Remove Jquery by deleting it in the package file (.meteor/packages)
    jquery@1.11.10 # Helpful client-side library

    You can add and remove packages even if the server is running. Meteor will restart it automatically when a package is removed or added.

    The next step is directories and files:

    • Create index.js in the root of the client folder. This will be our start up file where we can import and render the rest of the components.
    • Create the components folder. For a small demo app like this, we can keep the components in a folder components.
    • In folder components, create a Timer.js file, you can use and also Timer.jsx; Meteor will transpile JSX into JavaScript by default. Both ways are fine.

    Install react and react-dom with npm:

            >> npm install react --save
            >> npm install react-dom --save

    In the Timer.js file, let's define our component:

    import React from 'react';
    import ReactDOM from 'react-dom';
    class Timer extends React.Component {
      constructor(props) {
      super(props);
    }
    render() {
      return (<div>
             <p>Timer</p>
             </div> )
      }
    }
    export default Timer;

    It is a class component that will display the time pushed in real time from the server. The only difference between preceding examples and this one, is that we exported that component to use it in other components.

    Now, let's import and render it in the index.js file:

    import React from 'react';
    import {render} from 'react-dom';
    import Timer from './components/Timer'
    render(<Timer/>, document.getElementById('root'))
    
    

    First, let's create the functionality of the app on the client; then we can start pushing the data from the server.

    Initialize the state in the constructor and set a new state every second:

    constructor(props) {
       super(props);
    this.state = {time: 0};
    } 
      componentDidMount() {
    setInterval(() => this.setState({time: new Date().toLocaleString()}), 1000);
    }

    Also, we have the following code in the render() method:

    render() {
        return (<div>Time : 
    {this.state.time}</div>)
       }

    When the component mounts, we set a new state every second. This will force the component to re-render and display the latest state.

    To exercise the idea of the state and the props, we can now create a child component that the Timer component will render and pass its state as prop.

    Create a child component in the components folder, called TimerDisplay:

    class TimerDisplay 
    extends React.Component {
        constructor(props) {
         super(props);
      }
     render() {
        return 
        (
           <div>Time : {this.props.time}</div>
        )
       }
    }
    export default TimerDisplay;

    The TimerDisplay will receive and render the data through the props.time. It can be a stateless presentational component, and it can be defined as a function instead of a class:

    import TimerDisplay from './TimerDisplay';
    class Timer extends React.Component {
       constructor() {
       super();
    this.state = {time: new Date().toLocaleString()};
    }
       componentDidMount() {
    setInterval(() => this.setState({time: new Date().toLocaleString()}), 1000);
     }
     render() 
    {
       return (
       <div>
       <TimerDisplay time={this.state.time}/>
    </div>)
      }
    }
    export default Timer;

    Here, the parent component, Timer, re-renders every time its state changes, and then renders the child component, TimerDisplay, by passing its state as props.

    What will happen if we add another TimerDisplay, but this time with a static value:

    render() 
    {
      return (
        <div>
         <TimerDisplay time={this.state.time}/>
         <TimerDisplay time='today'/>
      </div>)
    }

    To see the power of React in action, open the console in Chrome and press the Esc key then go to Rendering and click on the checkbox Paint Flashing. You will note that even if we rendered both TimerDisplay, only the one that has its value changed is re-rendering.

    Integrating React with Meteor's reactive data system

    In the preceding example, the data passed to the child component via props was generated in the parent component itself in the setInterval function. In order to render React components on Meteor's data change, we need to create a component container.

    The steps are as follows:

    1. Add react-meteor-data and react-addons-pure-render-mixin npm packages using the following command:
            >> npm install react-meteor-data --save
            >> npm install react-addons-pure-render-mixin --save
    1. Import createContainer into the Timer.js component:
            import React from 'react';
            import TimerDisplay from './TimerDisplay';
            import { createContainer } from 'react-meteor-data';
    1. Export the container function instead of the component:
            export default createContainer(() => {
            return {
               time: Time.find().fetch()
              };
            }, 
           Timer);

    The first parameter is a callback function that returns the result as an object named time, and the second parameter is the Timer component. The way it works is that on any changes in the browser database Minimongo, the data will be fetched and passed to the component as props (time in our case).

    To break this down, refer to this:

    1. We defined Time as a MongoDB collection.
    2. find() is a MongoDB method to query records (records are called documents in MongoDB) from the collection. If there is no query specified, will return cursor for the first 20 records by default.
    3. Adding the fetch() method will return the documents as an array.

    Meteor allows us to create a collection directly in the code:

    Time = new Mongo.Collection('time');

    Explore MongoDB in the Meteor shell

    You can access all the application data with the Meteor MongoDB shell.

    Open another terminal, cd to the app directory, and start the MongoDB shell.

    Note

    The app should be running at the same time.

    >> meteor mongo

    Show all the databases in MongoDB:

    >> show dbs

    The default database for the app is named meteor; switch to the meteor database:

    >> use meteor

    Display all collections in the database:

    >>show collections

    The show collections command will not return any results.

    The reason is that we created a collection on the client side only. This collection exists in Minimongo, and it is in the browser's memory. If we refresh the page, the collection and the data will be gone.

    In order to create the same collection and persist data into MongoDB, we have to execute the exact same Time = new Mongo.Collection('time'); on the server. As soon as we do that, both the collections will be in sync and the data will be persisted into the database.

    For now, we don't want to save the timer data on the server; we only want to take advantage of the Meteor server to client real-time communication.

    Publishing and Subscribing

    The way we can get real-time updates from the server is through the Publishing and Subscribing messaging pattern of Meteor.

    The server publishes an event and on the other side, the client subscribes to that event and listens to data changes.

    On the server, in our case in the server/main.js file, we can publish an event in a very simple way:

      import { Meteor } from 'meteor/meteor';
      Meteor.startup(() => {
         // code to run on server at startup
     Meteor.publish('time', function() {
         ...
        });
    });

    The publish function takes two arguments: name of the collection and a callback function that will be executed on each subscription from the client.

    On the client, we can subscribe to it as shown here:

    Meteor.subscribe('time');

    All updates from the server will push an update to Minimongo collection on the client. The subscriber can also pass a parameter as a second argument and/or have subscription handlers as callback functions:

    Meteor.subscribe('time', id);

    Also, the subscription handlers look like this:

    Meteor.subscribe('time', {
    
     //called when data is availble in  Minimongo
       onReady: function() {
       },
        // called on error
       onError: function() {
       },
       // called when the subcription is stopped. 
        onStop: function () {
       }
    });

    Here's the server-side code of the subscription:

    import { Meteor } from 'meteor/meteor';
    import { Random } from 'meteor/random';
    
    Meteor.startup(() => {
    // code to run on server 
    
    at startup
    Meteor.publish('time', function() {
       let self = this;
       const newTime = () => {
       let 
    
    id = Random.id();
       let time = {
        time: new Date().toString()
     }
       self.added
    
    ('time', id, time);
    }
    Meteor.setInterval(function() {
        newTime();
      }, 1000);
    });

    What we did is covered in the following points:

    1. We created a publisher with a collection called time.
    2. We used one of the Meteor's timer functions, setInteval(), to call a newTime() function every 1000 milliseconds or one second.
    3. In the newTime() function, we created an ID of the document and the document as the current time.
    4. We then called the added method, which will notify the subscriber that we added a new document to the time collection.

    The client-side code is as follows:

    Time = new Mongo.Collection('time');
    class Timer extends React.Component {
         constructor(props) 
    
    {
         super(props);
        Meteor.subscribe('time');
    }
    render() {
       return 
    
     <TimerDisplay time={this.props.time}/>;
      }
    }
    export default createContainer(() => {
     return 
    
    {
        time: Time.find().fetch()
      };
    }, Timer);

    This is what we did here:

    1. We created a collection called time. The collection is created locally in Minimongo. If we don't create the same collection on the server, it will be only in the browser's memory.
    2. In the class constructor, we subscribed to the dataset time published on the server.
    3. In the render method, we rendered the TimerDisplay component as we passed time as props.
    4. At the end, we created a Meteor React container that listens to data changes, fetches the latest data from the collection, and passes it down to the component as props.
    Improvements in the current code

    In both the server and the client, we didn't provide an unsubscribing mechanism. For example, if you close the browser, the server will continue calling the newTime() function indefinitely.

    Meteor.publish() provides some other useful APIs. When the client is subscribed for the first time, we can send a notification that the initial dataset was sent using this.ready(). This will call the onReady callback on the client.

    We can also unsubscribe the client with this.stop() or listen whether the client subscription is stopped.

    The publisher on the server:

    Meteor.publish('time', function() {
       let self = this;
       self.added('time', id, time); // notify if record is added to the collection time
      let interval = Meteor.setInterval(function() {
          newTime();
      }, 1000);
     this.ready(); // 
    
    notify that the initial dataset was sent
       self.onStop(function () {
       self.stop()
       console.log('stopped called')
       Meteor.clearInterval(interval); // clear the interval if the the client unsubscribed
      });
    });

    The subscriber on the client:

    const handle = Meteor.subscribe("time", {
       onReady: function() { 
    // fires when this.ready() called on the server.
      }
    });
     handle.stop() // will call onStop(callback) on the server.
     handle.ready() // returns true if the server called ready()

    The clientTimer component:

    Time = new Mongo.Collection('time');
    const handle = Meteor.subscribe('time');
    class Timer extends React.Component {
        constructor(props) {
        super(props);
     }
     shouldComponentUpdate() {
        return this.props.handle.ready() && this.props.time.length > 0;
     }
     componentWillUnmount() {
       this.props.handle.stop();
     }
     render() {
        return <TimerDisplay time = { this.props.time }/>;
     }
    }
    export default createContainer(() => {
      return {
        time: Time.find().fetch(), handle: handle
      };
    }, Timer);

    Here, we passed the subscriber's handle as a prop to the component and in shouldComponentUpdate, we check whether the publisher sent the first dataset and whether it has any records. If yes, it will render the imerDisplay component.

    When we unmount the component, we send a notification to the that we stopped the subscription.

    Summary


    We went over the foundation of Meteor and overviewed its core components. High-level databases, servers, package managers, and its communication protocol (Distributed Data Protocol). On a high level, we now understand how the platform works.

    We installed Meteor and created a sample app with the Meteor CLI. Then, we went over the default app skeleton and some of the included Atmosphere and NPM packages.

    On the frontend, we overviewed the basics of React, its data flow, and component architecture. Then, we created a sample real-time server to client communication app and got familiar with the core functionality of the Meteor Publish and Subscribing API.

    In the next chapter, we will get more familiar with the Meteor Methods, Schema, and validation by building a simple shopping cart app, and we will continue exploring data handling and reactive rendering with React on the frontend.

    Left arrow icon Right arrow icon

    Key benefits

    • Develop a set of real-world applications each exploring different features of Meteor
    • Make your app more appealing by adding reactivity and responsiveness to it
    • Work with the most powerful feature of Meteor—the “full stack reactivity”—through building real-time applications with many third party libraries

    Description

    This book starts with the basic installation and overview of the main components in Meteor. You’ll get hands-on multiple versatile applications covering a wide range of topics from adding a front-end views with the hottest rendering technology React to implementing a microservices oriented architecture.All the code is written with ES6/7 which is the latest significantly improved JavaScript language. We’ll also look at real-time data streaming, server to server data exchange, responsive styles on the front-end, full-text search functionality, and integration of many third-party libraries and APIs using npm. By the end of the book, you’ll have the skills to quickly prototype and even launch your next app idea in a matter of days.

    What you will learn

    * See how Meteor fits in the modern web application development by using its reactive data system *Make your front-end behave consistently across environments by implementing a predictable state container with Redux * Get familiar with React and overview of Angular 2 * Add a map to your application with a real-time geolocation * Plugin into Meteor social media APIs like Twitter’s streaming and Facebook’s Messenger * Add search functionality from scratch to your existing app and data * Add responsiveness with Bootstrap 4 and Google’s Material Design using Less and Sass * Distribute your data across machines and data centers by adding Apache Cassandra to your existing stack. * Learn how to scale your microservices with the high performant language neutral framework gRPC. *Learn how to query multiple data sources using GraphQL.

    What do you get with eBook?

    Product feature icon Instant access to your Digital eBook purchase
    Product feature icon Download this book in EPUB and PDF formats
    Product feature icon Access this title in our online reader with advanced features
    Product feature icon DRM FREE - Read whenever, wherever and however you want
    Buy Now

    Product Details


    Publication date : May 30, 2017
    Length 388 pages
    Edition : 1st Edition
    Language : English
    ISBN-13 : 9781787129887
    Category :

    Table of Contents

    16 Chapters
    Title Page Chevron down icon Chevron up icon
    Credits Chevron down icon Chevron up icon
    About the Author Chevron down icon Chevron up icon
    About the Reviewer Chevron down icon Chevron up icon
    www.PacktPub.com Chevron down icon Chevron up icon
    Customer Feedback Chevron down icon Chevron up icon
    Preface Chevron down icon Chevron up icon
    Foundation of Meteor Chevron down icon Chevron up icon
    Building a Shopping Cart Chevron down icon Chevron up icon
    Style Your React Components with Bootstrap and Material Design Chevron down icon Chevron up icon
    Real-Time Twitter Streaming Chevron down icon Chevron up icon
    Developing Kanban Project Management Tool Chevron down icon Chevron up icon
    Building a Real-Time Search Application Chevron down icon Chevron up icon
    Real-Time Maps Chevron down icon Chevron up icon
    Build a Chatbot with Facebook’s Messenger Platform Chevron down icon Chevron up icon
    Build Internet of Things Platform Chevron down icon Chevron up icon

    Customer reviews

    Filter icon Filter
    Top Reviews
    Rating distribution
    Empty star icon Empty star icon Empty star icon Empty star icon Empty star icon 0
    (0 Ratings)
    5 star 0%
    4 star 0%
    3 star 0%
    2 star 0%
    1 star 0%

    Filter reviews by


    No reviews found
    Get free access to Packt library with over 7500+ books and video courses for 7 days!
    Start Free Trial

    FAQs

    How do I buy and download an eBook? Chevron down icon Chevron up icon

    Where there is an eBook version of a title available, you can buy it from the book details for that title. Add either the standalone eBook or the eBook and print book bundle to your shopping cart. Your eBook will show in your cart as a product on its own. After completing checkout and payment in the normal way, you will receive your receipt on the screen containing a link to a personalised PDF download file. This link will remain active for 30 days. You can download backup copies of the file by logging in to your account at any time.

    If you already have Adobe reader installed, then clicking on the link will download and open the PDF file directly. If you don't, then save the PDF file on your machine and download the Reader to view it.

    Please Note: Packt eBooks are non-returnable and non-refundable.

    Packt eBook and Licensing When you buy an eBook from Packt Publishing, completing your purchase means you accept the terms of our licence agreement. Please read the full text of the agreement. In it we have tried to balance the need for the ebook to be usable for you the reader with our needs to protect the rights of us as Publishers and of our authors. In summary, the agreement says:

    • You may make copies of your eBook for your own use onto any machine
    • You may not pass copies of the eBook on to anyone else
    How can I make a purchase on your website? Chevron down icon Chevron up icon

    If you want to purchase a video course, eBook or Bundle (Print+eBook) please follow below steps:

    1. Register on our website using your email address and the password.
    2. Search for the title by name or ISBN using the search option.
    3. Select the title you want to purchase.
    4. Choose the format you wish to purchase the title in; if you order the Print Book, you get a free eBook copy of the same title. 
    5. Proceed with the checkout process (payment to be made using Credit Card, Debit Cart, or PayPal)
    Where can I access support around an eBook? Chevron down icon Chevron up icon
    • If you experience a problem with using or installing Adobe Reader, the contact Adobe directly.
    • To view the errata for the book, see www.packtpub.com/support and view the pages for the title you have.
    • To view your account details or to download a new copy of the book go to www.packtpub.com/account
    • To contact us directly if a problem is not resolved, use www.packtpub.com/contact-us
    What eBook formats do Packt support? Chevron down icon Chevron up icon

    Our eBooks are currently available in a variety of formats such as PDF and ePubs. In the future, this may well change with trends and development in technology, but please note that our PDFs are not Adobe eBook Reader format, which has greater restrictions on security.

    You will need to use Adobe Reader v9 or later in order to read Packt's PDF eBooks.

    What are the benefits of eBooks? Chevron down icon Chevron up icon
    • You can get the information you need immediately
    • You can easily take them with you on a laptop
    • You can download them an unlimited number of times
    • You can print them out
    • They are copy-paste enabled
    • They are searchable
    • There is no password protection
    • They are lower price than print
    • They save resources and space
    What is an eBook? Chevron down icon Chevron up icon

    Packt eBooks are a complete electronic version of the print edition, available in PDF and ePub formats. Every piece of content down to the page numbering is the same. Because we save the costs of printing and shipping the book to you, we are able to offer eBooks at a lower cost than print editions.

    When you have purchased an eBook, simply login to your account and click on the link in Your Download Area. We recommend you saving the file to your hard drive before opening it.

    For optimal viewing of our eBooks, we recommend you download and install the free Adobe Reader version 9.