Exploring the .meteor/local Folder

All Meteor apps have a .meteor/local folder. Usually you don't have to look inside it, but understanding what is inside can help with setting up CI or troubleshooting issues. Let's explore it.

This folder contains temporary data and your development data from MongoDb and can grow very large. Most of it is safe to delete when you want more disk space, with the one exception being the db folder. Most of the work done by meteor reset is deleting .meteor/local.

There is no official documentation on what should be cached on CI to improve Meteor's build performance. At the end there is a list of the folders that should be cached in CI.

build #

The build folder contains the built app Meteor runs during development. We will explore what it contains in a separate post; however, there is an interesting detail that could affect you.

When building for development, Meteor uses symlinks to each folder in node_modules instead of copying them. If you have removed any npm dependencies since the last time you ran your app, the build folder will have invalid symlinks. Meteor makes a copy of the build folder as part of meteor test (I'm not sure why since later in the build process most if not all of it is deleted and recreated). If there are invalid symlinks, Meteor will fail to copy the build folder and crash before starting the tests. This can be fixed by running meteor again, or deleting the build folder.

db #

This folder is the data directory for MongoDB used with meteor run/meteor. meteor reset deletes this folder, so if you want to preserve it you need to make a copy first.

If you upgrade or downgrade Meteor to a version that uses a different Mongo version, the data might no longer be compatible and Mongo will crash. To fix this, you can use meteor reset to delete the database or repair it with:

~/.meteor/packages/meteor-tool/<meteor version>/mt-os.osx.x86_64/dev_bundle/mongodb/bin/mongod --repair --dbpath /my-app/.meteor/local/db

shell #

The shell folder has a single file: info.json. This is used by the shell client (usually meteor shell) to connect to the Meteor app.

bundler-cache #

This has two folders: scanner and linker.

scanner is used for Reify's cache. Starting in Meteor 1.8.2, Meteor uses Reify to compile all JavaScript files in your Meteor app in case they use import/export. The file name is the hash of a Javascript file's contents, and the contents of the cache file is the compiled output.

linker is used by Meteor's linker. The linker takes all of the source files from the app or a Meteor package and creates a single output file. During rebuilds, the linker can take up to half of the time. It usually uses an in-memory cache, but the file cache is useful during the initial build, when switching git branches, or your modified files match a previous version. This folder can become very large, though sometimes updates to Meteor will remove files created by an older version. You can try catching this folder in CI, but sometimes saving and restoring the folder will be slower than linking due to the size of the folder.

isopacks #

Folders in isopacks contain the built version of any local packages the app uses. Each app that uses a local package has its own copy. During the initial build, Meteor has to compile and link app code, though usually most of the work is cached. In contrast, Meteor can completely skip building local packages and use the isopack as long as the package hasn't been modified. This can make apps that keep most of their code in local packages build much faster.

plugin-cache #

plugin-cache has a separate folder for each version of each Meteor package that the app uses. If the app has a build plugin, it can use this folder to store its caches. A package can get its path by adding a setDiskCacheDirectory method to its build plugin class:

BuildPlugin.prototype.setDiskCacheDirectory = function (diskCache) {
this._diskCache = diskCache;

These folders are used by almost all compilers, and at least one minifier.

Review of caches #

During a build, this is the order the disk caches are used:

  1. The build starts. It is either the initial build from meteor being run, or a rebuild from a watched file being modified
  2. Meteor checks each package for changes. If it has changed, a new isopack is generated
  3. Meteor sends a list of files to each build plugin. When the build plugin doesn't have the file in its in-memory cache, it uses the disk cache in plugin-cache, and saves any compiled files to disk. Some compilers allow lazy compilation, which means this step is delayed until the scanner knows the file will be used.
  4. During scanning, it uses Reify to compile files
  5. After scanning and compiling is finished, the linker runs
  6. The files are then sent to the minifier. I only know of one minifier that uses caches.

Caching in CI #

Meteor relies on the caches to build your app quickly. CI environments by default preserve nothing between runs, and must be configured to cache certain folders or files to restore them during the next run. For small apps you can cache the whole .meteor/local folder. If you app is large you will want to be more precise and cache these folders:

For the cache key, you usually should use the current git commit, and fallback to using the current branch. For example, on CircleCI the cache key could be v1-meteor_cache-{{ .Branch }}-{{ .Revision }} and to restore it would use v1-meteor_cache-{{ .Branch }}-{{ .Revision }} and fallback to v1-meteor_cache-{{ .Branch }}- and v1-meteor_cache-.

Have a comment? Please Send me an email

Want More? Join my monthly newsletter for new blog posts and news about Meteor and my projects.

Have a Meteor app in production? I run Monti APM for production monitoring to help improve performance and reduce errors.