流星初学者指南

流星是一个Web应用程序平台。它是初学者和专家的工具,它使启动变得超级容易,并提供了可利用的庞大图书馆生态系统

流星是一个Web应用程序平台。

现代的Web应用程序可以极其复杂来写。特别是对于初学者。

流星是初学者和专家的工具,它使容易上手,并提供您可以利用的庞大的库生态系统。

JavaScript

流星方法是最早在客户端和服务器上无缝使用JavaScript的流行方法之一。

加上MongoDB的,这是一个数据库,用于存储JSON格式对象,并使用Javascript作为查询语言,它使JavaScript无处不在。

流星还附带迷你蒙哥在前端中,这是一个与MongoDB API兼容的前端数据库,完全用JavaScript编写。

即时的

流星以其实时功能而闻名,但是实时到底是什么呢?假设您要创建一个聊天应用程序。流星为您提供了完美的功能。

想要创建一个内部通讯应用程序吗?太完美了。项目管理应用程序?基本上,任何可以通知用户或应根据其他用户操作来更新事物的应用程序,或者诸如API之类的第三方事物都可以更改显示的信息,可以很容易地立即将这些更改通知给查看该应用程序的用户与其他解决方案相比。

感觉很快

一个叫做延迟补偿为您提供了一个技巧,即使接口仍需要与远程服务器通信,也可以使接口快速消失。最重要的是,它在实现方面对您是免费的,这意味着它已在Meteor中提供支持,您无需做任何事情即可启用它。

开源的

当然,Meteor完全是开源的。

这很简单

在流星中事情看起来非常简单,因为它们简单的。

复杂的事情以后会导致奇怪的错误或棘手的问题。流星为我们提供了干净,漂亮的API和功能。

出色的包装系统

关于Meteor的最酷的事情是,由于它既可以支持前端也可以支持后端,并且与数据库深度集成,前端和后端代码都可以放在一个包中,并在双方之间为我们无缝地工作。这就是为什么我们可以用一行代码来添加完整的用户管理。

流星如何改善生活

流星给你全栈平台, 通过提供客户端框架和服务器端框架。更重要的是,Meteor甚至为您提供了两者之间的沟通渠道。叫做DDP,我们稍后再讨论。

您不再需要将不同的框架,语言,工具和代码库粘合在一起。对于不希望浪费时间和资源使事情变得比他们本应困难的独立开发人员,小型创业公司甚至更大的组织而言,这是巨大的。

当流星可能不适合您

静态内容网站还有其他更好的平台可以建立。如果您只需要输出一些没有太多交互性的HTML,请使用静态网站生成器。

截至撰写时,流星不支持SQL数据库,这在许多情况下可能是一件好事,但在其他情况下可能需要它们。当然,您可以编写自己的使用SQL数据的过程。

流星七原则

流星是建立在以下七个原则之上的。它们已列在项目文档中,它们是基本原理,因此我们将在此处报告。

原则在日常生活中受到尊重时总是很重要。

线上数据

流星不会通过网络发送HTML。服务器发送数据,并让客户端呈现它。

一种语言

使用Meteor,您可以在以下位置编写应用程序的客户端和服务器部分:JavaScript

数据库无处不在

您可以使用相同的方法从客户端或服务器访问数据库。

延迟补偿

在客户端上,Meteor会预取数据并模拟模型,以使其看起来像服务器方法调用立即返回。

全堆反应性

在Meteor中,实时是默认设置。从数据库到模板的所有层均在必要时自动更新。

拥抱生态

Meteor是开源的,并且与现有的开源工具和框架集成在一起。

简单等于生产力

使某件事情看起来简单的最好方法是使它实际上简单。流星的主要功能具有干净,经典漂亮的API。

安装步骤

在OSX和Linux上,安装Meteor就像在“操作系统”终端中键入以下命令一样简单:

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

Install Meteor

而已!

Windows有其自己的官方安装程序,因此请在官方网站上进行检查。

