Book Image

Meteor Design Patterns

By : Marcelo Reyna
Book Image

Meteor Design Patterns

By: Marcelo Reyna

Overview of this book

Table of Contents (13 chapters)

The beginning of our online shop


Throughout the book we will be developing an e-commerce website to help us understand the core concepts of advanced Meteor web development. Let's begin by creating a new project:

meteor create online_shop

The must-have packages

Atmospherejs.com has always been the "go to" website to find packages. Here you will find thousands of packages produced by the community for free. There are a handful of packages that we absolutely need to install to make our website function properly.

First, we install the languages:

meteor add coffeescript
meteor add mquandalle:jade
meteor add mquandalle:stylus
meteor add less

Next, the router and functions that will help us with SEO and routing:

meteor add kadira:flow-router
meteor add kadira:blaze-layout
meteor add meteorhacks:fast-render
meteor add nimble:restivus
meteor add yasinuslu:blaze-meta
meteor add dfischer:prerenderio
meteor add wizonesolutions:canonical

Note

WARNING: Do not run Meteor yet! Canonical could mess up your project unless you have it set up correctly.

We will need a couple of packages as well to help us manage publishers:

meteor add lepozepo:publish-with-relations
meteor add tmeasday:publish-counts
meteor add meteorhacks:aggregate
meteor add http
meteor add meteorhacks:unblock

These next packages will extend Meteor's functions:

meteor add xorax:multiple-callbacks
meteor add aldeed:collection2
meteor add aldeed:autoform
meteor add fastclick
meteor add reactive-var
meteor add alanning:roles
meteor add accounts-password
meteor add u2622:persistent-session
meteor add ongoworks:security

We will need these packages to properly manage time:

meteor add momentjs:moment
meteor add mrt:moment-timezone

For the last set, we'll be using a couple of additional packages that will make the design process much faster:

meteor add kyleking:customizable-bootstrap-stylus
meteor add raix:handlebar-helpers
meteor add fortawesome:fontawesome
meteor add percolate:momentum

We need to remove some packages for security too:

meteor remove autopublish
meteor remove insecure

All of these packages will be explained in more detail throughout the book, but all of these are must-haves. The first package that we need to explain is the wizonesolutions:canonical package. This package makes sure that all incoming traffic is routed to your ROOT_URL, so it is particularly useful when you want all the traffic to go to your SSL site. The first thing that we need to do before running Meteor is set up canonical to run only in the production environment.

Create /server/canonical.coffee, and add this code:

#/server/canonical.coffee
if process.env.NODE_ENV is "development" or process.env.ROOT_URL.indexOf("meteor.com") > -1
  Meteor.startup ->
    process.env.PACKAGE_CANONICAL_DISABLE = true

This code snippet effectively sets your PACKAGE_CANONICAL_DISABLE environment variable to make sure that canonical is inactive while you are developing.

What are environment variables? These variables are defined within the scope of the deployment, and they make sure that the project knows information before the build finishes on the server. Information such as what database to use, which domains to use, and other setup information can usually be found in these variables. We will cover this information in the final chapter.

File structure

A proper file structure is tremendously important in Meteor. We have found that the best way to work is with functional top-level modules. This means that every folder is a micro-service, and therefore can act on its own. This allows for a lot of modularity in the project, and it's very easy for others to understand what it is that you are trying to accomplish. In this section, we will cover this file structure and Meteor's special folders.

Let's look at a sample web application folder structure:

/online_shop
/online_shop/cart
/online_shop/cart/cart_route.coffee  #RUNS ON CLIENT AND SERVER
/online_shop/cart/client
/online_shop/cart/client/cart_view.jade  #RUNS ON CLIENT ONLY
/online_shop/cart/client/cart_controller.coffee
/online_shop/cart/client/cart.styl
/online_shop/cart/server
/online_shop/cart/server/cart_publisher.coffee  #RUNS ON SERVER ONLY
/online_shop/cart/server/cart_methods.coffee

In this folder structure, cart is the micro-service, and it is composed of a route, view, controller, and publisher. The files placed under a /client directory will be published to the client and will only run on the client. The files placed under a /server directory will only run and be accessible on the server. If a file is placed in none of these directories, then the file will run on both the client and server. The expected structure goes like this:

/project_folder
/project_folder/_globals
  ./client/<global support function files>
  ./server/<global support function files>
  ./lib/collections/<collection>/<file>
  ./lib/collections/<collection>/server/<permissions file>

/project_folder/router
  ./client/layouts/<layout file>
  ./lib/<configuration file>
  ./lib/<middleware file>

/project_folder/<module>
  ./<route file>
  ./client/<template file>
  ./client/<logic file>
  ./client/<styles file>
  ./server/<publishers file>
  ./server/<methods file>

It's important to note that the /lib directory will always run before any other code does. Let's place our canonical file under the /_globals/canonical/server directory.

Let's create our first module: the router. Create the /router/client/layout.jade directory, and we will only have one layout throughout the project. Now let's code our layout:

//- LAYOUT.JADE
head
  title Online Shop
  meta(charset="utf-8")

  //- Allow saving to homescreen
  meta(name="apple-mobile-web-app-capable" content="yes")

  //- Do not try to detect phone numbers
  meta(name="format-detection" content="telephone=no")

  //- Make it mobile friendly
  meta(name="viewport" content="user-scalable=no, initial- scale=1.0, maximum-scale=1.0")

body

template(name="layout")
  +Template.dynamic(template=nav)
  +Template.dynamic(template=content)

Here, we have introduced the Template.dynamic component. This component may be used to render other templates dynamically by changing the value of a variable to the name of the template we want to render. We decided to use two variables—nav and content— that are controlled by the router. So, basically, the content variable will be changing to different strings that are equal to the names of our templates.

We will create our landing module in the next chapter to learn not only how to use the router but also how to properly subscribe to data.