SlideShare a Scribd company logo
Reactive web
application using
Meteor
By Sapna Upreti @sapna0214
About Me
A Full Stack Developer @NodeXperts
Speaker at MeteorNoida and JsFusion
What’s inside?
Start
Meteor? Working Structure Templating
Engine
Publications/
Subscription
MethodUnit TestsBest PracticesDeployment
Maintenance Stop
What is Meteor?
Reactivity Isomorphic Hybrid Apps+ +
Reactivity
Reactivity
Change in data source → clients connected to the
Meteor server → gets updated automatically without
refresh.
Reactivity
Client
Listeners
Database
Pushes/Publishes data
Subscribes
Listens the changes
Pushed data
Data Listeners
Conventional Approach
a b c=+
4 6 10
Value Update 3 3 10
1st Call
c would still be 10 - until the code was called again.
Reactive Approach
a b c=+
4 6 10
Value Update 3 3 6
1st Call
c would become 6 automatically
Isomorphic?
Javascript Everywhere.
(Application logic that runs on both
server and client)
Conventional Systems
API
JavaScript
Client
Ruby, Python, Java, php
Server
Meteor’s System
API
JavaScript
Client
JavaScript Server
Your App
What is inside Meteor?
Command Line Tool
Server
Communication layer
Isobuild- for installing
packages via:
● Atmosphere
● NPM
● Cordova plugins
● Node.js
● Connect
● Database Driver
(Mongo)
● Livequery
● Fibers/Futures
● DDP
(Distributed
Data Protocol)
● EJSON
What is inside Meteor?
Browser
Cordova
The Packages
● Tracker
● Spacebars
● Blaze
● Minimongo
● Session
The Cordova interface is
just built upon the same
libraries as the browser,
listed on the left.
Reusable piece of
code.
It has few core
packages.
Inside Meteor
Reactivity in Meteor
Meteor's reactivity system uses
functions.
By passing a function to
Tracker.autorun we can
rerun that function any time
one of its reactive data sources
changes.
Posts.find();
Reactive data source
Ordinary function
let posts = function() {
Return Posts.find();
};
Function upgrader
Tracker.autorun(posts);
Posts
The posts function will re-run
itself every time Posts.find()
returns a different value.
DDP (Distributed Data Protocol)
● client-server protocol for querying
and updating a server-side database
● publish-subscribe messaging pattern
DDP Example
User
Posts
DDP Client DDP Server
Subscribes Posts
Post 1 Added
Post 2 Added
Post n Added
DDP Example
Post Added by user method call
Response (post data)
Updated
User Post
DDP Client
DDP Server
Minimongo
● reimplementation of
(almost) the entire
MongoDB API
● copy of MongoDB that
runs inside your web
browserMongoDB
Minimongo
Changes
Event
Minimongo cont...
View
( e.g. Blaze, Angular,
React )
Client Cache
( Minimongo )
Client Cache
( MongoDB )
Method Call
Network
latency
Data for
Client-Side
Cache
Data for
View
User input
event
Client-Side temporary
Optimistic update
Server-side persistent database operation
Architecture
ATMOSPHERE
NPM
METEOR
CLIENT
METEOR
CLIENT
NODE JS
RUNTIME
Spacebars
JavaScript
Mini Mongo
JavaScript
MongoDB
MongoDBLocal Storage
Advantages
Reactive
Data
Advantages
Single
Language
Large
community
Scalable
Scalable
Mobile
+
Web Apps
Disadvantages
Disadvantages
Ships all
templates, CSS,
JS
to Client
No need to
be real-time
REST-API
Only
Re-write server
code in JS
Let’s Code Now!
Enough Talking...Let’s get our hands dirty in
Meteor
What you need?
Meteor
Linux: curl https://install.meteor.com/ | sh
Windows: https://install.meteor.com/windows
GitHub Repo
https://github.com/sapna92/post-app
What we are going to make?
● A user posting application, where you can view
and like the user’s post.
● You can observe the reactivity through like
counts.
Final App Look
Road to our App
Step 1- Directory Structure
Step 2- Templates
Step 3- Routes
Step 4- Schemas/Collections
Step 5- Forms and Events
Step 6- Methods and Method call
Step 7- Subscription/Publication
Step 8- Update/Remove
Step 9- Unit Test Cases (TDD)
Step 10- Deployment
Step 11- Maintenance
Step 12- Mobile app build
Step- 1
Create Project
Create a Meteor Project
meteor create project_name
Directory Structure
Load Order
nav.html
main.html
client/lib/methods.js
lib/feature/styles.js
client/feature-y.js
client/main.js
HTML template files
Files inside any lib/directory
Files with deeper paths
Loaded in alphabetical order
Files beginning with main
Step- 2
Templates
Parses HTML 5 with top three level tags
<head> tag is added to the head
section
<template> tags → compiled→
Meteor templates → included inside
HTML with {{> templateName}}→
normal HTML tags
<body> tag is added to body section
Compiled using Spacebars compiler
Spacebars syntax {{#if}} or {{#each}}
Templates
Add the following code to client/head.html
<head>
<title>appName</title>
</head>
<body>
{{> hello}}
</body>
<template name="hello" >
<h1>Meteor is great for Rapid Application
Development</h1>
</template>
Meteor Build Process
Parse html file Template. main. jshead. html
Insert into the
Actual DOM
Render templates &
generate a DOM Range
Register body
And templates
When bundling your app
On screen
Load into client
Step- 3
User Accounts
Add the following packages by using the following commands:
meteor add accounts-ui
meteor add accounts-password
meteor add useraccounts:materialize
meteor add materialize:materialize
meteor add meteorstuff:materialize-modal
Routes
Add packages FlowRouter and useraccounts:flow-routing by
using the following commands:
meteor add kadira:flow-router
meteor add useraccounts:flow-routing
meteor add arillo:flow-router-helpers
Routes cont.
Add below code to imports/startup/client/routes.js
import { Meteor } from 'meteor/meteor';
import { FlowRouter } from
'meteor/kadira:flow-router';
import { BlazeLayout } from
'meteor/kadira:blaze-layout';
import { AccountsTemplates } from
'meteor/useraccounts:core';
Routes cont.
Add below code to imports/startup/client/routes.js continue...
// Import needed templates
import '../../ui/layouts/masterLayout.js';
import '../../ui/layouts/nav.js';
import '../../ui/layouts/loading.html';
import '../../ui/layouts/footer.html';
import '../../ui/pages/home/home.js';
import '../../ui/pages/post/post.js';
import '../../ui/pages/post/add.js';
import '../../ui/layouts/not-found.js';
Routes cont.
Add below code to imports/startup/client/routes.js continue...
FlowRouter.route('/', {
name: 'home',
triggersEnter: [function (context, redirect) {
if (Meteor.userId()) {
redirect('/posts');
}
}],
action(params, queryParams) {
BlazeLayout.render('masterLayout', {
main: 'home',
});
},
});
Routes cont.
Add below code to imports/startup/client/routes.js continue...
FlowRouter.route('/posts', {
name: 'post',
subscriptions(params) {
},
triggersEnter: [function (context, redirect) {
if (!Meteor.userId()) {
redirect('/');
}
}],
action(params, queryParams) {
BlazeLayout.render('masterLayout', {
footer: 'footer',
main: 'post',
nav: 'nav',
});
},
});
Routes cont.
Add below code to imports/startup/client/routes.js continue...
FlowRouter.route('/add-posts', {
name: 'addPost',
subscriptions(params) {
},
triggersEnter: [function (context, redirect) {
if (!Meteor.userId()) {
redirect('/');
}
}],
action(params, queryParams) {
BlazeLayout.render('masterLayout', {
footer: 'footer',
main: 'addPost',
nav: 'nav',
});
},
});
Routes cont.
Add below code to imports/startup/client/routes.js continue...
FlowRouter.notFound = {
action() {
BlazeLayout.render('masterLayout', {
footer: 'footer',
main: 'pageNotFound',
nav: 'nav',
});
},
};
FlowRouter.route('/dashboard', {
action(params, queryParams) {
BlazeLayout.render('masterLayout', {
nav: 'header',
main: 'dashboard',
});
},
});
Routes cont.
Add below code to imports/startup/client/routes.js continue...
AccountsTemplates.configure({
defaultLayout: 'masterLayout',
defaultLayoutRegions: {
nav: 'nav',
footer: 'footer',
},
defaultContentRegion: 'main',
showForgotPasswordLink: true,
overrideLoginErrors: true,
enablePasswordChange: true,
negativeValidation: true,
positiveValidation: true,
negativeFeedback: false,
positiveFeedback: true,
});
AccountsTemplates.configureRoute('changePwd');
AccountsTemplates.configureRoute('forgotPwd');
AccountsTemplates.configureRoute('resetPwd');
AccountsTemplates.configureRoute('signIn');
AccountsTemplates.configureRoute('signUp');
AccountsTemplates.configureRoute('verifyEmail');
Create Pages
Add below code to imports/ui/layouts/masterLayout.html
<template name="masterLayout">
<div id="wrapper">
{{#if currentUser}}
{{> Template.dynamic template=nav}}
{{/if}}
<main id="main">
{{> Template.dynamic template=main}}
</main>
{{#if currentUser}}
{{> Template.dynamic template=footer}}
{{/if}}
</div>
</template>
Create Pages
Add below code to imports/ui/layouts/masterLayout.js
import './masterLayout.html';
Add below code to imports/ui/layouts/loading.html
<template name="loading">
</template>
Create Pages
Add below code to imports/ui/layouts/footer.html
<template name="footer">
<footer class="page-footer">
<div class="footer-copyright">
<div class="container">
© 2017 NodeXperts
<a class="grey-text text-lighten-4 right"
href="http://www.nodexperts.com">NodeXperts</a>
</div>
</div>
</footer>
</template>
Create Pages
Add below code to imports/ui/layouts/nav.html
<template name="nav">
<nav>
<div class="">
<div class="nav-wrapper">
<ul id="nav-mobile" class="right side-nav">
<li class="{{isActiveRoute regex='post'}}"><a
href="/posts">Posts</a></li>
<li class="{{isActiveRoute regex='addPost'}}"><a
href="/add-posts">Add Post</a></li>
<li>{{> atNavButton }}</li>
</ul>
<a class="button-collapse show-on-large" href="#"
data-activates="nav-mobile"><i
class="material-icons">menu</i></a>
</div>
</div>
</nav>
</template>
Create Pages
Add below code to imports/ui/layouts/nav.js
import { Template } from 'meteor/templating';
import { $ } from 'meteor/jquery';
import './nav.html';
Template.nav.rendered = function () {
$('.button-collapse').sideNav({
menuWidth: 300, // Default is 300
edge: 'left', // Choose the horizontal origin
closeOnClick: true, // Closes side-nav on <a> clicks,
useful for Angular/Meteor
draggable: true, // Choose whether you can drag to open on
touch screens
},
);
};
Create Pages
Add below code to imports/ui/layouts/not-found.html
<template name="pageNotFound">
<div id="not-found">
<div class="not-found-image">
<img src="/img/404.svg" alt="" />
</div>
<div class="not-found-title">
<h1>Sorry, that page doesn't exist</h1>
<a href="/" class="gotohomepage">Go to home</a>
</div>
</div>
</template>
Add below code to imports/ui/layouts/not-found.js
import './not-found.html';
Create Pages
Add below code to imports/ui/pages/home/home.html
<template name="home">
<div class="container">
<div class="row center">
<a href="/sign-in" class="btn-large waves-effect
waves-light">Log in</a>
</div>
<div class="row center">
<a href="/sign-up" class="btn-large waves-effect
waves-light">Sign Up</a>
</div>
</div>
</template>
Add below code to imports/ui/pages/home/home.js
import './home.html';
Create Pages
Add a blank html file imports/ui/pages/post/post.html
Add below code to imports/ui/pages/post/post.js
import './post.html';
Add a blank html file imports/ui/pages/post/add.html
Add below code to imports/ui/pages/post/add.js
import './add.html';
Step- 4
Schemas & Collections
Add packages for defining database schemas and collections
by using the following commands:
meteor add aldeed:simple-schema
meteor add aldeed:collection2
Schemas & Collections
Add below code to imports/api/posts/posts.js
import { Mongo } from 'meteor/mongo';
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
const postSchema = new SimpleSchema({
title: {
type: String,
},
description: {
type: String,
},
author: {
type: String,
},
likes: {
type: Number,
},
Schemas & Collections
Add below code to imports/api/posts/posts.js continue..
createdAt: {
type: Date,
optional: true,
},
users: {
type: [String],
optional: true,
},
});
const Posts = new Mongo.Collection('posts');
Posts.attachSchema(postSchema);
export default Posts;
Schemas & Collections
Add below code to imports/api/users/users.js
import { Meteor } from 'meteor/meteor';
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
const userSchema = new SimpleSchema({
emails: {
type: [Object],
},
'emails.$.address': {
type: String,
regEx: SimpleSchema.RegEx.Email,
label: 'Email Address',
},
'emails.$.verified': {
type: Boolean,
defaultValue: false,
},
createdAt: {
type: Date,
},
Schemas & Collections
Add below code to imports/api/users/users.js continue..
profile: {
type: Object,
optional: true,
blackbox: true,
},
services: {
type: Object,
optional: true,
blackbox: true,
},
});
const Users = Meteor.users;
Users.attachSchema(userSchema);
export default Users;
Step- 5
Forms & Events
Add below code to imports/ui/pages/post/add.html
<template name="addPost">
<div class="col s12">
<div class="row">
<form class="col s12">
<div class="row">
<div class="input-field col s12">
<input id="description" name="description" type="text" class="validate">
<label for="description">Description</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input type="submit" class="btn"/>
</div>
</div>
</form>
</div>
</div>
</template>
<div class="row">
<div class="input-field
col s12">
<input id="title"
name="title" type="text"
class="validate">
<label
for="title">Title</label>
</div>
</div>
Forms & Events
Add below code to imports/ui/pages/post/add.js
import { FlowRouter } from 'meteor/kadira:flow-router';
import { Materialize } from 'meteor/materialize:materialize';
import { Template } from 'meteor/templating';
import { $ } from 'meteor/jquery';
import { Meteor } from 'meteor/meteor';
import Posts from './../../../api/posts/posts';
import './add.html';
Forms & Events
Add below code to imports/ui/pages/post/add.js continue...
Template.addPost.events({
submit(event) {
event.preventDefault();
const data = {};
$('form').serializeArray().map((obj) => {
data[obj.name] = obj.value;
return obj;
});
if (!postId) {
Materialize.toast('Unknown Error', 4000, 'rounded');
} else {
Materialize.toast('Post added Successfully', 4000,
'rounded');
FlowRouter.go('/posts');
}
},
});
const postId =
Posts.insert({
title: data.title,
description:
data.description,
userId:
Meteor.userId(),
likes: 0,
author:Meteor
.user().emails[0].address,
createdAt: new
Date(),
users: []
});
Template Helpers
Add below code to imports/ui/pages/post/post.js
import { FlowRouter } from 'meteor/kadira:flow-router';
import { Template } from 'meteor/templating';
import { Meteor } from 'meteor/meteor';
import Posts from './../../../api/posts/posts';
import './../../layouts/loading.html';
import './post.html';
Template Helpers
Add below code to imports/ui/pages/post/post.js continue...
Template.post.helpers({
posts() {
return Posts.find();
},
isLiked(userIds) {
return userIds.indexOf(Meteor.userId()) >= 0;
},
});
Template Helpers
Add below code to
imports/ui/pages/post/post.html
<template name="post">
<ul class="collection">
{{#each posts}}
{{else}}
<div>
No post to display yet!
</div>
{{/each}}
</ul>
</template>
<li class="collection-item avatar">
<i class="material-icons circle">folder</i>
<span class="title">{{title}}</span>
<p>{{description}}
</p>
<p>Likes: {{likes}}</p>
{{#if isLiked users}}
<a href="" id="unlike"
class="secondary-content waves-effect
waves-light"><i
class="material-icons">thumb_down</i></a>
{{else}}
<a href="" id="like"
class="secondary-content waves-effect
waves-light"><i
class="material-icons">thumb_up</i></a>
{{/if}}
</li>
Step- 6
Methods & Method Call
Add package check which will restrict the type of data
to be sent from client by using following command
meteor add check
Let’s remove the insecure package which will restrict
database write operation on client side by using
following command
meteor remove insecure
Methods & Method Call
Add Below code to imports/api/posts/method.js
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import Posts from './posts.js';
Meteor.methods({
'posts.insert': function (title,
description, userId = this.userId) {
});
check(description, String);
check(title, String);
check(userId, String);
return Posts.insert({
title,
description,
userId,
likes: 0,
author:Meteor
.user().emails[0].address,
createdAt: new Date(),
users: [],
});
Methods & Method Call
Registering the api to the server, add below code to imports/startup/server/register-api.js
import '../../api/posts/methods.js';
Import register-api.js file to imports/startup/server/index.js
import './register-api.js';
Methods & Method Call
Replace the code in imports/ui/pages/post/add.js with newly created method
const postId = Posts.insert({
title: data.title,
description: data.description,
userId: Meteor.userId(),
likes: 0,
author: Meteor.user().emails[0].address,
createdAt: new Date(),
users: []
});
if (!postId) {
Materialize.toast('Unknown Error', 4000, 'rounded');
} else {
Materialize.toast('Post added Successfully', 4000,
'rounded');
FlowRouter.go('/posts');
}
},
Meteor.call('posts.insert',
data.title, data.description,
(err) => {
if (err) {
Materialize.toast(err.reason ||
'Unknown Error', 4000,
'rounded');
} else {
Materialize.toast('Post
added Successfully', 4000,
'rounded');
FlowRouter.go('/posts');
}
});
Methods
Client - 1
Meteor.Call ( ‘posts.insert’ )
Posts. Collection
Local Method Body
MongoDB
Server method
Body
Meteor Server
Method Call
Result
Step- 7
Publications
Let’s remove autopublish package as we don’t want everything
to be available on client side by using below code
Meteor remove autopublish
Publications
Add below code to imports/api/posts/server/publications.js
import { Meteor } from 'meteor/meteor';
import Posts from '../posts.js';
Meteor.publish('posts.all', () => Posts.find());
Register the publication in register-api file under imports/startup/server/register-api.js
import '../../api/posts/server/publications.js';
Subscriptions
Let’s subscribe to the publication created in previous step inside route defined
for displaying posts
Add below code to imports/startup/client/routes.js
FlowRouter.route('/posts', {
name: 'post',
subscriptions(params) {
},
triggersEnter: [function (context, redirect) {
if (!Meteor.userId()) {
redirect('/');
}
}],
this.register('posts',
Meteor.subscribe('posts.all'));
Subscriptions
Let’s add logic for showing loader until subscription is ready
Add below code to imports/ui/pages/post/post.html to
modify it
<template name="post">
<ul class="collection">
{{#if isReady "posts"}}
{{else}}
{{> loading}}
{{/if}}
</ul>
</template>
{{#each posts}}
<li class="collection-item avatar">
<i class="material-icons
circle">folder</i>
...
...
<div>
No post to display yet!
</div>
{{/each}}
Subscriptions
Let’s add the helper isReady to
imports/ui/pages/post/post.js so that our loader works
until subscription is ready
Template.post.helpers({
posts() {
return Posts.find();
},
isLiked(userIds) {
return
userIds.indexOf(Meteor.userId()) >=
0;
},
});
isReady(sub) {
if (sub) {
return FlowRouter.subsReady(sub);
}
return FlowRouter.subsReady();
},
Pub/Sub
Posts Collection
Posts Collection
Blaze Template
MongoDB
Oplog Observers
Client - 1
Client - 2
Sending Posts
document
Meteor Server
Newly added
Posts document
Step- 8
Update & Remove
Let’s update the code to add more methods under imports/api/posts/methods.js
'posts.like': function (postId, userId = this.userId) {
check(postId, String);
check(userId, String);
return Posts.update({
_id: postId,
}, {
$inc: { likes: 1 },
$push: { users: userId },
});
},
Update & Remove
Let’s update the code to add more methods under imports/api/posts/methods.js ...continue
'posts.unlike': function (postId, userId = this.userId) {
check(postId, String);
check(userId, String);
return Posts.update({
_id: postId,
}, {
$inc: { likes: -1 },
$pop: { users: userId },
});
},
Update & Remove
Add events for calling above methods from client side
Add below code to imports/ui/pages/post/post.js
Template.post.events({
'click #like': function () {
Meteor.call('posts.like', this._id,
Meteor.userId());
},
'click #unlike': function () {
Meteor.call('posts.unlike', this._id,
Meteor.userId());
},
});
Step- 9
Unit Tests
To write unit test cases use below command to add package
practicalmeteor:mocha
meteor add practicalmeteor:mocha
To collect published data in test environment use below command to add
package johanbrook:publication-collector
meteor add johanbrook:publication-collector
Unit Tests
Add below code to imports/api/posts/server/publications.test.js
import { assert } from 'meteor/practicalmeteor:chai';
import Posts from '../posts.js';
import { PublicationCollector } from
'meteor/johanbrook:publication-collector';
import './publications.js';
Unit Tests
Add below code to imports/api/posts/server/publications.test.js ...continue
describe('posts publications', () => {
beforeEach(() => {
Posts.remove({});
Posts.insert({
title: 'NX homepage',
description: 'This is our home page',
author: 'userId',
likes: 2,
});
});
Unit Tests
Add below code to imports/api/posts/server/publications.test.js ...continue
describe('posts.all', () => {
it('sends all posts', (done) => {
const collector = new PublicationCollector();
collector.collect('posts.all', (collections) => {
assert.equal(collections.posts.length, 1);
done();
});
});
});
});
Unit Tests
Add below code to imports/api/posts/methods.test.js
import { Meteor } from 'meteor/meteor';
import { assert } from 'meteor/practicalmeteor:chai';
import Posts from './posts.js';
import './methods.js';
if (Meteor.isServer) {
describe('post methods', () => {
beforeEach(() => {
Posts.remove({});
});
Unit Tests
Add below code to imports/api/posts/methods.test.js ...continue
it('can add a new post', () => {
const addPost =
Meteor.server.method_handlers['posts.insert'];
addPost.apply({}, ['test', 'test description',
'user_id']);
assert.equal(Posts.find().count(), 1);
});
});
}
Unit Tests
Add below code to imports/api/posts/posts.test.js
import { Meteor } from 'meteor/meteor';
import { assert } from 'meteor/practicalmeteor:chai';
import Posts from './posts.js';
if (Meteor.isServer) {
describe('post collection', () => {
it('insert correctly', () => {
const postId = Posts.insert({
title: 'Test post',
description: 'Test description',
userId: 'user_id',
author: 'test',
users: [],
likes: 0,
});
Unit Tests
Add below code to imports/api/posts/posts.test.js ...continue
const added = Posts.find({ _id: postId });
const collectionName = added._getCollectionName();
const count = added.count();
assert.equal(collectionName, 'posts');
assert.equal(count, 1);
});
});
}
Unit Tests
Add below code to imports/api/users/users.test.js
import { Meteor } from 'meteor/meteor';
import { assert } from 'meteor/practicalmeteor:chai';
import Users from './users.js';
if (Meteor.isServer) {
describe('users collection', () => {
it('insert correctly', () => {
const userId = Accounts.createUser({
email: 'testuser@test.com',
password: '123445',
});
Unit Tests
Add below code to imports/api/users/users.test.js ...continue
const added = Users.find({ _id: userId });
const collectionName = added._getCollectionName();
const count = added.count();
assert.equal(collectionName, 'users');
assert.equal(count, 1);
});
});
}
Step- 10
Deployment
● Sign up for Galaxy, https://www.meteor.com/galaxy/signup
● Configure your MongoDB database using: mLab, compose or
MongoDB Atlas.
● Create a settings.json file with following info:
{
"galaxy.meteor.com": {
"env": {
"NODE_ENV": "production",
"MONGO_URL":
"mongodb://sapna:sapna@ds143767.mlab.com:43767/posts
"
}
},
"public": {
}
}
Deployment cont.
● Login to your meteor account using: meteor login
● Create a deploy.sh file with following info:
DEPLOY_HOSTNAME=us-east-1.galaxy-deploy.
meteor.com meteor deploy
http://posts-demo.meteorapp.com
--settings settings.json
● Instead of using this URL http://posts-demo.meteorapp.com you
can use your own domain.
● Type the following command to deploy your app:
sh deploy.sh
Deployment cont.
Step- 11
Maintenance using APM
● Meteor APM formally Kadira
● Add Meteor APM to your app:
meteor add mdg:meteor-apm-agent
● App will send data to Meteor APM
● Re-deploy sh deploy.sh
Maintenance using APM
Step- 12
Mobile app build
● Download tools for Mobiles like Android Studio, Xcode
● Running on an iOS simulator (Mac Only):
○ meteor install-sdk ios
○ meteor add-platform ios
○ meteor run ios
● Running on an iOS device:
○ meteor run ios-device
● Running on an Android emulator:
○ meteor install-sdk android
○ meteor run android
● Running on an Android device:
○ meteor run android-device
Note: Currently, Meteor on Windows does not support mobile builds.
Thank You.
Questions?
By Sapna Upreti @sapna0214

More Related Content

What's hot

Overview of CSharp MVC3 and EF4
Overview of CSharp MVC3 and EF4Overview of CSharp MVC3 and EF4
Overview of CSharp MVC3 and EF4
Rich Helton
 
ASP.NET Basics
ASP.NET Basics ASP.NET Basics
Seven Versions of One Web Application
Seven Versions of One Web ApplicationSeven Versions of One Web Application
Seven Versions of One Web Application
Yakov Fain
 
Silverlight2 Security
Silverlight2 SecuritySilverlight2 Security
Silverlight2 Security
Reagan Hwang
 
How to build a chat application with react js, nodejs, and socket.io
How to build a chat application with react js, nodejs, and socket.ioHow to build a chat application with react js, nodejs, and socket.io
How to build a chat application with react js, nodejs, and socket.io
Katy Slemon
 
Testing Web Apps with Spring Framework 3.2
Testing Web Apps with Spring Framework 3.2Testing Web Apps with Spring Framework 3.2
Testing Web Apps with Spring Framework 3.2
Rossen Stoyanchev
 
Why You Should Use MERN Stack for Startup Apps?
Why You Should Use MERN Stack for Startup Apps?Why You Should Use MERN Stack for Startup Apps?
Why You Should Use MERN Stack for Startup Apps?
Pixel Crayons
 
Project Presentation on Advance Java
Project Presentation on Advance JavaProject Presentation on Advance Java
Project Presentation on Advance Java
Vikas Goyal
 
Angular - Chapter 3 - Components
Angular - Chapter 3 - ComponentsAngular - Chapter 3 - Components
Angular - Chapter 3 - Components
WebStackAcademy
 
Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.
Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.
Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.
VitaliyMakogon
 
MVC Training Part 1
MVC Training Part 1MVC Training Part 1
MVC Training Part 1
Lee Englestone
 
Angular kickstart slideshare
Angular kickstart   slideshareAngular kickstart   slideshare
Angular kickstart slideshare
SaleemMalik52
 
Java2 platform
Java2 platformJava2 platform
Java2 platform
Sajan Sahu
 
Meteor Meet-up San Diego December 2014
Meteor Meet-up San Diego December 2014Meteor Meet-up San Diego December 2014
Meteor Meet-up San Diego December 2014
Lou Sacco
 
Developing an ASP.NET Web Application
Developing an ASP.NET Web ApplicationDeveloping an ASP.NET Web Application
Developing an ASP.NET Web Application
Rishi Kothari
 
Proposal
ProposalProposal
Angular elements - embed your angular components EVERYWHERE
Angular elements - embed your angular components EVERYWHEREAngular elements - embed your angular components EVERYWHERE
Angular elements - embed your angular components EVERYWHERE
Nadav Mary
 
Part 1 implementing a simple_web_service
Part 1 implementing a simple_web_servicePart 1 implementing a simple_web_service
Part 1 implementing a simple_web_service
krishmdkk
 
Angular 2 Essential Training
Angular 2 Essential Training Angular 2 Essential Training
Angular 2 Essential Training
Patrick Schroeder
 
A First Date With Scala
A First Date With ScalaA First Date With Scala
A First Date With Scala
Franco Lombardo
 

What's hot (20)

Overview of CSharp MVC3 and EF4
Overview of CSharp MVC3 and EF4Overview of CSharp MVC3 and EF4
Overview of CSharp MVC3 and EF4
 
ASP.NET Basics
ASP.NET Basics ASP.NET Basics
ASP.NET Basics
 
Seven Versions of One Web Application
Seven Versions of One Web ApplicationSeven Versions of One Web Application
Seven Versions of One Web Application
 
Silverlight2 Security
Silverlight2 SecuritySilverlight2 Security
Silverlight2 Security
 
How to build a chat application with react js, nodejs, and socket.io
How to build a chat application with react js, nodejs, and socket.ioHow to build a chat application with react js, nodejs, and socket.io
How to build a chat application with react js, nodejs, and socket.io
 
Testing Web Apps with Spring Framework 3.2
Testing Web Apps with Spring Framework 3.2Testing Web Apps with Spring Framework 3.2
Testing Web Apps with Spring Framework 3.2
 
Why You Should Use MERN Stack for Startup Apps?
Why You Should Use MERN Stack for Startup Apps?Why You Should Use MERN Stack for Startup Apps?
Why You Should Use MERN Stack for Startup Apps?
 
Project Presentation on Advance Java
Project Presentation on Advance JavaProject Presentation on Advance Java
Project Presentation on Advance Java
 
Angular - Chapter 3 - Components
Angular - Chapter 3 - ComponentsAngular - Chapter 3 - Components
Angular - Chapter 3 - Components
 
Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.
Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.
Vitaliy Makogon: Migration to ivy. Angular component libraries with IVY support.
 
MVC Training Part 1
MVC Training Part 1MVC Training Part 1
MVC Training Part 1
 
Angular kickstart slideshare
Angular kickstart   slideshareAngular kickstart   slideshare
Angular kickstart slideshare
 
Java2 platform
Java2 platformJava2 platform
Java2 platform
 
Meteor Meet-up San Diego December 2014
Meteor Meet-up San Diego December 2014Meteor Meet-up San Diego December 2014
Meteor Meet-up San Diego December 2014
 
Developing an ASP.NET Web Application
Developing an ASP.NET Web ApplicationDeveloping an ASP.NET Web Application
Developing an ASP.NET Web Application
 
Proposal
ProposalProposal
Proposal
 
Angular elements - embed your angular components EVERYWHERE
Angular elements - embed your angular components EVERYWHEREAngular elements - embed your angular components EVERYWHERE
Angular elements - embed your angular components EVERYWHERE
 
Part 1 implementing a simple_web_service
Part 1 implementing a simple_web_servicePart 1 implementing a simple_web_service
Part 1 implementing a simple_web_service
 
Angular 2 Essential Training
Angular 2 Essential Training Angular 2 Essential Training
Angular 2 Essential Training
 
A First Date With Scala
A First Date With ScalaA First Date With Scala
A First Date With Scala
 

Similar to Reactive Application Using METEOR

Maciej Treder ''Angular Universal - a medicine for the Angular + SEO/CDN issu...
Maciej Treder ''Angular Universal - a medicine for the Angular + SEO/CDN issu...Maciej Treder ''Angular Universal - a medicine for the Angular + SEO/CDN issu...
Maciej Treder ''Angular Universal - a medicine for the Angular + SEO/CDN issu...
OdessaJS Conf
 
Introduction to meteor
Introduction to meteorIntroduction to meteor
Introduction to meteor
NodeXperts
 
Meteor Introduction - Ashish
Meteor Introduction - AshishMeteor Introduction - Ashish
Meteor Introduction - Ashish
Entrepreneur / Startup
 
Meteor MIT Tech Talk 9/18/14: Designing a New Platform For Modern Apps
Meteor MIT Tech Talk 9/18/14: Designing a New Platform For Modern AppsMeteor MIT Tech Talk 9/18/14: Designing a New Platform For Modern Apps
Meteor MIT Tech Talk 9/18/14: Designing a New Platform For Modern Apps
Sashko Stubailo
 
Meet with Meteor
Meet with MeteorMeet with Meteor
Meet with Meteor
Tahmina Khatoon
 
Meteor
MeteorMeteor
using Mithril.js + postgREST to build and consume API's
using Mithril.js + postgREST to build and consume API'susing Mithril.js + postgREST to build and consume API's
using Mithril.js + postgREST to build and consume API's
Antônio Roberto Silva
 
Meteor intro-2015
Meteor intro-2015Meteor intro-2015
Meteor intro-2015
MeteorJS
 
Meteoro de pegasuus! Desenvolvendo aplicações realtime com MeteorJS
Meteoro de pegasuus! Desenvolvendo aplicações realtime com MeteorJSMeteoro de pegasuus! Desenvolvendo aplicações realtime com MeteorJS
Meteoro de pegasuus! Desenvolvendo aplicações realtime com MeteorJS
Julio Antonio Mendonça de Marins
 
Meteor Workshop - Open Sanca
Meteor Workshop - Open SancaMeteor Workshop - Open Sanca
Meteor Workshop - Open Sanca
Paulo Hecht
 
Isomorphic JavaScript: #DevBeat Master Class
Isomorphic JavaScript: #DevBeat Master ClassIsomorphic JavaScript: #DevBeat Master Class
Isomorphic JavaScript: #DevBeat Master Class
Spike Brehm
 
Front End Development for Back End Developers - UberConf 2017
Front End Development for Back End Developers - UberConf 2017Front End Development for Back End Developers - UberConf 2017
Front End Development for Back End Developers - UberConf 2017
Matt Raible
 
Real time Communication with Signalr (Android Client)
Real time Communication with Signalr (Android Client)Real time Communication with Signalr (Android Client)
Real time Communication with Signalr (Android Client)
Deepak Gupta
 
Day in a life of a node.js developer
Day in a life of a node.js developerDay in a life of a node.js developer
Day in a life of a node.js developer
Edureka!
 
Day In A Life Of A Node.js Developer
Day In A Life Of A Node.js DeveloperDay In A Life Of A Node.js Developer
Day In A Life Of A Node.js Developer
Edureka!
 
React loadable
React loadableReact loadable
React loadable
George Bukhanov
 
Building Mobile Friendly APIs in Rails
Building Mobile Friendly APIs in RailsBuilding Mobile Friendly APIs in Rails
Building Mobile Friendly APIs in Rails
Jim Jeffers
 
JSFest 2019: Technology agnostic microservices at SPA frontend
JSFest 2019: Technology agnostic microservices at SPA frontendJSFest 2019: Technology agnostic microservices at SPA frontend
JSFest 2019: Technology agnostic microservices at SPA frontend
Vlad Fedosov
 
Cloud Foundry a Developer's Perspective
Cloud Foundry a Developer's PerspectiveCloud Foundry a Developer's Perspective
Cloud Foundry a Developer's Perspective
Dave McCrory
 
MongoDB World 2018: Ch-Ch-Ch-Ch-Changes: Taking Your Stitch Application to th...
MongoDB World 2018: Ch-Ch-Ch-Ch-Changes: Taking Your Stitch Application to th...MongoDB World 2018: Ch-Ch-Ch-Ch-Changes: Taking Your Stitch Application to th...
MongoDB World 2018: Ch-Ch-Ch-Ch-Changes: Taking Your Stitch Application to th...
MongoDB
 

Similar to Reactive Application Using METEOR (20)

Maciej Treder ''Angular Universal - a medicine for the Angular + SEO/CDN issu...
Maciej Treder ''Angular Universal - a medicine for the Angular + SEO/CDN issu...Maciej Treder ''Angular Universal - a medicine for the Angular + SEO/CDN issu...
Maciej Treder ''Angular Universal - a medicine for the Angular + SEO/CDN issu...
 
Introduction to meteor
Introduction to meteorIntroduction to meteor
Introduction to meteor
 
Meteor Introduction - Ashish
Meteor Introduction - AshishMeteor Introduction - Ashish
Meteor Introduction - Ashish
 
Meteor MIT Tech Talk 9/18/14: Designing a New Platform For Modern Apps
Meteor MIT Tech Talk 9/18/14: Designing a New Platform For Modern AppsMeteor MIT Tech Talk 9/18/14: Designing a New Platform For Modern Apps
Meteor MIT Tech Talk 9/18/14: Designing a New Platform For Modern Apps
 
Meet with Meteor
Meet with MeteorMeet with Meteor
Meet with Meteor
 
Meteor
MeteorMeteor
Meteor
 
using Mithril.js + postgREST to build and consume API's
using Mithril.js + postgREST to build and consume API'susing Mithril.js + postgREST to build and consume API's
using Mithril.js + postgREST to build and consume API's
 
Meteor intro-2015
Meteor intro-2015Meteor intro-2015
Meteor intro-2015
 
Meteoro de pegasuus! Desenvolvendo aplicações realtime com MeteorJS
Meteoro de pegasuus! Desenvolvendo aplicações realtime com MeteorJSMeteoro de pegasuus! Desenvolvendo aplicações realtime com MeteorJS
Meteoro de pegasuus! Desenvolvendo aplicações realtime com MeteorJS
 
Meteor Workshop - Open Sanca
Meteor Workshop - Open SancaMeteor Workshop - Open Sanca
Meteor Workshop - Open Sanca
 
Isomorphic JavaScript: #DevBeat Master Class
Isomorphic JavaScript: #DevBeat Master ClassIsomorphic JavaScript: #DevBeat Master Class
Isomorphic JavaScript: #DevBeat Master Class
 
Front End Development for Back End Developers - UberConf 2017
Front End Development for Back End Developers - UberConf 2017Front End Development for Back End Developers - UberConf 2017
Front End Development for Back End Developers - UberConf 2017
 
Real time Communication with Signalr (Android Client)
Real time Communication with Signalr (Android Client)Real time Communication with Signalr (Android Client)
Real time Communication with Signalr (Android Client)
 
Day in a life of a node.js developer
Day in a life of a node.js developerDay in a life of a node.js developer
Day in a life of a node.js developer
 
Day In A Life Of A Node.js Developer
Day In A Life Of A Node.js DeveloperDay In A Life Of A Node.js Developer
Day In A Life Of A Node.js Developer
 
React loadable
React loadableReact loadable
React loadable
 
Building Mobile Friendly APIs in Rails
Building Mobile Friendly APIs in RailsBuilding Mobile Friendly APIs in Rails
Building Mobile Friendly APIs in Rails
 
JSFest 2019: Technology agnostic microservices at SPA frontend
JSFest 2019: Technology agnostic microservices at SPA frontendJSFest 2019: Technology agnostic microservices at SPA frontend
JSFest 2019: Technology agnostic microservices at SPA frontend
 
Cloud Foundry a Developer's Perspective
Cloud Foundry a Developer's PerspectiveCloud Foundry a Developer's Perspective
Cloud Foundry a Developer's Perspective
 
MongoDB World 2018: Ch-Ch-Ch-Ch-Changes: Taking Your Stitch Application to th...
MongoDB World 2018: Ch-Ch-Ch-Ch-Changes: Taking Your Stitch Application to th...MongoDB World 2018: Ch-Ch-Ch-Ch-Changes: Taking Your Stitch Application to th...
MongoDB World 2018: Ch-Ch-Ch-Ch-Changes: Taking Your Stitch Application to th...
 

More from NodeXperts

ECMA Script
ECMA ScriptECMA Script
ECMA Script
NodeXperts
 
Apollo Server IV
Apollo Server IVApollo Server IV
Apollo Server IV
NodeXperts
 
React Context API
React Context APIReact Context API
React Context API
NodeXperts
 
Devops - Microservice and Kubernetes
Devops - Microservice and KubernetesDevops - Microservice and Kubernetes
Devops - Microservice and Kubernetes
NodeXperts
 
Introduction to EC2 (AWS)
Introduction to EC2 (AWS)Introduction to EC2 (AWS)
Introduction to EC2 (AWS)
NodeXperts
 
Apollo server II
Apollo server IIApollo server II
Apollo server II
NodeXperts
 
Apollo Server
Apollo ServerApollo Server
Apollo Server
NodeXperts
 
Apollo Server III
Apollo Server IIIApollo Server III
Apollo Server III
NodeXperts
 
Getting Reactive Data
Getting Reactive DataGetting Reactive Data
Getting Reactive Data
NodeXperts
 
State, Life cycle, Methods & Events
State, Life cycle, Methods & Events State, Life cycle, Methods & Events
State, Life cycle, Methods & Events
NodeXperts
 
Refs in react
Refs in reactRefs in react
Refs in react
NodeXperts
 
Flow router, components and props
Flow router, components and propsFlow router, components and props
Flow router, components and props
NodeXperts
 
Using react with meteor
Using react with meteorUsing react with meteor
Using react with meteor
NodeXperts
 
Introduction to Reactjs
Introduction to ReactjsIntroduction to Reactjs
Introduction to Reactjs
NodeXperts
 
Mobile apps using meteor - Part 1
Mobile apps using meteor - Part 1Mobile apps using meteor - Part 1
Mobile apps using meteor - Part 1
NodeXperts
 
Microservice architecture : Part 1
Microservice architecture : Part 1Microservice architecture : Part 1
Microservice architecture : Part 1
NodeXperts
 
Reactive web applications using MeteorJS
Reactive web applications using MeteorJSReactive web applications using MeteorJS
Reactive web applications using MeteorJS
NodeXperts
 
Improving build solutions dependency management with webpack
Improving build solutions  dependency management with webpackImproving build solutions  dependency management with webpack
Improving build solutions dependency management with webpack
NodeXperts
 
Meteor workshop
Meteor workshopMeteor workshop
Meteor workshop
NodeXperts
 
Introduction to MongoDB
Introduction to MongoDBIntroduction to MongoDB
Introduction to MongoDB
NodeXperts
 

More from NodeXperts (20)

ECMA Script
ECMA ScriptECMA Script
ECMA Script
 
Apollo Server IV
Apollo Server IVApollo Server IV
Apollo Server IV
 
React Context API
React Context APIReact Context API
React Context API
 
Devops - Microservice and Kubernetes
Devops - Microservice and KubernetesDevops - Microservice and Kubernetes
Devops - Microservice and Kubernetes
 
Introduction to EC2 (AWS)
Introduction to EC2 (AWS)Introduction to EC2 (AWS)
Introduction to EC2 (AWS)
 
Apollo server II
Apollo server IIApollo server II
Apollo server II
 
Apollo Server
Apollo ServerApollo Server
Apollo Server
 
Apollo Server III
Apollo Server IIIApollo Server III
Apollo Server III
 
Getting Reactive Data
Getting Reactive DataGetting Reactive Data
Getting Reactive Data
 
State, Life cycle, Methods & Events
State, Life cycle, Methods & Events State, Life cycle, Methods & Events
State, Life cycle, Methods & Events
 
Refs in react
Refs in reactRefs in react
Refs in react
 
Flow router, components and props
Flow router, components and propsFlow router, components and props
Flow router, components and props
 
Using react with meteor
Using react with meteorUsing react with meteor
Using react with meteor
 
Introduction to Reactjs
Introduction to ReactjsIntroduction to Reactjs
Introduction to Reactjs
 
Mobile apps using meteor - Part 1
Mobile apps using meteor - Part 1Mobile apps using meteor - Part 1
Mobile apps using meteor - Part 1
 
Microservice architecture : Part 1
Microservice architecture : Part 1Microservice architecture : Part 1
Microservice architecture : Part 1
 
Reactive web applications using MeteorJS
Reactive web applications using MeteorJSReactive web applications using MeteorJS
Reactive web applications using MeteorJS
 
Improving build solutions dependency management with webpack
Improving build solutions  dependency management with webpackImproving build solutions  dependency management with webpack
Improving build solutions dependency management with webpack
 
Meteor workshop
Meteor workshopMeteor workshop
Meteor workshop
 
Introduction to MongoDB
Introduction to MongoDBIntroduction to MongoDB
Introduction to MongoDB
 

Recently uploaded

Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
James Anderson
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Paige Cruz
 
GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...
ThomasParaiso2
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
KAMESHS29
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
Full-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalizationFull-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalization
Zilliz
 
UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6
DianaGray10
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
DianaGray10
 
Data structures and Algorithms in Python.pdf
Data structures and Algorithms in Python.pdfData structures and Algorithms in Python.pdf
Data structures and Algorithms in Python.pdf
TIPNGVN2
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
Neo4j
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
Uni Systems S.M.S.A.
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
Kari Kakkonen
 
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex ProofszkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
Alex Pruden
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
Neo4j
 
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Nexer Digital
 
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdfUni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems S.M.S.A.
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
mikeeftimakis1
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Albert Hoitingh
 

Recently uploaded (20)

Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
 
GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
Full-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalizationFull-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalization
 
UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
 
Data structures and Algorithms in Python.pdf
Data structures and Algorithms in Python.pdfData structures and Algorithms in Python.pdf
Data structures and Algorithms in Python.pdf
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
 
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex ProofszkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
 
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?
 
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdfUni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdf
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
 

Reactive Application Using METEOR

  • 2. About Me A Full Stack Developer @NodeXperts Speaker at MeteorNoida and JsFusion
  • 3. What’s inside? Start Meteor? Working Structure Templating Engine Publications/ Subscription MethodUnit TestsBest PracticesDeployment Maintenance Stop
  • 4. What is Meteor? Reactivity Isomorphic Hybrid Apps+ +
  • 6. Reactivity Change in data source → clients connected to the Meteor server → gets updated automatically without refresh.
  • 8. Conventional Approach a b c=+ 4 6 10 Value Update 3 3 10 1st Call c would still be 10 - until the code was called again.
  • 9. Reactive Approach a b c=+ 4 6 10 Value Update 3 3 6 1st Call c would become 6 automatically
  • 10. Isomorphic? Javascript Everywhere. (Application logic that runs on both server and client)
  • 13. What is inside Meteor? Command Line Tool Server Communication layer Isobuild- for installing packages via: ● Atmosphere ● NPM ● Cordova plugins ● Node.js ● Connect ● Database Driver (Mongo) ● Livequery ● Fibers/Futures ● DDP (Distributed Data Protocol) ● EJSON
  • 14. What is inside Meteor? Browser Cordova The Packages ● Tracker ● Spacebars ● Blaze ● Minimongo ● Session The Cordova interface is just built upon the same libraries as the browser, listed on the left. Reusable piece of code. It has few core packages.
  • 16. Reactivity in Meteor Meteor's reactivity system uses functions. By passing a function to Tracker.autorun we can rerun that function any time one of its reactive data sources changes. Posts.find(); Reactive data source Ordinary function let posts = function() { Return Posts.find(); }; Function upgrader Tracker.autorun(posts); Posts The posts function will re-run itself every time Posts.find() returns a different value.
  • 17. DDP (Distributed Data Protocol) ● client-server protocol for querying and updating a server-side database ● publish-subscribe messaging pattern
  • 18. DDP Example User Posts DDP Client DDP Server Subscribes Posts Post 1 Added Post 2 Added Post n Added
  • 19. DDP Example Post Added by user method call Response (post data) Updated User Post DDP Client DDP Server
  • 20. Minimongo ● reimplementation of (almost) the entire MongoDB API ● copy of MongoDB that runs inside your web browserMongoDB Minimongo Changes Event
  • 21. Minimongo cont... View ( e.g. Blaze, Angular, React ) Client Cache ( Minimongo ) Client Cache ( MongoDB ) Method Call Network latency Data for Client-Side Cache Data for View User input event Client-Side temporary Optimistic update Server-side persistent database operation
  • 24. Disadvantages Disadvantages Ships all templates, CSS, JS to Client No need to be real-time REST-API Only Re-write server code in JS
  • 25. Let’s Code Now! Enough Talking...Let’s get our hands dirty in Meteor
  • 26. What you need? Meteor Linux: curl https://install.meteor.com/ | sh Windows: https://install.meteor.com/windows GitHub Repo https://github.com/sapna92/post-app
  • 27. What we are going to make? ● A user posting application, where you can view and like the user’s post. ● You can observe the reactivity through like counts.
  • 29. Road to our App Step 1- Directory Structure Step 2- Templates Step 3- Routes Step 4- Schemas/Collections Step 5- Forms and Events Step 6- Methods and Method call Step 7- Subscription/Publication Step 8- Update/Remove Step 9- Unit Test Cases (TDD) Step 10- Deployment Step 11- Maintenance Step 12- Mobile app build
  • 31. Create Project Create a Meteor Project meteor create project_name
  • 33. Load Order nav.html main.html client/lib/methods.js lib/feature/styles.js client/feature-y.js client/main.js HTML template files Files inside any lib/directory Files with deeper paths Loaded in alphabetical order Files beginning with main
  • 35. Templates Parses HTML 5 with top three level tags <head> tag is added to the head section <template> tags → compiled→ Meteor templates → included inside HTML with {{> templateName}}→ normal HTML tags <body> tag is added to body section Compiled using Spacebars compiler Spacebars syntax {{#if}} or {{#each}}
  • 36. Templates Add the following code to client/head.html <head> <title>appName</title> </head> <body> {{> hello}} </body> <template name="hello" > <h1>Meteor is great for Rapid Application Development</h1> </template>
  • 37. Meteor Build Process Parse html file Template. main. jshead. html Insert into the Actual DOM Render templates & generate a DOM Range Register body And templates When bundling your app On screen Load into client
  • 39. User Accounts Add the following packages by using the following commands: meteor add accounts-ui meteor add accounts-password meteor add useraccounts:materialize meteor add materialize:materialize meteor add meteorstuff:materialize-modal
  • 40. Routes Add packages FlowRouter and useraccounts:flow-routing by using the following commands: meteor add kadira:flow-router meteor add useraccounts:flow-routing meteor add arillo:flow-router-helpers
  • 41. Routes cont. Add below code to imports/startup/client/routes.js import { Meteor } from 'meteor/meteor'; import { FlowRouter } from 'meteor/kadira:flow-router'; import { BlazeLayout } from 'meteor/kadira:blaze-layout'; import { AccountsTemplates } from 'meteor/useraccounts:core';
  • 42. Routes cont. Add below code to imports/startup/client/routes.js continue... // Import needed templates import '../../ui/layouts/masterLayout.js'; import '../../ui/layouts/nav.js'; import '../../ui/layouts/loading.html'; import '../../ui/layouts/footer.html'; import '../../ui/pages/home/home.js'; import '../../ui/pages/post/post.js'; import '../../ui/pages/post/add.js'; import '../../ui/layouts/not-found.js';
  • 43. Routes cont. Add below code to imports/startup/client/routes.js continue... FlowRouter.route('/', { name: 'home', triggersEnter: [function (context, redirect) { if (Meteor.userId()) { redirect('/posts'); } }], action(params, queryParams) { BlazeLayout.render('masterLayout', { main: 'home', }); }, });
  • 44. Routes cont. Add below code to imports/startup/client/routes.js continue... FlowRouter.route('/posts', { name: 'post', subscriptions(params) { }, triggersEnter: [function (context, redirect) { if (!Meteor.userId()) { redirect('/'); } }], action(params, queryParams) { BlazeLayout.render('masterLayout', { footer: 'footer', main: 'post', nav: 'nav', }); }, });
  • 45. Routes cont. Add below code to imports/startup/client/routes.js continue... FlowRouter.route('/add-posts', { name: 'addPost', subscriptions(params) { }, triggersEnter: [function (context, redirect) { if (!Meteor.userId()) { redirect('/'); } }], action(params, queryParams) { BlazeLayout.render('masterLayout', { footer: 'footer', main: 'addPost', nav: 'nav', }); }, });
  • 46. Routes cont. Add below code to imports/startup/client/routes.js continue... FlowRouter.notFound = { action() { BlazeLayout.render('masterLayout', { footer: 'footer', main: 'pageNotFound', nav: 'nav', }); }, }; FlowRouter.route('/dashboard', { action(params, queryParams) { BlazeLayout.render('masterLayout', { nav: 'header', main: 'dashboard', }); }, });
  • 47. Routes cont. Add below code to imports/startup/client/routes.js continue... AccountsTemplates.configure({ defaultLayout: 'masterLayout', defaultLayoutRegions: { nav: 'nav', footer: 'footer', }, defaultContentRegion: 'main', showForgotPasswordLink: true, overrideLoginErrors: true, enablePasswordChange: true, negativeValidation: true, positiveValidation: true, negativeFeedback: false, positiveFeedback: true, }); AccountsTemplates.configureRoute('changePwd'); AccountsTemplates.configureRoute('forgotPwd'); AccountsTemplates.configureRoute('resetPwd'); AccountsTemplates.configureRoute('signIn'); AccountsTemplates.configureRoute('signUp'); AccountsTemplates.configureRoute('verifyEmail');
  • 48. Create Pages Add below code to imports/ui/layouts/masterLayout.html <template name="masterLayout"> <div id="wrapper"> {{#if currentUser}} {{> Template.dynamic template=nav}} {{/if}} <main id="main"> {{> Template.dynamic template=main}} </main> {{#if currentUser}} {{> Template.dynamic template=footer}} {{/if}} </div> </template>
  • 49. Create Pages Add below code to imports/ui/layouts/masterLayout.js import './masterLayout.html'; Add below code to imports/ui/layouts/loading.html <template name="loading"> </template>
  • 50. Create Pages Add below code to imports/ui/layouts/footer.html <template name="footer"> <footer class="page-footer"> <div class="footer-copyright"> <div class="container"> © 2017 NodeXperts <a class="grey-text text-lighten-4 right" href="http://www.nodexperts.com">NodeXperts</a> </div> </div> </footer> </template>
  • 51. Create Pages Add below code to imports/ui/layouts/nav.html <template name="nav"> <nav> <div class=""> <div class="nav-wrapper"> <ul id="nav-mobile" class="right side-nav"> <li class="{{isActiveRoute regex='post'}}"><a href="/posts">Posts</a></li> <li class="{{isActiveRoute regex='addPost'}}"><a href="/add-posts">Add Post</a></li> <li>{{> atNavButton }}</li> </ul> <a class="button-collapse show-on-large" href="#" data-activates="nav-mobile"><i class="material-icons">menu</i></a> </div> </div> </nav> </template>
  • 52. Create Pages Add below code to imports/ui/layouts/nav.js import { Template } from 'meteor/templating'; import { $ } from 'meteor/jquery'; import './nav.html'; Template.nav.rendered = function () { $('.button-collapse').sideNav({ menuWidth: 300, // Default is 300 edge: 'left', // Choose the horizontal origin closeOnClick: true, // Closes side-nav on <a> clicks, useful for Angular/Meteor draggable: true, // Choose whether you can drag to open on touch screens }, ); };
  • 53. Create Pages Add below code to imports/ui/layouts/not-found.html <template name="pageNotFound"> <div id="not-found"> <div class="not-found-image"> <img src="/img/404.svg" alt="" /> </div> <div class="not-found-title"> <h1>Sorry, that page doesn't exist</h1> <a href="/" class="gotohomepage">Go to home</a> </div> </div> </template> Add below code to imports/ui/layouts/not-found.js import './not-found.html';
  • 54. Create Pages Add below code to imports/ui/pages/home/home.html <template name="home"> <div class="container"> <div class="row center"> <a href="/sign-in" class="btn-large waves-effect waves-light">Log in</a> </div> <div class="row center"> <a href="/sign-up" class="btn-large waves-effect waves-light">Sign Up</a> </div> </div> </template> Add below code to imports/ui/pages/home/home.js import './home.html';
  • 55. Create Pages Add a blank html file imports/ui/pages/post/post.html Add below code to imports/ui/pages/post/post.js import './post.html'; Add a blank html file imports/ui/pages/post/add.html Add below code to imports/ui/pages/post/add.js import './add.html';
  • 57. Schemas & Collections Add packages for defining database schemas and collections by using the following commands: meteor add aldeed:simple-schema meteor add aldeed:collection2
  • 58. Schemas & Collections Add below code to imports/api/posts/posts.js import { Mongo } from 'meteor/mongo'; import { SimpleSchema } from 'meteor/aldeed:simple-schema'; const postSchema = new SimpleSchema({ title: { type: String, }, description: { type: String, }, author: { type: String, }, likes: { type: Number, },
  • 59. Schemas & Collections Add below code to imports/api/posts/posts.js continue.. createdAt: { type: Date, optional: true, }, users: { type: [String], optional: true, }, }); const Posts = new Mongo.Collection('posts'); Posts.attachSchema(postSchema); export default Posts;
  • 60. Schemas & Collections Add below code to imports/api/users/users.js import { Meteor } from 'meteor/meteor'; import { SimpleSchema } from 'meteor/aldeed:simple-schema'; const userSchema = new SimpleSchema({ emails: { type: [Object], }, 'emails.$.address': { type: String, regEx: SimpleSchema.RegEx.Email, label: 'Email Address', }, 'emails.$.verified': { type: Boolean, defaultValue: false, }, createdAt: { type: Date, },
  • 61. Schemas & Collections Add below code to imports/api/users/users.js continue.. profile: { type: Object, optional: true, blackbox: true, }, services: { type: Object, optional: true, blackbox: true, }, }); const Users = Meteor.users; Users.attachSchema(userSchema); export default Users;
  • 63. Forms & Events Add below code to imports/ui/pages/post/add.html <template name="addPost"> <div class="col s12"> <div class="row"> <form class="col s12"> <div class="row"> <div class="input-field col s12"> <input id="description" name="description" type="text" class="validate"> <label for="description">Description</label> </div> </div> <div class="row"> <div class="input-field col s12"> <input type="submit" class="btn"/> </div> </div> </form> </div> </div> </template> <div class="row"> <div class="input-field col s12"> <input id="title" name="title" type="text" class="validate"> <label for="title">Title</label> </div> </div>
  • 64. Forms & Events Add below code to imports/ui/pages/post/add.js import { FlowRouter } from 'meteor/kadira:flow-router'; import { Materialize } from 'meteor/materialize:materialize'; import { Template } from 'meteor/templating'; import { $ } from 'meteor/jquery'; import { Meteor } from 'meteor/meteor'; import Posts from './../../../api/posts/posts'; import './add.html';
  • 65. Forms & Events Add below code to imports/ui/pages/post/add.js continue... Template.addPost.events({ submit(event) { event.preventDefault(); const data = {}; $('form').serializeArray().map((obj) => { data[obj.name] = obj.value; return obj; }); if (!postId) { Materialize.toast('Unknown Error', 4000, 'rounded'); } else { Materialize.toast('Post added Successfully', 4000, 'rounded'); FlowRouter.go('/posts'); } }, }); const postId = Posts.insert({ title: data.title, description: data.description, userId: Meteor.userId(), likes: 0, author:Meteor .user().emails[0].address, createdAt: new Date(), users: [] });
  • 66. Template Helpers Add below code to imports/ui/pages/post/post.js import { FlowRouter } from 'meteor/kadira:flow-router'; import { Template } from 'meteor/templating'; import { Meteor } from 'meteor/meteor'; import Posts from './../../../api/posts/posts'; import './../../layouts/loading.html'; import './post.html';
  • 67. Template Helpers Add below code to imports/ui/pages/post/post.js continue... Template.post.helpers({ posts() { return Posts.find(); }, isLiked(userIds) { return userIds.indexOf(Meteor.userId()) >= 0; }, });
  • 68. Template Helpers Add below code to imports/ui/pages/post/post.html <template name="post"> <ul class="collection"> {{#each posts}} {{else}} <div> No post to display yet! </div> {{/each}} </ul> </template> <li class="collection-item avatar"> <i class="material-icons circle">folder</i> <span class="title">{{title}}</span> <p>{{description}} </p> <p>Likes: {{likes}}</p> {{#if isLiked users}} <a href="" id="unlike" class="secondary-content waves-effect waves-light"><i class="material-icons">thumb_down</i></a> {{else}} <a href="" id="like" class="secondary-content waves-effect waves-light"><i class="material-icons">thumb_up</i></a> {{/if}} </li>
  • 70. Methods & Method Call Add package check which will restrict the type of data to be sent from client by using following command meteor add check Let’s remove the insecure package which will restrict database write operation on client side by using following command meteor remove insecure
  • 71. Methods & Method Call Add Below code to imports/api/posts/method.js import { Meteor } from 'meteor/meteor'; import { check } from 'meteor/check'; import Posts from './posts.js'; Meteor.methods({ 'posts.insert': function (title, description, userId = this.userId) { }); check(description, String); check(title, String); check(userId, String); return Posts.insert({ title, description, userId, likes: 0, author:Meteor .user().emails[0].address, createdAt: new Date(), users: [], });
  • 72. Methods & Method Call Registering the api to the server, add below code to imports/startup/server/register-api.js import '../../api/posts/methods.js'; Import register-api.js file to imports/startup/server/index.js import './register-api.js';
  • 73. Methods & Method Call Replace the code in imports/ui/pages/post/add.js with newly created method const postId = Posts.insert({ title: data.title, description: data.description, userId: Meteor.userId(), likes: 0, author: Meteor.user().emails[0].address, createdAt: new Date(), users: [] }); if (!postId) { Materialize.toast('Unknown Error', 4000, 'rounded'); } else { Materialize.toast('Post added Successfully', 4000, 'rounded'); FlowRouter.go('/posts'); } }, Meteor.call('posts.insert', data.title, data.description, (err) => { if (err) { Materialize.toast(err.reason || 'Unknown Error', 4000, 'rounded'); } else { Materialize.toast('Post added Successfully', 4000, 'rounded'); FlowRouter.go('/posts'); } });
  • 74. Methods Client - 1 Meteor.Call ( ‘posts.insert’ ) Posts. Collection Local Method Body MongoDB Server method Body Meteor Server Method Call Result
  • 76. Publications Let’s remove autopublish package as we don’t want everything to be available on client side by using below code Meteor remove autopublish
  • 77. Publications Add below code to imports/api/posts/server/publications.js import { Meteor } from 'meteor/meteor'; import Posts from '../posts.js'; Meteor.publish('posts.all', () => Posts.find()); Register the publication in register-api file under imports/startup/server/register-api.js import '../../api/posts/server/publications.js';
  • 78. Subscriptions Let’s subscribe to the publication created in previous step inside route defined for displaying posts Add below code to imports/startup/client/routes.js FlowRouter.route('/posts', { name: 'post', subscriptions(params) { }, triggersEnter: [function (context, redirect) { if (!Meteor.userId()) { redirect('/'); } }], this.register('posts', Meteor.subscribe('posts.all'));
  • 79. Subscriptions Let’s add logic for showing loader until subscription is ready Add below code to imports/ui/pages/post/post.html to modify it <template name="post"> <ul class="collection"> {{#if isReady "posts"}} {{else}} {{> loading}} {{/if}} </ul> </template> {{#each posts}} <li class="collection-item avatar"> <i class="material-icons circle">folder</i> ... ... <div> No post to display yet! </div> {{/each}}
  • 80. Subscriptions Let’s add the helper isReady to imports/ui/pages/post/post.js so that our loader works until subscription is ready Template.post.helpers({ posts() { return Posts.find(); }, isLiked(userIds) { return userIds.indexOf(Meteor.userId()) >= 0; }, }); isReady(sub) { if (sub) { return FlowRouter.subsReady(sub); } return FlowRouter.subsReady(); },
  • 81. Pub/Sub Posts Collection Posts Collection Blaze Template MongoDB Oplog Observers Client - 1 Client - 2 Sending Posts document Meteor Server Newly added Posts document
  • 83. Update & Remove Let’s update the code to add more methods under imports/api/posts/methods.js 'posts.like': function (postId, userId = this.userId) { check(postId, String); check(userId, String); return Posts.update({ _id: postId, }, { $inc: { likes: 1 }, $push: { users: userId }, }); },
  • 84. Update & Remove Let’s update the code to add more methods under imports/api/posts/methods.js ...continue 'posts.unlike': function (postId, userId = this.userId) { check(postId, String); check(userId, String); return Posts.update({ _id: postId, }, { $inc: { likes: -1 }, $pop: { users: userId }, }); },
  • 85. Update & Remove Add events for calling above methods from client side Add below code to imports/ui/pages/post/post.js Template.post.events({ 'click #like': function () { Meteor.call('posts.like', this._id, Meteor.userId()); }, 'click #unlike': function () { Meteor.call('posts.unlike', this._id, Meteor.userId()); }, });
  • 87. Unit Tests To write unit test cases use below command to add package practicalmeteor:mocha meteor add practicalmeteor:mocha To collect published data in test environment use below command to add package johanbrook:publication-collector meteor add johanbrook:publication-collector
  • 88. Unit Tests Add below code to imports/api/posts/server/publications.test.js import { assert } from 'meteor/practicalmeteor:chai'; import Posts from '../posts.js'; import { PublicationCollector } from 'meteor/johanbrook:publication-collector'; import './publications.js';
  • 89. Unit Tests Add below code to imports/api/posts/server/publications.test.js ...continue describe('posts publications', () => { beforeEach(() => { Posts.remove({}); Posts.insert({ title: 'NX homepage', description: 'This is our home page', author: 'userId', likes: 2, }); });
  • 90. Unit Tests Add below code to imports/api/posts/server/publications.test.js ...continue describe('posts.all', () => { it('sends all posts', (done) => { const collector = new PublicationCollector(); collector.collect('posts.all', (collections) => { assert.equal(collections.posts.length, 1); done(); }); }); }); });
  • 91. Unit Tests Add below code to imports/api/posts/methods.test.js import { Meteor } from 'meteor/meteor'; import { assert } from 'meteor/practicalmeteor:chai'; import Posts from './posts.js'; import './methods.js'; if (Meteor.isServer) { describe('post methods', () => { beforeEach(() => { Posts.remove({}); });
  • 92. Unit Tests Add below code to imports/api/posts/methods.test.js ...continue it('can add a new post', () => { const addPost = Meteor.server.method_handlers['posts.insert']; addPost.apply({}, ['test', 'test description', 'user_id']); assert.equal(Posts.find().count(), 1); }); }); }
  • 93. Unit Tests Add below code to imports/api/posts/posts.test.js import { Meteor } from 'meteor/meteor'; import { assert } from 'meteor/practicalmeteor:chai'; import Posts from './posts.js'; if (Meteor.isServer) { describe('post collection', () => { it('insert correctly', () => { const postId = Posts.insert({ title: 'Test post', description: 'Test description', userId: 'user_id', author: 'test', users: [], likes: 0, });
  • 94. Unit Tests Add below code to imports/api/posts/posts.test.js ...continue const added = Posts.find({ _id: postId }); const collectionName = added._getCollectionName(); const count = added.count(); assert.equal(collectionName, 'posts'); assert.equal(count, 1); }); }); }
  • 95. Unit Tests Add below code to imports/api/users/users.test.js import { Meteor } from 'meteor/meteor'; import { assert } from 'meteor/practicalmeteor:chai'; import Users from './users.js'; if (Meteor.isServer) { describe('users collection', () => { it('insert correctly', () => { const userId = Accounts.createUser({ email: 'testuser@test.com', password: '123445', });
  • 96. Unit Tests Add below code to imports/api/users/users.test.js ...continue const added = Users.find({ _id: userId }); const collectionName = added._getCollectionName(); const count = added.count(); assert.equal(collectionName, 'users'); assert.equal(count, 1); }); }); }
  • 98. Deployment ● Sign up for Galaxy, https://www.meteor.com/galaxy/signup ● Configure your MongoDB database using: mLab, compose or MongoDB Atlas. ● Create a settings.json file with following info: { "galaxy.meteor.com": { "env": { "NODE_ENV": "production", "MONGO_URL": "mongodb://sapna:sapna@ds143767.mlab.com:43767/posts " } }, "public": { } }
  • 99. Deployment cont. ● Login to your meteor account using: meteor login ● Create a deploy.sh file with following info: DEPLOY_HOSTNAME=us-east-1.galaxy-deploy. meteor.com meteor deploy http://posts-demo.meteorapp.com --settings settings.json ● Instead of using this URL http://posts-demo.meteorapp.com you can use your own domain. ● Type the following command to deploy your app: sh deploy.sh
  • 102. Maintenance using APM ● Meteor APM formally Kadira ● Add Meteor APM to your app: meteor add mdg:meteor-apm-agent ● App will send data to Meteor APM ● Re-deploy sh deploy.sh
  • 105. Mobile app build ● Download tools for Mobiles like Android Studio, Xcode ● Running on an iOS simulator (Mac Only): ○ meteor install-sdk ios ○ meteor add-platform ios ○ meteor run ios ● Running on an iOS device: ○ meteor run ios-device ● Running on an Android emulator: ○ meteor install-sdk android ○ meteor run android ● Running on an Android device: ○ meteor run android-device Note: Currently, Meteor on Windows does not support mobile builds.
  • 106. Thank You. Questions? By Sapna Upreti @sapna0214