流星的第一步

让我们创建第一个Meteor应用程序。

打开操作系统终端,进入您将在其中托管项目的目录,然后键入

meteor create hello-world

Create a Meteor app

流星将在您的手机中为您创建新的应用hello-world目录。

现在进入该目录并输入

meteor

这将启动Meteor Web服务器,您可以通过将浏览器指向来访问您的第一个Meteor应用程序。http://localhost:3000

Hello Meteor

很简单,对吧?

代码演练

让我们遍历应用程序代码以了解其工作原理。

如果现在还不太清楚,请不要担心,稍后将介绍和解释许多概念。

几年前,这个Meteor示例应用程序只包含一个JavaScript文件,用于客户端和服务器,使用Meteor.isClientMeteor.isServer检查应用程序是在客户端还是在服务器上运行。

示例应用程序摆脱了这种方法,以及如何server/main.js文件,以及其他文件client/

client / main.html

如果您打开client/main.html文件,您可以看到该应用程序的源代码:

<head>
  <title>hello-world</title>
</head>

<body> <h1>Welcome to Meteor!</h1>

{{> hello}} {{> info}} </body>

<template name=“hello”> <button>Click Me</button> <p>You’ve pressed the button {{counter}} times.</p> </template>

<template name=“info”> <h2>Learn Meteor!</h2> <ul> … </ul> </template>

流星认识到headbody标记并将其放置在页面内容中的正确位置。这意味着通过包含一个head标签,其所有内容将添加到“真实”页面head标签。

同样的情况适用于body标签。它们是两个主要标签。

所有其余的应用程序必须放在单独的位置template标签。

特别的{{ }}您看到的括号由空格键,这是一种模板语言,与车把具有一些独特的功能,使其与Meteor完美搭配

在hello-world示例中,

{{> hello}}

包括hello模板,以及

{{counter}}

在 - 的里面hello模板在模板上下文中查找计数器值。

客户端/ main.js

这是内容client/main.js文件:

import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';

import ‘./main.html’;

