Just answering some common questions that aren’t answered on the meteor site. Thanks to all the contributors: https://github.com/oortcloud/unofficial-meteor-faq/graphs/contributors !
Table of Contents
- How do I update this FAQ?
- How can I find out more about Meteor?
- Customizing Meteor
- Reactivity and Rendering
- How do I stop meteor from reactively overwriting DOM changes from outside meteor?
- How do I ensure control state preservation across live page updating?
- How do I get a callback that runs after my template is attached to the DOM?
- How do I get reactive HTML in the tag?
- How can I tell why my code is getting re-run?
- Animation
- Subscriptions and Methods
- How can I alter every document before it is added to the database?
- How do I know when my subscription is "ready" and not still loading?
- Why does observe fire a bunch of added events for existing documents?
- Why do I sometimes see two copies of a document during a latency compensated method?
- How can I add additional RESTful API for my collections
- Deployment
- Best practices
- Should I check in this
.meteor/
folder into my git repo? - What are the best practices for form handling?
- What is the best way to do file uploads?
- What are best practices for security?
- How do I debug my meteor app?
- How do I run a local version of Meteor with the production database?
- What are the best practices for Test-Driven Development?
- Where should I put my files?
- What IDEs are best suited for meteor?
- What versions of Internet Explorer does meteor support?
- Should I check in this
- Troubleshooting errors
- "Uncaught SyntaxError: Unexpected token Y"
- "TypeError: Object # has no method '_defineMutationMethods'"
- "Uncaught TypeError: Converting circular structure to JSON"
- "Unexpected mongo exit code 100. Restarting."
- @importing in less or sass files causes errors related to variables not found.
- Connecting with default MongoDB database
- Obviously, start at the Meteor Website.
- This blog post has a list of online resources.
- Discover Meteor (written by the author of this list) is a book which takes you through building an app from scratch.
- first you need to install npm smart package with -
mrt add npm
- then add a file named
packages.json
and add npm modules - Not deleting the element immediately but waiting for the animation to complete (ughhh, not great interactivity between users).
- Hooking up your own
observe
calls on the collection so you can handleremoved
differently - ie. making an 'animating' cursor. (Much better, perhaps over-engineering the problem) - A default Meteor project comes with the
insecure
andautopublish
packages enabled to assist with rapid development. These should be disabled before development is completed.- With the
insecure
package removed, Collection insertions, updates and removals can be executed from the client if they pass oneCollection.allow
method and fail to trigger aCollection.deny
method.
- With the
- Code that resides outside the
server
,private
andtests
subdirectories is delivered to all clients. Ensure no sensitive code is stored outside these folders.- Any API keys or other sensitive information should be stored outside your codebase and delivered via environment variables.
- Even users who are not logged in have access to the templates of the whole site, possibly including admin templates, etc.
- Your client code can be unminified and the
Meteor.methods
discovered. Additionally, your Meteor application can be fuzzed. Don't rely on security through obscurity. Use the Meteor Accounts system to validate and authenticate every point of client access.
- Server-side code has full read/write access to the database. Additionally,
Meteor.methods
can be called from the terminal by any client at any time. This means you should:- Ensure authentication checks exist for each
Meteor.method
. - Ensure any client-provided data is of the proper type e.g. run through the
check
package. - A companion tool to the
check
package is theaudit-arguments-check
package which ensures every argument passed has been run throughcheck
.
- Ensure authentication checks exist for each
- Meteor lets you exactly specify which data is published and to which client.
- Your application should take care which information is published to which users.
- Any client-provided information passed to a publish function should be run through the
check
package. - Inside a
Meteor.publish
function, use the server-providedthis.userId
, not a client-provided property to determine access. - Take extra care with any publish function that deals with the
Meteor.users
Collection.
- Using the
browser-policy
package helps prevent malicious JavaScript from being injected client-side, your site being iframed by a malicious site, etc. - You should be using the most up-to-date version of Meteor possible, but minimally Meteor version 0.6.6.2 (0.6.6.2 was a Node.js security patch).
- Install node-inspector:
npm install -g node-inspector
- Start meteor:
NODE_OPTIONS='--debug-brk' mrt run
- Start
node-inspector
- In Chrome, go to the URL given by node-inspector
- If debugging remotely, make sure the port given at the URL above (8080) is not firewalled
- Debug at will
- Cloud9, the cloud-based IDE with Node.js support
- JetBrains WebStorm (Win/Mac/Linux), with existing support for Node.js. If you use Webstorm, make sure to disable auto-save. Webstorm is proprietary software that offers a gratis license to people working on open source projects
- for LESS: you can change the extension of the less files to be imported from
.less
to.import.less
and then change your@import file.less
to@import file.import.less
. - for Sass: rename the files you're importing by adding a
_
before them.file.scss
becomes_file.scss
. And then change@import 'file';
to@import '_file';
. This will prevent the less/sass compiler from automatically trying to compile all your import files independently, yet still let you use them in the order you want.
###How do I update this FAQ?
Send me (Tom Coleman, @tmeasday) a message on github (or otherwise) or fork the FAQ and send a pull request (we can discuss changes and ideas as part of the pull request).
###How can I find out more about Meteor?
###How do I use a preview release of meteor? Find the git tag you'd like to use in the meteor repository's release list, then use the --release flag with the meteor command. For example:
$ meteor --release template-engine-preview-10.1
Meteor will handle updating any smart packages and npm dependencies automatically.
###How do I use a unreleased branch of meteor? You can git clone it anywhere on your system and then run it with:
$ path/to/checked/out/meteor/meteor
Or you could let meteorite do this for you.
###How can I use someone else's javascript in my meteor project?
It depends on how it's packaged. Search for it on Atmosphere, and if there's a existing package, it should be as simple as
meteor add X
to get it.If there's no Atmosphere package yet, consider repackaging the external library for meteor.
If it's a simple client side JS script, you can include it in
client/lib/
orlib/
, although it might be nicer to create a smart package to wrap it, and publish that package on atmosphere. There are some good instructions on the atmosphere page about how to do that.###What about npm (node) modules?
Meteor by default comes bundled with a set of node modules, which you can access via:
var foo = Npm.require('foo');
If you need a npm package that is not included in Meteor, you need to create a Meteor package that wraps it. Avital Oliver created a simple example for the xml2js npm library.
Note that you cannot
Npm.require
such npm packages from within your app, you can only require them within the Meteor package that depends on them. This is due to different Meteor packages potentially depending on different versions of the same npm package.There is another way you can use NPM modules with your app.
Read this guide to learn more on using NPM modules with a meteor app.
###How do I stop meteor from reactively overwriting DOM changes from outside meteor?
Since the rendering-system blaze has come out, this shouldn't happen anymore. You may want to read the templates section of the docs. You may also be interested in the using-blaze article.
Add the
preserve-inputs
package.From the docs: "This preserves all elements of type input, textarea, button, select, and option that have unique id attributes or that have name attributes that are unique within an enclosing element with an id attribute."
Also, make sure to store related client-side data in the Session object (not in JavaScript variables)
NOTE: form data will still get cleared across hot-code pushes unfortunately.
###How do I get a callback that runs after my template is attached to the DOM?
This is now straightforward with the
rendered
callback.###How do I get reactive HTML in the
<head>
tag?Unfortunately, this isn't yet supported. However, you can work around it, like so:
Meteor.startup(function() { Deps.autorun(function() { document.title = Session.get('document-title'); }); });
Note also that this code should work fine with the spiderable package, as long as the
document-title
session var is set when your site initially loads (for instance in a router).If you are using an
autorun
block, you could try this:Deps.autorun(function(computation) { computation.onInvalidate(function() { console.trace(); }); // standard autorun code... });
This is a similar problem to above. I outlined some techniques that have worked for me in a blog post.
###How do I animate things adding/being removed from collections?
One way to animate things being added is to transition from a
.loading
class when it's rendered. First, add a.loading
class to to the element in the HTML.Then, in the relevant template's
rendered
function, remove the class just after it attaches to the document:Template.item.rendered = function() { var $item = $(this.find('.item')); Meteor.defer(function() { $item.removeClass('loading'); }); }
The
defer
(which corresponds to asetTimeout
of0
) is necessary as otherwise the browser won't have had a chance to render the item in the.loading
state (i.e. hidden / offscreen / whatever).Removal animations are more difficult, because Meteor will remove the element from the DOM immediately upon the item leaving the collection. Some hacks that you could try (please show me if you get anything working!):
You may also want to render items added by the client in a different state, until they're confirmed server side.
###How do I route my app between different views/pages?
Ideally, you'd use an existing JS router and combine it with a reactive variable (e.g. in the session) which defines the visible page. Or you could just try Iron Router, which supersedes my reactive router package, which did this for you with the backbone router. Worth a look even if you want to use a different router as it could give you some ideas.
###How do I animate/transition such view changes?
You can view these articles (part 1 and part 2) on animating using _uihooks.
###How do I animate "drag-n-drop", "add" and "remove" actions on lists?
Example implementation here: meteor-todos-sortable-animation.
There is a feature request to add this to core - please vote for it. Right now you can hack around by using a
deny
to achieve what you want on the server. For example, to timestamp each document as it goes into MongoDB:Posts.deny({insert: function(userId, doc) { doc.createdAt = new Date().valueOf(); return false; }})
You can do something similar with
update
to for example simulate a syntheticupdatedAt
field.Avoid the tempation to use
allow
for this, as there's no guarantee it will run (only oneallow
needs to be successful for theinsert
to go ahead).Until the feature gets implemented in core, Mathieu Bouchard (@matb33) has published collection-hooks.
When you subscribe to a collection you are returned a handle. This handle has a reactive ready() method that lets you know when the initial snapshot of the collection has been sent to the client.
globalSubscriptionHandles.push(Meteor.subscribe('foo')); ... Template.item.areCollectionsReady = function() { var isReady = globalSubscriptionHandles.every(function(handle) { return handle.ready(); }); return isReady; }
The default behaviour is to do this, because it's often what you want (think about how the
{{#each}}
tag works for instance). You can avoid it with a hidden options though:Posts.find().observe({ _suppress_initial: true, added: function() { // ... } })
Note that this option only works on the client. Also note that considering this option is undocumented (and underscore-cased), it could silently change in the future.
If you insert a document in both the real (server-side) method and the simulation (client-side), but then subsequently do more work on the server, there will be a time period where, for the a single browser, there will be two copies of the document in the database.
Meteor dev Nick Martin wrote:
There are a couple ways to work around this:
a) pick the same id on the client and the server. The easiest way to do this (and what the default 'insert' method does) is simply pick an id on the client and pass it along with the document to be inserted.
Doing this will result in their only being one document in the database, so you won't see double. It will still be the case that the server changes to the document don't show up locally until the method is done, though.
b) make the method finish faster. The latency compensation is triggered when the method finishes. If the thing you are blocking on doesn't do any writes (or its writes don't need to be latency compensated), you can have the method return early and complete its work asynchronously.
c) do the writes at the end of the method on the server. batch up all the database modifications and wait till after all the blocking stuff is done. this is gross, but should work to reduce the time where the user may see two items.
We also have an item on the roadmap to make this easy: https://trello.com/card/pattern-for-creating-multiple-database-records-from-a-method/508721606e02bb9d570016ae/57
For adding RESTful methods on top of your data, look into the Collection API written for Meteor:
https://github.com/crazytoad/meteor-collectionapi
###Where can I host my applications for production? Meteor gives you a proper infrastructure to deploy your application:
meteor deploy myapp.meteor.com
Meteorpedia lists more deployment options.
###How do I hook into an existing, running MongoDB instance? You can start meteor with the
MONGO_URL
environment var set:$ MONGO_URL=mongodb://localhost:27017 meteor
Note that pre-existing data in mongo may be hard to deal with.
###How do I set environment variables on meteor.com? This is not currently possible, unfortunately. You can set
process.env.X = Y
early on in the startup of your app though.###Should I check in this
.meteor/
folder into my git repo? Yes. (Unless you've put unwanted files in there yourself.)The
.meteor/
folder includes the filespackages
(a list of the project's current packages) andrelease
(describing what Meteor version your project is using); these are important for other developers to clone and use your project.Meteor also generates a
.meteor/.gitignore
file, which tells Git to ignore the folder.meteor/local
(the built development app and database). Users of other source control systems should manually prevent this folder from entering source control.###What are the best practices for form handling? While originally intended to be part of core, forms is not currently on the roadmap.
The most popular forms package currently in use is autoform. Other maintained packages include simple-form and Mesosphere.
###What is the best way to do file uploads? There's brief discussion on telescope. Also, there's a filepicker smart package.
###What are best practices for security? Core dev Emily Stark has given some fantastic talks about Meteor security.
This is not a definitive listing, but some common points that should be followed:
###How do I debug my meteor app? Client-side you have the browser console.
If you're using an IDE like WebStorm, see this SO answer.
For server-side debugging, use node-inspector and make sure you have meteor v0.5.3 or later, which makes things easier thanks to support for
NODE_OPTIONS
:Override the MONGO_URL environment variable with the output of meteor mongo, which looks like.
MONGO_URL=$(meteor mongo --url http://<your-app>.meteor.com/) meteor
For testing or security or backup's sake, you may also just want to download the production database into your local app. There's a script that makes downloading your production database as easy as
./download.sh <yourapp>.meteor.com
###What are the best practices for Test-Driven Development? Velocity is Meteor's official testing solution as of 0.8.1.
TDD support was't official in meteor prior to 0.8.1, but (test) files placed in the
tests
subdirectory won't be loaded on the client or server. There are various Node.JS modules that help with testing in versions prior to 0.8.1 - see Meteor test driven development on SO.The most popular TDD frameworks for meteor 0.8.0 and lower were Laika, RTD, and Safety Harness, which was designed to address some of the shortcomings of the first two - see the feature comparison and the meteor-talk thread where the three authors duke it out. But if you're using 0.8.1 or later, Velocity is where it's at.
###Where should I put my files?
The example apps in meteor are very simple, and don’t provide much insight. Here’s my current thinking on the best way to do it: (any suggestions/improvements are very welcome!)
lib/ # <- any common code for client/server. lib/environment.js # <- general configuration lib/methods.js # <- Meteor.method definitions lib/external # <- common code from someone else ## Note that js files in lib folders are loaded before other js files. collections/ # <- definitions of collections and methods on them (could be models/) client/lib # <- client specific libraries (also loaded first) client/lib/environment.js # <- configuration of any client side packages client/lib/helpers # <- any helpers (handlebars or otherwise) that are used often in view files client/application.js # <- subscriptions, basic Meteor.startup code. client/index.html # <- toplevel html client/index.js # <- and its JS client/views/<page>.html # <- the templates specific to a single page client/views/<page>.js # <- and the JS to hook it up client/views/<type>/ # <- if you find you have a lot of views of the same object type client/stylesheets/ # <- css / styl / less files server/publications.js # <- Meteor.publish definitions server/lib/environment.js # <- configuration of server side packages public/ # <- static files, such as images, that are served directly. tests/ # <- unit test files (won't be loaded on client or server)
For larger applications, discrete functionality can be broken up into sub-directories which are themselves organized using the same pattern. The idea here is that eventually module of functionality could be factored out into a separate smart package, and ideally, shared around.
feature-foo/ # <- all functionality related to feature 'foo' feature-foo/lib/ # <- common code feature-foo/models/ # <- model definitions feature-foo/client/ # <- files only sent to the client feature-foo/server/ # <- files only available on the server
While many IDEs support SASS, CoffeeScript etc., at the moment, there are no known IDEs that support meteor. Two efforts are underway:
There isn't an official list of supported versions, but meteor is known to work on IE8+.
Client-side error caused by the server crashing and sending a message starting with "Your app is crashing. Here's the latest log."
Server-side error. Most likely, you forgot to place "new" before a constructor call in the client. Read more.
Check if you're trying to save into
Session
an object with circular references, such as aCollection
. Read more.Mongo was killed without cleaning itself up. Try removing
.meteor/local/db/mongod.lock
. If that fails do anmeteor reset
.If you're using a collection of less files that need to be imported in a specific order because of variable dependencies (like a custom Twitter Bootstrap installation):
In order to look up content of default MongoDB database, you can retreive
MONGO_URI
by running following command:meteor mongo -U