Unit Tests
Set up your tests with the Package.onTest
handler, which has an interface that's parallel to that of the onUse
handler. The tests will need to depend on the package that you have just created. For example, if your package is the email
package, you have to call api.use('email')
in order to test the package.
If you used meteor create
to set up your package, Meteor will create the required scaffolding in package.js
, and you'll only need to add unit test code in the _test.js
file that was created.
Define dependencies and expose package methods for unit tests.
Arguments
- func Function
-
A function that takes in the package control 'api' object, which keeps track of dependencies and exports.
External Packages and Plugins
Meteor packages can include NPM packages and Cordova plugins by using Npm.depends
and Cordova.depends
in the package.js
file.
Specify which NPM packages your Meteor package depends on.
Arguments
- dependencies Object
-
An object where the keys are package names and the values are one of:
- Version numbers in string form
- Http(s) URLs to a git commit by SHA.
- Git URLs in the format described here
Https URL example:
Npm.depends({ moment: "2.8.3", async: "https://github.com/caolan/async/archive/71fa2638973dafd8761fa5457c472a312cc820fe.tar.gz" });
Git URL example:
Npm.depends({ moment: "2.8.3", async: "git+https://github.com/caolan/async#master" });
Require a package that was specified using Npm.depends()
.
Arguments
- name String
-
The name of the package to require.
Specify which Cordova / PhoneGap plugins your Meteor package depends on.
Plugins are installed from plugins.cordova.io, so the plugins and versions specified must exist there. Alternatively, the version can be replaced with a GitHub tarball URL as described in the Cordova page of the Meteor wiki on GitHub.
Arguments
- dependencies Object
-
An object where the keys are plugin names and the values are version numbers or GitHub tarball URLs in string form. Example:
Cordova.depends({ "org.apache.cordova.camera": "0.3.0" });
Alternatively, with a GitHub URL:
Cordova.depends({ "org.apache.cordova.camera": "https://github.com/apache/cordova-plugin-camera/tarball/d84b875c449d68937520a1b352e09f6d39044fbf" });
Define a build plugin. A build plugin extends the build process for apps and packages that use this package. For example, the coffeescript
package uses a build plugin to compile CoffeeScript source files into JavaScript.
Options
- name String
-
A cosmetic name, must be unique in the package.
- use String or Array of Strings
-
Meteor packages that this plugin uses, independent of the packages specified in api.onUse.
- sources Array of Strings
-
The source files that make up the build plugin, independent from api.addFiles.
- npmDependencies Object
-
An object where the keys are NPM package names, and the values are the version numbers of required NPM packages, just like in Npm.depends.
Inside a build plugin source file specified in Package.registerBuildPlugin, add a handler to compile files with a certain file extension.
Arguments
- fileExtension String
-
The file extension that this plugin should handle, without the first dot. Examples:
"coffee"
,"coffee.md"
. - handler Function
-
A function that takes one argument, a CompileStep object.
Documentation for CompileStep is available on the GitHub Wiki.
Mobile Config File
If your Meteor application targets mobile platforms such as iOS or Android, you can configure your app's metadata and build process in a special top-level file called mobile-config.js
which is not included in your application and is used only for this configuration.
The code snippet below is an example mobile-config.js
file. The rest of this section will explain the specific API commands in greater detail.
// This section sets up some basic app metadata, // the entire section is optional. App.info({ id: 'com.example.matt.uber', name: 'über', description: 'Get über power in one button click', author: 'Matt Development Group', email: 'contact@example.com', website: 'http://example.com' }); // Set up resources such as icons and launch screens. App.icons({ 'iphone': 'icons/icon-60.png', 'iphone_2x': 'icons/icon-60@2x.png', // ... more screen sizes and platforms ... }); App.launchScreens({ 'iphone': 'splash/Default~iphone.png', 'iphone_2x': 'splash/Default@2x~iphone.png', // ... more screen sizes and platforms ... }); // Set PhoneGap/Cordova preferences App.setPreference('BackgroundColor', '0xff0000ff'); App.setPreference('HideKeyboardFormAccessoryBar', true); App.setPreference('Orientation', 'default'); App.setPreference('Orientation', 'all', 'ios'); // Pass preferences for a particular PhoneGap/Cordova plugin App.configurePlugin('com.phonegap.plugins.facebookconnect', { APP_ID: '1234567890', API_KEY: 'supersecretapikey' });
App.info(options)
Set your mobile app's core configuration information.
Options
- id, version, name, description, author, email, website String
-
Each of the options correspond to a key in the app's core configuration as described in the Cordova documentation.
App.setPreference(name, value, [platform])
Add a preference for your build as described in the Cordova documentation.
Arguments
- name String
-
A preference name supported by Cordova's
config.xml
. - value String
-
The value for that preference.
- platform String
-
Optional. A platform name (either
ios
orandroid
) to add a platform-specific preference.
App.accessRule(pattern, [options])
Set a new access rule based on origin domain for your app. By default your application has a limited list of servers it can contact. Use this method to extend this list.
Default access rules:
-
tel:*
,geo:*
,mailto:*
,sms:*
,market:*
are allowed and are handled by the system (e.g. opened in the phone app or an email client) -
http://localhost:*
is used to serve the app's assets from. - The domain or address of the Meteor server to connect to for DDP and hot code push of new versions.
Read more about domain patterns in Cordova docs.
Starting with Meteor 1.0.4 access rule for all domains and protocols (<access origin="*"/>
) is no longer set by default due to certain kind of possible attacks.
Arguments
- pattern String
-
The pattern defining affected domains or URLs.
Options
- type String
-
Possible values:
-
'intent'
: Controls which URLs the app is allowed to ask the system to open. (e.g. in the phone app or an email client). -
'navigation'
: Controls which URLs the WebView itself can be navigated to (can also needed for iframes). -
'network'
or undefined: Controls which network requests (images, XHRs, etc) are allowed to be made.
-
- launchExternal Boolean
-
(Deprecated, use
type: 'intent'
instead.)
App.configurePlugin(id, config)
Set the build-time configuration for a Cordova plugin.
Arguments
- id String
-
The identifier of the plugin you want to configure.
- config Object
-
A set of key-value pairs which will be passed at build-time to configure the specified plugin.
App.icons(icons)
Set the icons for your mobile app.
Arguments
- icons Object
-
An Object where the keys are different devices and screen sizes, and values are image paths relative to the project root directory.
Valid key values:
-
iphone_2x
(120x120) -
iphone_3x
(180x180) -
ipad
(76x76) -
ipad_2x
(152x152) -
ipad_pro
(167x167) -
ios_settings
(29x29) -
ios_settings_2x
(58x58) -
ios_settings_3x
(87x87) -
ios_spotlight
(40x40) -
ios_spotlight_2x
(80x80) -
android_mdpi
(48x48) -
android_hdpi
(72x72) -
android_xhdpi
(96x96) -
android_xxhdpi
(144x144) -
android_xxxhdpi
(192x192)
-
App.launchScreens(launchScreens)
Set the launch screen images for your mobile app.
Arguments
- launchScreens Object
-
A dictionary where keys are different devices, screen sizes, and orientations, and the values are image paths relative to the project root directory.
For Android, launch screen images should be special "Nine-patch" image files that specify how they should be stretched. See the Android docs.
Valid key values:
-
iphone_2x
(640x960) -
iphone5
(640x1136) -
iphone6
(750x1334) -
iphone6p_portrait
(1242x2208) -
iphone6p_landscape
(2208x1242) -
ipad_portrait
(768x1024) -
ipad_portrait_2x
(1536x2048) -
ipad_landscape
(1024x768) -
ipad_landscape_2x
(2048x1536) -
android_mdpi_portrait
(320x470) -
android_mdpi_landscape
(470x320) -
android_hdpi_portrait
(480x640) -
android_hdpi_landscape
(640x480) -
android_xhdpi_portrait
(720x960) -
android_xhdpi_landscape
(960x720) -
android_xxhdpi_portrait
(1080x1440) -
android_xxhdpi_landscape
(1440x1080)
-
Meteor supports a variety of add-on packages and third party libraries. While you can build great applications using only the Meteor core functionality, optional packages can make development even faster and better.
Packages can be added to a Meteor project with:
meteor add <package_name>
and removed with:
meteor remove <package_name>
Some of the packages that Meteor Development Group maintains include:
appcache
The appcache
package stores the static parts of a Meteor application (the client side Javascript, HTML, CSS, and images) in the browser's application cache. To enable caching simply add the appcache
package to your project.
Once a user has visited a Meteor application for the first time and the application has been cached, on subsequent visits the web page loads faster because the browser can load the application out of the cache without contacting the server first.
Hot code pushes are loaded by the browser in the background while the app continues to run. Once the new code has been fully loaded the browser is able to switch over to the new code quickly.
The application cache allows the application to be loaded even when the browser doesn't have an Internet connection, and so enables using the app offline.
(Note however that the appcache
package by itself doesn't make data available offline: in an application loaded offline, a Meteor Collection will appear to be empty in the client until the Internet becomes available and the browser is able to establish a DDP connection).
To turn AppCache off for specific browsers use:
Meteor.AppCache.config({ chrome: false, firefox: false });
The supported browsers that can be enabled or disabled include, but are not limited to, android
, chrome
, chromium
, chromeMobileIOS
, firefox
, ie
, mobileSafari
and safari
.
Browsers limit the amount of data they will put in the application cache, which can vary due to factors such as how much disk space is free. Unfortunately if your application goes over the limit rather than disabling the application cache altogether and running the application online, the browser will instead fail that particular update of the cache, leaving your users running old code.
Thus it's best to keep the size of the cache below 5MB. The appcache
package will print a warning on the Meteor server console if the total size of the resources being cached is over 5MB.
If you have files too large to fit in the cache you can disable caching by URL prefix. For example,
Meteor.AppCache.config({onlineOnly: ['/online/']});
causes files in your public/online
directory to not be cached, and so they will only be available online. You can then move your large files into that directory and refer to them at the new URL:
<img src="/online/bigimage.jpg">
If you'd prefer not to move your files, you can use the file names themselves as the URL prefix:
Meteor.AppCache.config({ onlineOnly: [ '/bigimage.jpg', '/largedata.json' ] });
though keep in mind that since the exclusion is by prefix (this is a limitation of the application cache manifest), excluding /largedata.json
will also exclude such URLs as /largedata.json.orig
and /largedata.json/file1
.
For more information about how Meteor interacts with the application cache, see the AppCache page in the Meteor wiki.
accounts-ui
A turn-key user interface for Meteor Accounts.
To add Accounts and a set of login controls to an application, add the accounts-ui
package and at least one login provider package: accounts-password
, accounts-facebook
, accounts-github
, accounts-google
, accounts-twitter
, or accounts-weibo
.
Then simply add the {{> loginButtons}}
helper to an HTML file. This will place a login widget on the page. If there is only one provider configured and it is an external service, this will add a login/logout button. If you use accounts-password
or use multiple external login services, this will add a "Sign in" link which opens a dropdown menu with login options. If you plan to position the login dropdown in the right edge of the screen, use {{> loginButtons align="right"}}
in order to get the dropdown to lay itself out without expanding off the edge of the screen.
To configure the behavior of {{> loginButtons}}
, use Accounts.ui.config
.
accounts-ui
also includes modal popup dialogs to handle links from sendResetPasswordEmail
, sendVerificationEmail
, and sendEnrollmentEmail
. These do not have to be manually placed in HTML: they are automatically activated when the URLs are loaded.
If you want to control the look and feel of your accounts system a little more, we recommend reading the useraccounts section of the Meteor Guide.
audit-argument-checks
This package causes Meteor to require that all arguments passed to methods and publish functions are check
ed. Any method that does not pass each one of its arguments to check
will throw an error, which will be logged on the server and which will appear to the client as a 500 Internal server error
. This is a simple way to help ensure that your app has complete check coverage.
Methods and publish functions that do not need to validate their arguments can simply run check(arguments, [Match.Any])
to satisfy the audit-argument-checks
coverage checker.
coffeescript
CoffeeScript is a little language that compiles into JavaScript. It provides a simple syntax without lots of braces and parentheses. The code compiles one-to-one into the equivalent JS, and there is no interpretation at runtime.
CoffeeScript is supported on both the client and the server. Files ending with .coffee
, .litcoffee
, or .coffee.md
are automatically compiled to JavaScript.
Namespacing and CoffeeScript
Here's how CoffeeScript works with Meteor's namespacing.
Per the usual CoffeeScript convention, CoffeeScript variables are file-scoped by default (visible only in the
.coffee
file where they are defined.)When writing a package, CoffeeScript-defined variables can be exported like any other variable (see Writing Packages). Exporting a variable pulls it up to package scope, meaning that it will be visible to all of the code in your app or package (both
.js
and.coffee
files).Package-scope variables declared in
.js
files are visible in any.coffee
files in the same app or project.There is no way to make a package-scope variable from a
.coffee
file other than exporting it. We couldn't figure out a way to make this fit naturally inside the CoffeeScript language. If you want to use package-scope variables with CoffeeScript, one way is to make a short.js
file that declares all of your package-scope variables. They can then be used and assigned to from.coffee
files.If you want to share variables between
.coffee
files in the same package, and don't want to separately declare them in a.js
file, we have an experimental feature that you may like. An object calledshare
is visible in CoffeeScript code and is shared across all.coffee
files in the same package. So, you can writeshare.foo
for a value that is shared between all CoffeeScript code in a package, but doesn't escape that package.
Heavy CoffeeScript users, please let us know how this arrangement works for you, whether share
is helpful for you, and anything else you'd like to see changed.
ecmascript
This package lets you use new JavaScript language features that are part of the ECMAScript 2015 specification but are not yet supported by all engines or browsers. Unsupported syntax is automatically translated into standard JavaScript that behaves the same way.
This video from the July 2015 Meteor Devshop gives an overview of how the package works, and what it provides.
Usage
The ecmascript
package registers a compiler plugin that transpiles ECMAScript 2015+ to ECMAScript 5 (standard JS) in all .js
files. By default, this package is pre-installed for all new apps and packages.
To add this package to an existing app, run the following command from your app directory:
meteor add ecmascript
To add the ecmascript
package to an existing package, include the statement api.use('ecmascript');
in the Package.onUse
callback in your package.js
file:
Package.onUse(function (api) { api.use('ecmascript'); });
Supported ES2015 Features
Syntax
The ecmascript
package uses Babel to compile ES2015 syntax to ES5 syntax. Many but not all ES2015 features can be simulated by Babel, and ecmascript
enables most of the features supported by Babel.
Here is a list of the Babel transformers that are currently enabled:
es3.propertyLiterals
Makes it safe to use reserved keywords likecatch
as unquoted keys in object literals. For example,{ catch: 123 }
is translated to{ "catch": 123 }
.es3.memberExpressionLiterals
Makes it safe to use reserved keywords as property names. For example,object.catch
is translated toobject["catch"]
.es6.arrowFunctions
Provides a shorthand for function expressions. For example,[1, 2, 3].map(x => x + 1)
evaluates to[2, 3, 4]
. Ifthis
is used in the body of the arrow function, it will be automatically bound to the value ofthis
in the enclosing scope.es6.literals
Adds support for binary and octal numeric literals. For example,0b111110111 === 503
and0o767 === 503
.es6.templateLiterals
Enables multi-line strings delimited by backticks instead of quotation marks, with variable interpolation:js var name = "Ben"; var message = `My name is: ${name}`;
-
es6.classes
Enablesclass
syntax:class Base { constructor(a, b) { this.value = a * b; } }</p> <p>class Derived extends Base { constructor(a, b) { super(a + 1, b + 1); } }</p> <p>var d = new Derived(2, 3); d.value; // 12
-
es6.constants
Allows defining block-scoped variables that are not allowed to be redefined:const GOLDEN_RATIO = (1 + Math.sqrt(5)) / 2;</p> <p>// This reassignment will be forbidden by the compiler: GOLDEN_RATIO = "new value";
-
es6.blockScoping
Enables thelet
andconst
keywords as alternatives tovar
. The key difference is that variables defined usinglet
orconst
are visible only within the block where they are declared, rather than being visible anywhere in the enclosing function. For example:function example(condition) { let x = 0; if (condition) { let x = 1; console.log(x); } else { console.log(x); x = 2; } return x; }</p> <p>example(true); // logs 1, returns 0 example(false); // logs 0, returns 2
es6.properties.shorthand
Allows omitting the value of an object literal property when the desired value is held by a variable that has the same name as the property key. For example, instead of writing{ x: x, y: y, z: "asdf" }
you can just write{ x, y, z: "asdf" }
. Methods can also be written without the: function
property syntax:js var obj = { oldWay: function (a, b) { ... }, newWay(a, b) { ... } };
-
es6.properties.computed
Allows object literal properties with dynamically computed keys:var counter = 0; function getKeyName() { return "key" + counter++; }</p> <p>var obj = { [getKeyName()]: "zero", [getKeyName()]: "one", };</p> <p>obj.key0; // "zero" obj.key1; // "one"
-
es6.parameters
Default expressions for function parameters, evaluated whenever the parameter isundefined
,...rest
parameters for capturing remaining arguments without using thearguments
object:function add(a = 0, ...rest) { rest.forEach(n => a += n); return a; }</p> <p>add(); // 0 add(1, 2, 3); // 6
es6.spread
Allows an array of arguments to be interpolated into a list of arguments to a function call,new
expression, or array literal, without usingFunction.prototype.apply
:js add(1, ...[2, 3, 4], 5); // 15 new Node("name", ...children); [1, ...[2, 3, 4], 5]; // [1, 2, 3, 4, 5]
es6.forOf
Provides an easy way to iterate over the elements of a collection:js let sum = 0; for (var x of [1, 2, 3]) { sum += x; } x; // 6
-
es6.destructuring
Destructuring is the technique of using an array or object pattern on the left-hand side of an assignment or declaration, in place of the usual variable or parameter, so that certain sub-properties of the value on the right-hand side will be bound to identifiers that appear within the pattern. Perhaps the simplest example is swapping two variables without using a temporary variable:js [a, b] = [b, a];
Extracting a specific property from an object:js let { username: name } = user; // is equivalent to let name = user.username;
Instead of taking a single opaqueoptions
parameter, a function can use an object destructuring pattern to name the expected options:function run({ command, args, callback }) { ... }</p> <p>run({ command: "git", args: ["status", "."], callback(error, status) { ... }, unused: "whatever" });
es7.objectRestSpread
Supports catch-all...rest
properties in object literal declarations and assignments:js let { x, y, ...rest } = { x: 1, y: 2, a: 3, b: 4 }; x; // 1 y; // 2 rest; // { a: 3, b: 4 }
Also enables...spread
properties in object literal expressions:js let n = { x, y, ...rest }; n; // { x: 1, y: 2, a: 3, b: 4 }
es7.trailingFunctionCommas
Allows the final parameter of a function to be followed by a comma, provided that parameter is not a...rest
parameter.flow
Permits the use of Flow type annotations. These annotations are simply stripped from the code, so they have no effect on the code's behavior, but you can run theflow
tool over your code to check the types if desired.
Polyfills
The ECMAScript 2015 standard library has grown to include new APIs and data structures, some of which can be implemented ("polyfilled") using JavaScript that runs in all engines and browsers today. Here are three new constructors that are guaranteed to be available when the ecmascript
package is installed:
Promise
APromise
allows its owner to wait for a value that might not be available yet. See this tutorial for more details about the API and motivation. The MeteorPromise
implementation is especially useful because it runs all callback functions in recycledFiber
s, so you can use any Meteor API, including those that yield (e.g.HTTP.get
,Meteor.call
, orMongoCollection
), and you never have to callMeteor.bindEnvironment
.Map
An associative key-value data structure where the keys can be any JavaScript value (not just strings). Lookup and insertion take constant time.Set
A collection of unique JavaScript values of any type. Lookup and insertion take constant time.Symbol
An implementation of the globalSymbol
s namespace that enables a number of other ES2015 features, such asfor
-of
loops andSymbol.iterator
methods:[1,2,3][Symbol.iterator]()
.-
Polyfills for the following
Object
-related methods:Object.assign
Object.is
Object.setPrototypeOf
-
Object.prototype.toString
(fixes@@toStringTag
support)
Complete reference here.
-
Polyfills for the following
String
-related methods:String.fromCodePoint
String.raw
String.prototype.includes
String.prototype.startsWith
String.prototype.endsWith
String.prototype.repeat
String.prototype.codePointAt
-
String.prototype.trim
Complete reference here.
-
Polyfills for the following
Array
-related methods:Array.from
Array.of
Array.prototype.copyWithin
Array.prototype.fill
Array.prototype.find
Array.prototype.findIndex
Complete reference here.
-
Polyfills for the following
Function
-related properties:-
Function.prototype.name
(fixes IE9+) -
Function.prototype[Symbol.hasInstance]
(fixes IE9+)
Complete reference here.
-
jquery
jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development.
The jquery
package adds the jQuery library to the client JavaScript bundle. It has no effect on the server.
In addition to the jquery
package, Meteor provides several jQuery plugins as separate packages. These include:
less
LESS extends CSS with dynamic behavior such as variables, mixins, operations and functions. It allows for more compact stylesheets and helps reduce code duplication in CSS files.
With the less
package installed, .less
files in your application are automatically compiled to CSS and the results are included in the client CSS bundle.
If you want to @import
a file, give it the extension .import.less
to prevent Meteor from processing it independently.
markdown
This package lets you use Markdown in your templates. It's easy: just put your markdown inside {{#markdown}} ... {{/markdown}}
tags. You can still use all of the usual Meteor template features inside a Markdown block, such as {{#each}}
, and you still get reactivity.
Example:
{{#markdown}}I am using __markdown__.{{/markdown}}
outputs
<p>I am using <strong>markdown</strong>.</p>
modules
Though Meteor 1.2 introduced support for many new ECMAScript 2015 features, one of the most notable omissions was ES2015 import
and export
syntax. Meteor 1.3 fills that gap with a fully standards-compliant module system that works on both the client and the server, solves multiple long-standing problems for Meteor applications (such as controlling file load order), and yet maintains full backwards compatibility with existing Meteor code. This document explains the usage and key features of the new module system.
Enabling modules
We think you’re going to love the new module system, and that's why it will be installed by default for all new apps and packages. Nevertheless, the modules
package is totally optional, and it will be up to you to add it to existing apps and/or packages.
For apps, this is as easy as meteor add modules
, or (even better) meteor add ecmascript
, since the ecmascript
package implies the modules
package.
For packages, you can enable modules
by adding api.use("modules")
to the Package.onUse
or Package.onTest
sections of your package.js
file.
Now, you might be wondering what good the modules
package is without the ecmascript
package, since ecmascript
enables import
and export
syntax. By itself, the modules
package provides the CommonJS require
and exports
primitives that may be familiar if you’ve ever written Node code, and the ecmascript
package simply compiles import
and export
statements to CommonJS. The require
and export
primitives also allow Node modules to run within Meteor application code without modification. Furthermore, keeping modules
separate allows us to use require
and exports
in places where using ecmascript
is tricky, such as the implementation of the ecmascript
package itself.
While the modules
package is useful by itself, we very much encourage using the ecmascript
package (and thus import
and export
) instead of using require
and exports
directly. If you need convincing, here’s a presentation that explains the differences: http://benjamn.github.io/empirenode-2015
Basic syntax
Although there are a number of different variations of import
and export
syntax, this section describes the essential forms that everyone should know.
First, you can export
any named declaration on the same line where it was declared:
// exporter.js export var a = ...; export let b = ...; export const c = ...; export function d() {...} export function* e() {...} export class F {...}
These declarations make the variables a
, b
, c
(and so on) available not only within the scope of the exporter.js
module, but also to other modules that import
from exporter.js
.
If you prefer, you can export
variables by name, rather than prefixing their declarations with the export
keyword:
// exporter.js function g() {...} let h = g(); // at the end of the file export {g, h};
All of these exports are named, which means other modules can import them using those names:
// importer.js import {a, c, F, h} from "./exporter"; new F(a, c).method(h);
If you’d rather use different names, you’ll be glad to know export
and import
statements can rename their arguments:
// exporter.js export {g as x}; g(); // same as calling y() in importer.js
// importer.js import {x as y} from "./exporter"; y(); // same as calling g() in exporter.js
As with CommonJS module.exports
, it is possible to define a single default export:
// exporter.js export default any.arbitrary(expression);
This default export may then be imported without curly braces, using any name the importing module chooses:
// importer.js import Value from "./exporter"; // Value is identical to the exported expression
Unlike CommonJS module.exports
, the use of default exports does not prevent the simultaneous use of named exports. Here is how you can combine them:
// importer.js import Value, {a, F} from "./exporter";
In fact, the default export is conceptually just another named export whose name happens to be "default":
// importer.js import {default as Value, a, F} from "./exporter";
These examples should get you started with import
and export
syntax. For further reading, here is a very detailed explanation by Axel Rauschmayer of every variation of import
and export
syntax.
Modular application structure
Before the release of Meteor 1.3, the only way to share values between files in an application was to assign them to global variables or communicate through shared variables like Session
(variables which, while not technically global, sure do feel syntactically identical to global variables). With the introduction of modules, one module can refer precisely to the exports of any other specific module, so global variables are no longer necessary.
If you are familiar with modules in Node, you might expect modules not to be evaluated until the first time you import them. However, because earlier versions of Meteor evaluated all of your code when the application started, and we care about backwards compatibility, eager evaluation is still the default behavior.
If you would like a module to be evaluated lazily (in other words: on demand, the first time you import it, just like Node does it), then you should put that module in an imports/
directory (anywhere in your app, not just the root directory), and include that directory when you import the module: import {stuff} from "./imports/lazy"
. Note: files contained by node_modules/
directories will also be evaluated lazily (more on that below).
Lazy evaluation will very likely become the default behavior in a future version of Meteor, but if you want to embrace it as fully as possible in the meantime, we recommend putting all your modules inside either client/imports/
or server/imports/
directories, with just a single entry point for each architecture: client/main.js
and server/main.js
. The main.js
files will be evaluated eagerly, giving your application a chance to import modules from the imports/
directories.
Modular package structure
If you are a package author, in addition to putting api.use("modules")
or api.use("ecmascript")
in the Package.onUse
section of your package.js
file, you can also use a new API called api.mainModule
to specify the main entry point for your package:
Package.describe({ name: "my-modular-package" }); Npm.depends({ moment: "2.10.6" }); Package.onUse(function (api) { api.use("modules"); api.mainModule("server.js", "server"); api.mainModule("client.js", "client"); api.export("Foo"); });
Now server.js
and client.js
can import other files from the package source directory, even if those files have not been added using the api.addFiles
function.
When you use api.mainModule
, the exports of the main module are exposed globally as Package["my-modular-package"]
, along with any symbols exported by api.export
, and thus become available to any code that imports the package. In other words, the main module gets to decide what value of Foo
will be exported by api.export
, as well as providing other properties that can be explicitly imported from the package:
// In an application that uses my-modular-package: import {Foo as ExplicitFoo, bar} from "meteor/my-modular-package"; console.log(Foo); // Auto-imported because of api.export. console.log(ExplicitFoo); // Explicitly imported, but identical to Foo. console.log(bar); // Exported by server.js or client.js, but not auto-imported.
Note that the import
is from "meteor/my-modular-package"
, not from "my-modular-package"
. Meteor package identifier strings must include the prefix meteor/...
to disambiguate them from npm packages.
Finally, since this package is using the new modules
package, and the package Npm.depends
on the "moment" npm package, modules within the package can import moment from "moment"
on both the client and the server. This is great news, because previous versions of Meteor allowed npm imports only on the server, via Npm.require
.
Local node_modules
Before Meteor 1.3, the contents of node_modules
directories in Meteor application code were completely ignored. When you enable modules
, those useless node_modules
directories suddenly become infinitely more useful:
meteor create modular-app cd modular-app mkdir node_modules npm install moment echo 'import moment from "moment";' >> modular-app.js echo 'console.log(moment().calendar());' >> modular-app.js meteor
When you run this app, the moment
library will be imported on both the client and the server, and both consoles will log output similar to: Today at 7:51 PM
. Our hope is that the possibility of installing Node modules directly within an app will reduce the need for npm wrapper packages such as https://atmospherejs.com/momentjs/moment.
A version of the npm
command comes bundled with every Meteor installation, and (as of Meteor 1.3) it's quite easy to use: meteor npm ...
is synonymous with npm ...
, so meteor npm install moment
will work in the example above. (Likewise, if you don't have a version of node
installed, or you want to be sure you're using the exact same version of node
that Meteor uses, meteor node ...
is a convenient shortcut.) That said, you can use any version of npm
that you happen to have available. Meteor's module system only cares about the files installed by npm
, not the details of how npm
installs those files.
File load order
Before Meteor 1.3, the order in which application files were evaluated was dictated by a set of rules described in the Structuring Your Application section of the docs (see File Load Order subheading). These rules could become frustrating when one file depended on a variable defined by another file, particularly when the first file was evaluated after the second file.
Thanks to modules, any load-order dependency you might imagine can be resolved by adding an import
statement. So if a.js
loads before b.js
because of their file names, but a.js
needs something defined by b.js
, then a.js
can simply import
that value from b.js
:
// a.js import {bThing} from "./b"; console.log(bThing, "in a.js");
// b.js export var bThing = "a thing defined in b.js"; console.log(bThing, "in b.js");
Sometimes a module doesn’t actually need to import anything from another module, but you still want to be sure the other module gets evaluated first. In such situations, you can use an even simpler import
syntax:
// c.js import "./a"; console.log("in c.js");
No matter which of these modules is imported first, the order of the console.log
calls will always be:
console.log(bThing, "in b.js"); console.log(bThing, "in a.js"); console.log("in c.js");
oauth-encryption
Encrypts sensitive login secrets stored in the database such as a login service's application secret key and users' access tokens.
Generating a Key
The encryption key is 16 bytes, encoded in base64.
To generate a key:
$ ~/.meteor/tools/latest/bin/node -e 'console.log(require("crypto").randomBytes(16).toString("base64"))'
Using oauth-encryption with accounts
On the server only, use the oauthSecretKey
option to Accounts.config
:
Accounts.config({oauthSecretKey: "onsqJ+1e4iGFlV0nhZYobg=="});
This call to Accounts.config
should be made at load time (place at the top level of your source file), not called from inside of a Meteor.startup
block.
To avoid storing the secret key in your application's source code, you can use Meteor.settings
:
Accounts.config({oauthSecretKey: Meteor.settings.oauthSecretKey});
Migrating unencrypted user tokens
This example for Twitter shows how existing unencrypted user tokens can be encrypted. The query finds user documents which have a Twitter access token but not the algorithm
field which is created when the token is encrypted. The relevant fields in the service data are then encrypted.
Meteor.users.find({ $and: [ { 'services.twitter.accessToken': {$exists: true} }, { 'services.twitter.accessToken.algorithm': {$exists: false} } ] }). forEach(function (userDoc) { var set = {}; _.each(['accessToken', 'accessTokenSecret', 'refreshToken'], function (field) { var plaintext = userDoc.services.twitter[field]; if (!_.isString(plaintext)) return; set['services.twitter.' + field] = OAuthEncryption.seal( userDoc.services.twitter[field], userDoc._id ); }); Meteor.users.update(userDoc._id, {$set: set}); });
Using oauth-encryption without accounts
If you're using the oauth packages directly instead of through the Meteor accounts packages, you can load the OAuth encryption key directly using OAuthEncryption.loadKey
:
OAuthEncryption.loadKey("onsqJ+1e4iGFlV0nhZYobg==");
If you call retrieveCredential
(such as Twitter.retrieveCredential
) as part of your process, you'll find when using oauth-encryption that the sensitive service data fields will be encrypted.
You can decrypt them using OAuth.openSecrets
:
var credentials = Twitter.retrieveCredential(token); var serviceData = OAuth.openSecrets(credentials.serviceData);
Using oauth-encryption on Windows
This package depends on npm-node-aes-gcm, which requires you to have OpenSSL installed on your system to run. To install OpenSSL on Windows, use one of the binaries on this page. Don't forget to install the Visual Studio 2008 redistributables if you don't have them yet.
random
The random
package provides several functions for generating random numbers. It uses a cryptographically strong pseudorandom number generator when possible, but falls back to a weaker random number generator when cryptographically strong randomness is not available (on older browsers or on servers that don't have enough entropy to seed the cryptographically strong generator).
- Random.id([n])
Returns a unique identifier, such as
"Jjwjg6gouWLXhMGKW"
, that is likely to be unique in the whole world. The optional argumentn
specifies the length of the identifier in characters and defaults to 17.- Random.secret([n])
Returns a random string of printable characters with 6 bits of entropy per character. The optional argument
n
specifies the length of the secret string and defaults to 43 characters, or 256 bits of entropy. UseRandom.secret
for security-critical secrets that are intended for machine, rather than human, consumption.- Random.fraction()
Returns a number between 0 and 1, like
Math.random
.- Random.choice(arrayOrString)
Returns a random element of the given array or string.
- Random.hexString(n)
Returns a random string of
n
hexadecimal digits.
spacebars
Spacebars is a Meteor template language inspired by Handlebars. It shares some of the spirit and syntax of Handlebars, but it has been tailored to produce reactive Meteor templates when compiled.
Getting Started
A Spacebars template consists of HTML interspersed with template tags, which are delimited by {{
and }}
(two curly braces).
<template name="myPage"> <h1>{{pageTitle}}</h1> {{> nav}} {{#each posts}} <div class="post"> <h3>{{title}}</h3> <div class="post-content"> {{{content}}} </div> </div> {{/each}} </template>
As illustrated by the above example, there are four major types of template tags:
{{pageTitle}}
- Double-braced template tags are used to insert a string of text. The text is automatically made safe. It may contain any characters (like<
) and will never produce HTML tags.{{> nav}}
- Inclusion template tags are used to insert another template by name.{{#each}}
- Block template tags are notable for having a block of content. The block tags#if
,#each
,#with
, and#unless
are built in, and it is also possible define custom ones. Some block tags, like#each
and#with
, establish a new data context for evaluating their contents. In the above example,{{title}}
and{{content}}
most likely refer to properties of the current post (though they could also refer to template helpers).{{{content}}}
- Triple-braced template tags are used to insert raw HTML. Be careful with these! It's your job to make sure the HTML is safe, either by generating it yourself or sanitizing it if it came from a user input.
Reactivity Model
Spacebars templates update reactively at a fine-grained level in response to changing data.
Each template tag's DOM is updated automatically when it evaluates to a new value, while avoiding unnecessary re-rendering as much as possible. For example, a double-braced tag replace its text node when its text value changes. An #if
re-renders its contents only when the condition changes from truthy to falsy or vice versa.
Identifiers and Paths
A Spacebars identifier is either a JavaScript identifier name or any string enclosed in square brackets ([
and ]
). There are also the special identifiers this
(or equivalently, .
) and ..
. Brackets are required to use one of the following as the first element of a path: else
, this
, true
, false
, and null
. Brackets are not required around JavaScript keywords and reserved words like var
and for
.
A Spacebars path is a series of one or more identifiers separated by either .
or /
, such as foo
, foo.bar
, this.name
, ../title
, or foo.[0]
(numeric indices must be enclosed in brackets).
Name Resolution
The first identifier in a path is resolved in one of two ways:
Indexing the current data context. The identifier
foo
refers to thefoo
property of the current data context object.As a template helper. The identifier
foo
refers to a helper function (or constant value) that is accessible from the current template.
Template helpers take priority over properties of the data context.
If a path starts with ..
, then the enclosing data context is used instead of the current one. The enclosing data context might be the one outside the current #each
, #with
, or template inclusion.
Path Evaluation
When evaluating a path, identifiers after the first are used to index into the object so far, like JavaScript's .
. However, an error is never thrown when trying to index into a non-object or an undefined value.
In addition, Spacebars will call functions for you, so {{foo.bar}}
may be taken to mean foo().bar
, foo.bar()
, or foo().bar()
as appropriate.
Helper Arguments
An argument to a helper can be any path or identifier, or a string, boolean, or number literal, or null.
Double-braced and triple-braced template tags take any number of positional and keyword arguments:
{{frob a b c verily=true}}
calls:
frob(a, b, c, Spacebars.kw({verily: true}))
Spacebars.kw
constructs an object that is instanceof Spacebars.kw
and whose .hash
property is equal to its argument.
The helper's implementation can access the current data context as this
.
Inclusion and Block Arguments
Inclusion tags ({{> foo}}
) and block tags ({{#foo}}
) take a single data argument, or no argument. Any other form of arguments will be interpreted as an object specification or a nested helper:
Object specification: If there are only keyword arguments, as in
{{#with x=1 y=2}}
or{{> prettyBox color=red}}
, the keyword arguments will be assembled into a data object with properties named after the keywords.Nested Helper: If there is a positional argument followed by other (positional or keyword arguments), the first argument is called on the others using the normal helper argument calling convention.
Template Tag Placement Limitations
Unlike purely string-based template systems, Spacebars is HTML-aware and designed to update the DOM automatically. As a result, you can't use a template tag to insert strings of HTML that don't stand on their own, such as a lone HTML start tag or end tag, or that can't be easily modified, such as the name of an HTML element.
There are three main locations in the HTML where template tags are allowed:
- At element level (i.e. anywhere an HTML tag could go)
- In an attribute value
- In a start tag in place of an attribute name/value pair
The behavior of a template tag is affected by where it is located in the HTML, and not all tags are allowed at all locations.
Double-braced Tags
A double-braced tag at element level or in an attribute value typically evalutes to a string. If it evalutes to something else, the value will be cast to a string, unless the value is null
, undefined
, or false
, which results in nothing being displayed.
Values returned from helpers must be pure text, not HTML. (That is, strings should have <
, not <
.) Spacebars will perform any necessary escaping if a template is rendered to HTML.
SafeString
If a double-braced tag at element level evalutes to an object created with Spacebars.SafeString("<span>Some HTML</span>")
, the HTML is inserted at the current location. The code that calls SafeString
is asserting that this HTML is safe to insert.
In Attribute Values
A double-braced tag may be part of, or all of, an HTML attribute value:
<input type="checkbox" class="checky {{moreClasses}}" checked={{isChecked}}>
An attribute value that consists entirely of template tags that return null
, undefined
, or false
is considered absent; otherwise, the attribute is considered present, even if its value is empty.
Dynamic Attributes
A double-braced tag can be used in an HTML start tag to specify an arbitrary set of attributes:
<div {{attrs}}>...</div> <input type=checkbox {{isChecked}}>
The tag must evaluate to an object that serves as a dictionary of attribute name and value strings. For convenience, the value may also be a string or null. An empty string or null expands to {}
. A non-empty string must be an attribute name, and expands to an attribute with an empty value; for example, "checked"
expands to {checked: ""}
(which, as far as HTML is concerned, means the checkbox is checked).
To summarize:
Return Value | Equivalent HTML |
---|---|
"" or null or {}
| |
"checked" or {checked: ""}
|
checked |
{checked: "", 'class': "foo"} |
checked class=foo |
"checked class=foo" |
ERROR, string is not an attribute name |
You can combine multiple dynamic attributes tags with other attributes:
<div id=foo class={{myClass}} {{attrs1}} {{attrs2}}>...</div>
Attributes from dynamic attribute tags are combined from left to right, after normal attributes, with later attribute values overwriting previous ones. Multiple values for the same attribute are not merged in any way, so if attrs1
specifies a value for the class
attribute, it will overwrite {{myClass}}
. As always, Spacebars takes care of recalculating the element's attributes if any of myClass
, attrs1
, or attrs2
changes reactively.
Triple-braced Tags
Triple-braced tags are used to insert raw HTML into a template:
<div class="snippet"> {{{snippetBody}}} </div>
The inserted HTML must consist of balanced HTML tags. You can't, for example, insert "</div><div>"
to close an existing div and open a new one.
This template tag cannot be used in attributes or in an HTML start tag.
Inclusion Tags
An inclusion tag takes the form {{> templateName}}
or {{> templateName
dataObj}}
. Other argument forms are syntactic sugar for constructing a data object (see Inclusion and Block Arguments).
An inclusion tag inserts an instantiation of the given template at the current location. If there is an argument, it becomes the data context, much as if the following code were used:
{{#with dataObj}} {{> templateName}} {{/with}}
Instead of simply naming a template, an inclusion tag can also specify a path that evalutes to a template object, or to a function that returns a template object.
Note that the above two points interact in a way that can be surprising! If foo
is a template helper function that returns another template, then {{>foo bar}}
will first push bar
onto the data context stack then call foo()
, due to the way this line is expanded as shown above. You will need to use Template.parentData(1)
to access the original context. This differs from regular helper calls like {{foo bar}}
, in which bar
is passed as a parameter rather than pushed onto the data context stack.
Function Returning a Template
If an inclusion tag resolves to a function, the function must return a template object or null
. The function is reactively re-run, and if its return value changes, the template will be replaced.
Block Tags
Block tags invoke built-in directives or custom block helpers, passing a block of template content that may be instantiated once, more than once, or not at all by the directive or helper.
{{#block}} <p>Hello</p> {{/block}}
Block tags may also specify "else" content, separated from the main content by the special template tag {{else}}
.
A block tag's content must consist of HTML with balanced tags.
Block tags can be used inside attribute values:
<div class="{{#if done}}done{{else}}notdone{{/if}}"> ... </div>
If/Unless
An #if
template tag renders either its main content or its "else" content, depending on the value of its data argument. Any falsy JavaScript value (including null
, undefined
, 0
, ""
, and false
) is considered false, as well as the empty array, while any other value is considered true.
{{#if something}} <p>It's true</p> {{else}} <p>It's false</p> {{/if}}
#unless
is just #if
with the condition inverted.
With
A #with
template tag establishes a new data context object for its contents. The properties of the data context object are where Spacebars looks when resolving template tag names.
{{#with employee}} <div>Name: {{name}}</div> <div>Age: {{age}}</div> {{/with}}
We can take advantage of the object specification form of a block tag to define an object with properties we name:
{{#with x=1 y=2}} {{{getHTMLForPoint this}}} {{/with}}
If the argument to #with
is falsy (by the same rules as for #if
), the content is not rendered. An "else" block may be provided, which will be rendered instead.
If the argument to #with
is a string or other non-object value, it may be promoted to a JavaScript wrapper object (also known as a boxed value) when passed to helpers, because JavaScript traditionally only allows an object for this
. Use String(this)
to get an unboxed string value or Number(this)
to get an unboxed number value.
Each
An #each
template tag takes a sequence argument and inserts its content for each item in the sequence, setting the data context to the value of that item:
<ul> {{#each people}} <li>{{name}}</li> {{/each}} </ul>
The newer variant of #each
doesn't change the data context but introduces a new variable that can be used in the body to refer to the current item:
<ul> {{#each person in people}} <li>{{person.name}}</li> {{/each}} </ul>
The argument is typically a Meteor cursor (the result of collection.find()
, for example), but it may also be a plain JavaScript array, null
, or undefined
.
An "else" section may be provided, which is used (with no new data context) if there are zero items in the sequence at any time.
You can use a special variable @index
in the body of #each
to get the 0-based index of the currently rendered value in the sequence.
Reactivity Model for Each
When the argument to #each
changes, the DOM is always updated to reflect the new sequence, but it's sometimes significant exactly how that is achieved. When the argument is a Meteor live cursor, the #each
has access to fine-grained updates to the sequence -- add, remove, move, and change callbacks -- and the items are all documents identified by unique ids. As long as the cursor itself remains constant (i.e. the query doesn't change), it is very easy to reason about how the DOM will be updated as the contents of the cursor change. The rendered content for each document persists as long as the document is in the cursor, and when documents are re-ordered, the DOM is re-ordered.
Things are more complicated if the argument to the #each
reactively changes between different cursor objects, or between arrays of plain JavaScript objects that may not be identified clearly. The implementation of #each
tries to be intelligent without doing too much expensive work. Specifically, it tries to identify items between the old and new array or cursor with the following strategy:
- For objects with an
_id
field, use that field as the identification key - For objects with no
_id
field, use the array index as the identification key. In this case, appends are fast but prepends are slower. - For numbers or strings, use their value as the identification key.
In case of duplicate identification keys, all duplicates after the first are replaced with random ones. Using objects with unique _id
fields is the way to get full control over the identity of rendered elements.
Let
The #let
tag creates a new alias variable for a given expression. While it doesn't change the data context, it allows to refer to an expression (helper, data context, another variable) with a short-hand within the template:
{{#let name=person.bio.firstName color=generateColor}} <div>{{name}} gets a {{color}} card!</div> {{/let}}
Variables introduced this way take precedence over names of templates, global helpers, fields of the current data context and previously introduced variables with the same name.
Custom Block Helpers
To define your own block helper, simply declare a template, and then invoke it using {{#someTemplate}}
(block) instead of {{> someTemplate}}
(inclusion) syntax.
When a template is invoked as a block helper, it can use {{>
Template.contentBlock}}
and {{> Template.elseBlock}}
to include the block content it was passed.
Here is a simple block helper that wraps its content in a div:
<template name="note"> <div class="note"> {{> Template.contentBlock}} </div> </template>
You would invoke it as:
{{#note}} Any content here {{/note}}
Here is an example of implementing #unless
in terms of #if
(ignoring for the moment that unless
is a built-in directive):
<template name="unless"> {{#if this}} {{> Template.elseBlock}} {{else}} {{> Template.contentBlock}} {{/if}} </template>
Note that the argument to #unless
(the condition) becomes the data context in the unless
template and is accessed via this
. However, it would not work very well if this data context was visible to Template.contentBlock
, which is supplied by the user of unless
.
Therefore, when you include {{> Template.contentBlock}}
, Spacebars hides the data context of the calling template, and any data contexts established in the template by #each
and #with
. They are not visible to the content block, even via ..
. Put another way, it's as if the {{> Template.contentBlock}}
inclusion occurred at the location where {{#unless}}
was invoked, as far as the data context stack is concerned.
You can pass an argument to {{> Template.contentBlock}}
or {{>
Template.elseBlock}}
to invoke it with a data context of your choice. You can also use {{#if Template.contentBlock}}
to see if the current template was invoked as a block helper rather than an inclusion.
Comment Tags
Comment template tags begin with {{!
and can contain any characters except for }}
. Comments are removed upon compilation and never appear in the compiled template code or the generated HTML.
{{! Start of a section}} <div class="section"> ... </div>
Comment tags also come in a "block comment" form. Block comments may contain {{
and }}
:
{{!-- This is a block comment. We can write {{foo}} and it doesn't matter. {{#with x}}This code is commented out.{{/with}} --}}
Comment tags can be used wherever other template tags are allowed.
Nested sub-expressions
Sometimes an argument to a helper call is best expressed as a return value of some other expression. For this and other cases, one can use parentheses to express the evaluation order of nested expressions.
{{capitalize (getSummary post)}}
In this example, the result of the getSummary
helper call will be passed to the capitalize
helper.
Sub-expressions can be used to calculate key-word arguments, too:
{{> tmpl arg=(helper post)}}
HTML Dialect
Spacebars templates are written in standard HTML extended with additional syntax (i.e. template tags).
Spacebars validates your HTML as it goes and will throw a compile-time error if you violate basic HTML syntax in a way that prevents it from determining the structure of your code.
Spacebars is not lenient about malformed markup the way a web browser is. While the latest HTML spec standardizes how browsers should recover from parse errors, these cases are still not valid HTML. For example, a browser may recover from a bare <
that does not begin a well-formed HTML tag, while Spacebars will not. However, gone are the restrictions of the XHTML days; attribute values do not have to quoted, and tags are not case-sensitive, for example.
You must close all HTML tags except the ones specified to have no end tag, like BR, HR, IMG and INPUT. You can write these tags as <br>
or equivalently <br/>
.
The HTML spec allows omitting some additional end tags, such as P and LI, but Spacebars doesn't currently support this.
Top-level Elements in a .html
file
Technically speaking, the <template>
element is not part of the Spacebars language. A foo.html
template file in Meteor consists of one or more of the following elements:
<template name="myName">
- The<template>
element contains a Spacebars template (as defined in the rest of this file) which will be compiled to theTemplate.myName
component.<head>
- Static HTML that will be inserted into the<head>
element of the default HTML boilerplate page. Cannot contain template tags. If<head>
is used multiple times (perhaps in different files), the contents of all of the<head>
elements are concatenated.<body>
- A template that will be inserted into the<body>
of the main page. It will be compiled to theTemplate.body
component. If<body>
is used multiple times (perhaps in different files), the contents of all of the<body>
elements are concatenated.
Escaping Curly Braces
To insert a literal {{
, {{{
, or any number of curly braces, put a vertical bar after it. So {{|
will show up as {{
, {{{|
will show up as {{{
, and so on.
underscore
Underscore is a utility-belt library for JavaScript that provides support for functional programming. It is invaluable for writing clear, concise JavaScript in a functional style.
The underscore
package defines the _
namespace on both the client and the server.
Currently, underscore is included in all projects, as the Meteor core depends on it. _ is available in the global namespace on both the client and the server even if you do not include this package. However if you do use underscore in your application, you should still add the package as we will remove the default underscore in the future.
We have slightly modified the way Underscore differentiates between objects and arrays in collection functions. The original Underscore logic is to treat any object with a numeric length
property as an array (which helps it work properly on NodeList
s). In Meteor's version of Underscore, objects with a numeric length
property are treated as objects if they have no prototype (specifically, if x.constructor === Object
.
webapp
The webapp
package is what lets your Meteor app serve content to a web browser. It is included in the meteor-base
set of packages that is automatically added when you run meteor create
. You can easily build a Meteor app without it - for example if you wanted to make a command-line tool that still used the Meteor package system and DDP.
This package also allows you to add handlers for HTTP requests. This lets other services access your app's data through an HTTP API, allowing it to easily interoperate with tools and frameworks that don't yet support DDP.
webapp
exposes the connect API for handling requests through WebApp.connectHandlers
. Here's an example that will let you handle a specific URL:
// Listen to incoming HTTP requests, can only be used on the server WebApp.connectHandlers.use("/hello", function(req, res, next) { res.writeHead(200); res.end("Hello world from: " + Meteor.release); });
WebApp.connectHandlers.use([path], handler)
has two arguments:
path - an optional path field. This handler will only be called on paths that match this string. The match has to border on a /
or a .
. For example, /hello
will match /hello/world
and /hello.world
, but not /hello_world
.
handler - this is a function that takes three arguments:
- req - a Node.js IncomingMessage object with some extra properties. This argument can be used to get information about the incoming request.
-
res - a Node.js ServerResponse object. Use this to write data that should be sent in response to the request, and call
res.end()
when you are done. - next - a function. Calling this function will pass on the handling of this request to the next relevant handler.
Command line
The following are some of the more commonly used commands in the meteor
command-line tool. This is just an overview and does not mention every command or every option to every command; for more details, use the meteor help
command.
meteor help
Get help on meteor command line usage. Running meteor help
by itself will list the common meteor commands. Running meteor help command
will print detailed help about the command.
meteor run
Run a meteor development server in the current project. Searches upward from the current directory for the root directory of a Meteor project. Whenever you change any of the application's source files, the changes are automatically detected and applied to the running application.
You can use the application by pointing your web browser at localhost:3000. No Internet connection is required.
This is the default command. Simply running meteor
is the same as meteor run
.
To pass additional options to Node.js use the NODE_OPTIONS
environment variable. For example: NODE_OPTIONS='--debug'
or NODE_OPTIONS='--debug-brk'
Run meteor help run
to see the full list of options.
meteor debug
Run the project, but suspend the server process for debugging.
The server process will be suspended just before the first statement of server code that would normally execute. In order to continue execution of server code, use either the web-based Node Inspector or the command-line debugger (further instructions will be printed in the console).
Breakpoints can be set using the debugger
keyword, or through the web UI of Node Inspector ("Sources" tab).
The server process debugger will listen for incoming connections from debugging clients, such as node-inspector, on port 5858 by default. To specify a different port use the --debug-port <port>
option.
The same debugging functionality can be achieved by adding the --debug-port <port>
option to other meteor
tool commands, such as meteor run
and meteor test-packages
.
meteor create name
Create a new Meteor project. By default, makes a subdirectory named name and copies in the template app. You can pass an absolute or relative path.
You can use the --package
option, to create a new package. If used in an existing app, this command will create a package in the packages directory.
meteor login / logout
Log in and out of your account using Meteor's authentication system.
You can pass METEOR_SESSION_FILE=token.json
before meteor login
to generate a login session token so you don't have to share your login credentials with third-party service providers. You can revoke the token at any time from your accounts settings page.
Once you have your account you can log in and log out from the command line, and check your username with meteor whoami
.
meteor deploy site
Deploy the project in your current directory to Galaxy.
You can deploy in debug mode by passing --debug
. This will leave your source code readable by your favorite in-browser debugger, just like it is in local development mode.
To delete an application you've deployed, specify the --delete
option along with the site.
You can add information specific to a particular deployment of your application by using the --settings
option. The argument to --settings
is a file containing any JSON string. The object in your settings file will appear on the server side of your application in Meteor.settings
.
Settings are persistent. When you redeploy your app, the old value will be preserved unless you explicitly pass new settings using the --settings
option. To unset Meteor.settings
, pass an empty settings file.
meteor update
Attempts to bring you to the latest version of Meteor, and then to upgrade your packages to their latest versions. By default, update will not break compatibility.
For example, let's say packages A and B both depend on version 1.1.0 of package X. If a new version of A depends on X@2.0.0, but there is no new version of package B, running meteor update
will not update A, because doing so will break package B.
You can pass in the flag --packages-only
to update only the packages, and not the release itself. Similarly, you can pass in names of packages (meteor update foo:kittens baz:cats
) to only update specific packages.
Every project is pinned to a specific release of Meteor. You can temporarily try using your package with another release by passing the --release
option to any command; meteor update
changes the pinned release.
Sometimes, Meteor will ask you to run meteor update --patch
. Patch releases are special releases that contain only very minor changes (usually crucial bug fixes) from previous releases. We highly recommend that you always run update
--patch
when prompted.
You may also pass the --release
flag to act as an override to update to a specific release. This is an override: if it cannot find compatible versions of packages, it will log a warning, but perform the update anyway. This will only change your package versions if necessary.
meteor add package
Add packages to your Meteor project. By convention, names of community packages include the name of the maintainer. For example: meteor add iron:router
. You can add multiple packages with one command.
Optionally, adds version constraints. Running meteor add package@1.1.0
will add the package at version 1.1.0
or higher (but not 2.0.0
or higher). If you want to use version 1.1.0
exactly, use meteor add package@=1.1.0
. You can also 'or' constraints together: for example, meteor add 'package@=1.0.0 || =2.0.1'
means either 1.0.0 (exactly) or 2.0.1 (exactly).
To remove a version constraint for a specific package, run meteor add
again without specifying a version. For example above, to stop using version 1.1.0
exactly, run meteor add package
.
meteor remove package
Removes a package previously added to your Meteor project. For a list of the packages that your application is currently using, run meteor list
.
This removes the package entirely. To continue using the package, but remove its version constraint, use meteor add
.
Meteor does not downgrade transitive dependencies unless it's necessary. This means that if running meteor add A
upgrades A's parent package X to a new version, your project will continue to use X at the new version even after you run meteor remove A
.
meteor list
Lists all the packages that you have added to your project. For each package, lists the version that you are using. Lets you know if a newer version of that package is available.
meteor add-platform platform
Adds platforms to your Meteor project. You can add multiple platforms with one command. Once a platform has been added, you can use 'meteor run platform' to run on the platform, and meteor build
to build the Meteor project for every added platform.
meteor remove-platform platform
Removes a platform previously added to your Meteor project. For a list of the platforms that your application is currently using, see meteor list-platforms
.
meteor list-platforms
Lists all of the platforms that have been explicitly added to your project.
meteor mongo
Open a MongoDB shell on your local development database, so that you can view or manipulate it directly.
For now, you must already have your application running locally with meteor run
. This will be easier in the future.
meteor reset
Reset the current project to a fresh state. Removes the local mongo database.
This deletes your data! Make sure you do not have any information you care about in your local mongo database by running meteor mongo
. From the mongo shell, use show collections
and db.collection.find()
to inspect your data.
For now, you can not run this while a development server is running. Quit all running meteor applications before running this.
meteor build
Package this project up for deployment. The output is a directory with several build artifacts:
- a tarball that includes everything necessary to run the application server (see the
README
in the tarball for details) - an unsigned
apk
bundle and a project source if Android is targetted as a mobile platform - a directory with an Xcode project source if iOS is targetted as a mobile platform
You can use the application server bundle to host a Meteor application on your own server, instead of deploying to Galaxy. You will have to deal with logging, monitoring, backups, load-balancing, etc, all of which we handle for you if you use Galaxy.
The unsigned apk
bundle and the outputted Xcode project can be used to deploy your mobile apps to Android Play Store and Apple App Store.
By default, your application is bundled for your current architecture. This may cause difficulties if your app contains binary code due to, for example, npm packages. You can try to override that behavior with the --architecture
flag.
meteor lint
Run through the whole build process for the app and run all linters the app uses. Outputs all build errors or linting warnings to the standard output.
meteor search
Searches for Meteor packages and releases, whose names contain the specified regular expression.
meteor show
Shows more information about a specific package or release: name, summary, the usernames of its maintainers, and, if specified, its homepage and git URL.
meteor publish
Publishes your package. To publish, you must cd
into the package directory, log in with your Meteor Developer Account and run meteor publish
. By convention, published package names must begin with the maintainer's Meteor Developer Account username and a colon, like so: iron:router
.
To publish a package for the first time, use meteor publish --create
.
Sometimes packages may contain binary code specific to an architecture (for example, they may use an npm package). In that case, running publish will only upload the build to the architecture that you were using to publish it. You can use publish-for-arch
to upload a build to a different architecture from a different machine.
meteor publish-for-arch
Publishes a build of an existing package version from a different architecture.
Some packages contain code specific to an architecture. Running publish
by itself, will upload the build to the architecture that you were using to publish. You need to run publish-for-arch
from a different architecture to upload a different build.
For example, let's say you published name:cool-binary-blob from a Mac. If you want people to be able to use cool-binary-blob from Linux, you should log into a Linux machine and then run meteor publish-for-arch name:cool-binary-blob@version
. It will notice that you are on a linux machine, and that there is no Linux-compatible build for your package and publish one.
Currently, the supported architectures for Meteor are 32-bit Linux, 64-bit Linux and Mac OS. Galaxy's servers run 64-bit Linux.
meteor publish-release
Publishes a release of Meteor. Takes in a JSON configuration file.
Meteor releases are divided into tracks. While only MDG members can publish to the default Meteor track, anyone can create a track of their own and publish to it. Running meteor update
without specifying the --release
option will not cause the user to switch tracks.
To publish to a release track for the first time, use the --create-track
flag.
The JSON configuration file must contain the name of the release track (track
), the release version (version
), various metadata, the packages specified by the release as mapped to versions (packages
), and the package & version of the Meteor command-line tool (tool
). Note that this means that forks of the meteor tool can be published as packages and people can use them by switching to a corresponding release. For more information, run meteor help publish-release
.
meteor test-packages
Test Meteor packages, either by name, or by directory. Not specifying an argument will run tests for all local packages. The results are displayed in an app that runs at localhost:3000
by default. If you need to, you can pass the --settings
and --port
arguments.
meteor admin
Catch-all for miscellaneous commands that require authorization to use.
Some example uses of meteor admin
include adding and removing package maintainers and setting a homepage for a package. It also includes various helpful functions for managing a Meteor release. Run meteor help admin
for more information.
meteor shell
When meteor shell
is executed in an application directory where a server is already running, it connects to the server and starts an interactive shell for evaluating server-side code.
Multiple shells can be attached to the same server. If no server is currently available, meteor shell
will keep trying to connect until it succeeds.
Exiting the shell does not terminate the server. If the server restarts because a change was made in server code, or a fatal exception was encountered, the shell will restart along with the server. This behavior can be simulated by typing .reload
in the shell.
The shell supports tab completion for global variables like Meteor
, Mongo
, and Package
. Try typing Meteor.is
and then pressing tab.
The shell maintains a persistent history across sessions. Previously-run commands can be accessed by pressing the up arrow.
Please login to continue.