Template.hello.onCreated(function helloOnCreated() { // counter starts at 0 this.counter = new ReactiveVar(0); });

Template.hello.helpers({ counter() { return Template.instance().counter.get(); }, });

Template.hello.events({ ‘click button’(event, instance) { // increment the counter when button is clicked instance.counter.set(instance.counter.get() + 1); }, });

该代码设置了一个ReactiveVar,反应变量。反应变量公开了一个setter和一个getter。通过使用setter,当其值更改时,将使用get()检索所有使用该值的函数。

反应变量的值使用{{counter}}片段,这称为counter()我们在此处定义的模板帮助器。

它首先将该变量初始化为零,然后将其值设置为在按钮中单击该按钮时递增。hello模板。

要处理点击,您需要对hello模板。在这种情况下,我们拦截了点击buttonHTML元素。发生这种情况时,您增加Session.counter值。

在流星服务器代码中,server/main.js, 有一个Meteor.startup调用,它在Meteor准备就绪时仅调用传递的函数。现在没有任何内容,但是稍后我们将看到它如何有用。

流星CLI

安装Meteor时,您会得到名为meteor

这是一个非常有用的工具,您已经使用它来创建第一个应用程序,并且从一开始我们只需要知道它可以做的一小部分。

让我们介绍一下从Meteor开始使用的四个最有用的命令。

流星

如果在空目录中,请键入

meteor

you’ll get an error because Meteor was not initialized in that directory.

If you instead type meteor in a folder that has a Meteor project already created (see meteor create here below), Meteor will start up and create the server, initialize the database and you’ll be able to open the Meteor website.

meteor create

If inside a directory you type

meteor create my_app_name

Meteor will initialize a new Meteor project in a subfolder named my_app_name.

meteor add

Inside your Meteor project already initialized, calling

meteor add package_name

will lookup the package_name package and will install it in the current project.

You can run this command in a separate terminal window while the Meteor app is running, and you’ll get the package functionality without the need to restart the Meteor server.

meteor remove

Inside your Meteor project already initialized, calling

meteor remove package_name

will remove the package with that name from your project.

Isomorphic

The term isomorphic identifies a framework where client-side code and server-side code are written in the same language. This implies that any piece of code could run both on the server and on the client, unless it’s tied to a context-specific action.

In the past 10 years Web Applications have been built by clearly separating the server and the client code. Server code run PHP, Ruby, Python code. That code could never work on the frontend-side, because the browser does not support those languages.

Browsers are only capable of executing code written in JavaScript.

With the meteoric rise of Node.js in the last few years, and what was built on top, now we have the chance to build an entire application in the same language: JavaScript.

Meteor takes the isomorphic concept even further, by transparently running every file in your project, unless you don’t want it to do it, on both sides of the platform, doing different things based on the context, clearly explained by the Meteor documentation.

This is an amazing opportunity and advantage that Meteor enables by building a “super-platform” on top of Node.js and the Browser platforms, enabling you to build applications faster and better than ever.

Isomorphic refers to JavaScript code that runs with little to no modifications on the client and on the server. It’s code that takes care of both what runs inside the browser, and the what runs on the server.

Meteor is an isomorphic framework. This is great because we can write concise applications that now even share some pieces of code between client and server code.

It enables you to become a full-stack developer, because you no longer need to deeply know two separate stacks to work on both sides of the application.

The classical example is the one of an HTTP request. On the browser you’d do an AJAX call. On the server you’d use your stack-specific code.

Using Meteor, you can use the same function HTTP.get() provided by the http package, on both sides, just like when you install the Axios library.

Meteor.isServer, Meteor.isClient

Meteor exposes two boolean variables to determine where the code is running:

  • Meteor.isServer
  • Meteor.isClient


Put them inside an if statement to run some code part just on one side of the platform.

For example:

if (Meteor.isClient) {
  alert('Hello dear user!')
} else if (Meteor.isServer) {
  //running server-side
}

Special directories

Putting lots of Meteor.isServer and Meteor.isClient checks in the application is not ideal of course.

First, the code can quickly grow complicated and not nice to read. Second, even the server code is sent to the client. This is bad because you’d better keep server-side code private, and also because you send unnecessary code which slows down loading times.

That’s why Meteor has two special folders that automatically take care of the distinction for us: client and server

Whatever you put in the client directory is not loaded on the server side.

Whatever you put in the server directory is not sent to the client.

Another advantage of keeping this distinction is that assets put in the client folders are never taken into consideration during the build phases.

Session variables and template helpers

Here’s a simple example on combining Session variables and template helpers to achieve a simple case of selecting the current comment selected in a list.

In our template.html file:

<template name="main">
  {{#each comments}}
    {{> comment}}
  {{/each}}
</template>

<template name=“comment”> <div class="{{#if selected}}selected{{/if}}"> <p>{{this.comment}}</p> </div> </template>

In template.js:

Session.set('selectedComment', null)

Template.main.helpers({ comments: function() { return Comments.find() } })

Template.comment.helpers({ selected: function() { return Session.equals(‘selectedComment’, this._id) } })

Template.comment.events({ ‘click div’ : function(e, t) { Session.set(‘selectedComment’, this._id) } })

In this case any time I click a comment, that comment becomes the selected comment, and we can show it full-size, fetch the other comments made by the user or do some other fancy stuff.

Reactive programming

First, a clarification: Meteor’s reactivity has nothing to do with React, the other very popular JavaScript framework.

What is reactive programming, you say? Reactive programming is a programming paradigm.

Reactive programming is nothing new, nor something that Meteor introduced. But, what Meteor did was making reactive programming easy to use.

Actually, you’re most probably already using reactive programming without even knowing about it.

What is reactive programming

Reactive programming allows you to write code that automatically refreshes and re-calculates functions and values when something that you depend on changed.

For example, data in the database changed? You need to re-display it in the client.

That variable that counts the number of comments changed because you added a comment? Everything that depends on it, or shows it, must react to that change and re-compute the values.

That works by having Reactive Sources. The database for example is a reactive source. When something changes inside it, it notifies the JavaScript variables that depend on those changes. Those variables are invalidated and must be recalculated according to the new data available.

Reactive sources

Meteor has a list of things that are reactive, and those drive the entire application. Not everything is reactive, just those things listed here:

  • Reactive variables, defined using new ReactiveVar()

  • The data coming from the database is a reactive data source, because by subscribing to a publication you get a cursor, and that cursor is reactive. Any change to the collection represented by the cursor will trigger a recomputation of anything that uses it.

  • Talking about subscriptions, when a subscription is available on the client its .ready() method is called. That is a reactive data source.

  • Session variables are a reactive data source. When one changes a session variable by using .set(), everything that depends on those will be recalculate or re-rendered.

  • The user methods Meteor.user() and Meteor.userId() are a reactive data source.

  • Meteor.status(), which is a client-side method that returns the current client-server connection status, is a reactive data source.

  • Meteor.loggingIn(), which returns true if the user is currently doing a login, is a reactive data source.

Reactive computations

Whatever changes upon a reactive source change is a reactive computation. It’s some piece of code, a function, that needs to run again when a reactive source it depends on changes.

An example of reactive computation is the template helpers: every time a reactive data source that involves a template helper changes, the template re-renders it.

Defining your own reactive computations

You can define your own reactive computations, and react when something changes upstream, by using Tracker.autorun().

This function:

Tracker.autorun(function () {
  var currentPage = Session.get('currentPage')
  alert("The current page is " + currentPage)
})

Will trigger an alert whenever you call Session.set('currentPage', 'whatever') without you needing to add callbacks or other observers.

Meteor Publications

One of the key features of Meteor is provided by the data layer.

Since Meteor manages both the server and the client, I can explain the concept in this way:

  • The server creates a publication
  • The client subscribes to that publication
  • Meteor keeps everything in sync

The server can precisely determine what each client will see. Each publication can be tailored upon parameters and user permissions.

Let’s do a simple Pub/Sub introduction on standard MongoDB collections.

Server publication

Here’s an example of a server code creating a publication for comments that have been approved:

//server-side code
Meteor.publish('comments', () => {
  return Comments.find({ approved: true })
})

Or we want to create a publication for comments made on a specific article:

Meteor.publish('comments', (articleId) => {
  return Comments.find({ articleId: articleId })
})

The publish function is called every time a client subscribes.

Client subscription

On the client the code is very easy. For example, let’s subscribe to all comments:

Meteor.subscribe('comments')

Let’s instead subscribe to comments made on the current article:

const articleId = 23
Meteor.subscribe('comments', articleId)

Once the subscribe method has been called, Meteor fills the client-side Minimongo (the MongoDB instance running on the client) with the data you chose to sent it.

Typically the client-side database only gets some records, the minimum amount needed to initialize and work. You don’t replicate the whole server-side Mongo collection content of course, but you request data as needed.

Autopublish

Meteor makes it very easy for us to start diving into a project without worrying at all about publications and subscriptions.

It does this by including the autopublish package in every new project. That that packages does is, it automatically creates a pub/sub for each collection we have defined, syncing all the data available from server to client.

When you’ll reach the phase when you need more control on the data available to each user or view, you’ll just remove the autopublish package and you’ll manually define what you need.

Minimongo

Minimongo is your best friend when developing in Meteor. Ok, if you feel you have lots of best friends when using Meteor, I feel the same. Everything in Meteor is provided to ease your life.

Minimongo, in particular, is a frontend implementation of MongoDB. You might say.. what? Why do I need another database?

MongoDB: The Meteor Database

As of writing, Meteor has just one officially supported database: MongoDB.

You may wonder why. First, let me clarify: you can actually use any database you want, but to enjoy at 100% the marvels of Meteor you need to use Mongo. There are currently community projects that are working towards adding support for many other databases.

MongoDB in two words

MongoDB is a document-based database. It features high performance, high availability, easy scalability. It stores its documents in database collections. A document is a set of key-value pairs (JSON), and it has a dynamic schema. This means that each document does not need to have the same set of fields, but you have a great freedom in managing data.

Meteor and MongoDB

As said, a MongoDB document is a JSON object. Meteor Collections are directly related to MongoDB collections, and the Meteor internals make sure that when data changes in a MongoDB Collection tracked by Meteor, the Meteor Collection is updated too.

Minimongo

In short, in Meteor you typically create a collection, and that collection is available on both client and server code. When you do some database query or database processing, you don’t “think” whether you should do that operation on the client-side database, or the server-side database: to a certain extent, they’re mostly the same thing. And they talk to each other transparently.

This means that when the server-side database (MongoDB) is updated by someone else or something happens in the app you’re using, or even you add something in a second browser window.. everything that’s stored in the database that interests your current session is pushed by the server MongoDB to the Minimongo running inside your browser.

The same happens for the opposite: you push a post to the Posts collection? Minimongo is updated immediately, while Meteor pushes the update to the MongoDB database server side.

This has the nice effect of making your changes, your pages and interactions feel immediate to the user.

Minimongo is a MongoDB client-side clone

Minimongo tries to perfectly emulate a subset of MongoDB. You can insert data, remove data, search, sort, update.. with the same exact MongoDB APIs.

This means you can also easily port some parts of your code from the server to the client-side very easily when it makes sense.

Client-side storage facility

With Minimongo you have a fantastic client-side storage that you can query using the MongoDB Query functionalities.

You can of course create instances of a Minimongo collection just client-side, when you don’t have the need to sync a collection to the server.

Not only, you can observe for database changes, and your interface can react to those changes easily.

Latency Compensation

Latency Compensation is part of the Meteor Principles. There, it’s described in this way: on the client, Meteor prefetches data and simulates models to make it look like server method calls return instantly.

What does it mean?

On a typical Web Application, when you do some kind of action, the action is passed to the server to be processed, and then you need to wait until the server responds, and then changes are applied to the page you’re interacting with.

More modern applications rely on AJAX to provide a better turnaround and avoid refreshing a page on every action, but still many apps rely on the server response prior to taking any action. Better apps introduce some sort of latency compensation, but it’s a manual process.

Meteor introduces the concept of Latency Compensation deep into his philosophy and it’s enabled by default, without you needing to do anything special to work with it.

For example when you add an item to a collection, meanwhile the item will be sent to the server, it’s already added to the collection view on your page.

It feels better, because the app feels immediately responsive (it is).

If there is an error you’ll be notified later and you have the opportunity to handle things in the best way for each situation.

Meteor Collections

An application typically needs to display data of some sort.

Be it messages, comments, posts, books, addresses, pictures.. everything is a collection of something.

Meteor being deeply integrated with MongoDB takes the Mongo database collection concept and takes it to the application level.

In both the client and server contexts, you’ll typically interact with data by interacting with data collections.

How does it work?

Create your first collection

Messages = new Mongo.Collection('messages')

This defines a global variable messages, which will be visible across the entire App on client and server.

This code needs to run on both the client and the server, so you’ll put it for example under collections/messages.js.

While the code running in the two environments is the same, what it does is different:

  • on the server it creates a Mongo collection if it’s not already existing, and then it will load the cursor in the Messages variable
  • on the client it will instantiate a Minimongo local collection. The app once instantiated will link that to the server-side collection, and will automatically keep them in sync.

Adding items to a collection

You’ll be able to insert items into a collection using the .insert() method on the collection cursor:

Messages.insert({message: "Hi"})

Showing the collection in the template

In a template you can use the {{#each}} Spacebars helper to navigate the collection and print all values stored in it:

<template name="messages">
  {{#each messages}}
    {{message}}
  {{/each}}
</template>