Advanced Guides

Upgrade to Parse 3.1

24min

More power to your App with Parse Server 3.1

Introduction

The Parse Community recently released version 3.1 of the Parse Server. This update has cleaned up Cloud Code syntax: it is far more amenable to leveraging the es6 async and await constructs.

Additionally, some idiosyncrasies associated with using Parse were dropped, for example, Cloud functions simply return a Promise rather than using the error or success messages on the Response object.

You can upgrade your apps on Back4App easily on your Dashboard. This guide will demonstrate how to upgrade your code to leverage the new features of 3.1.

To follow this guide you are welcome to take a look at the example project provided.

This is a guest tutorial written by John Considine, lead developer at K-Optional.

Goals

  • To update your Back4App Parse Server to 3.1 and migrate your Cloud Code accordingly.

Prerequisites

To complete this tutorial, you need: ° An existing Back4App application that’s using Parse Server 2.x ° Follow the Create New App tutorial to learn how to create an app at Back4App.

Summary of changes

The most notable changes are the following:

1. Cloud Code runs with Parse-SDK 2.x.

Previously, Cloud Code ran with Parse-SDK 1.x. With Parse Server 3.1, it runs Parse-SDK 2.x.

Look at Parse SDK releases to understand better what this entails. This major version bump mostly involves bug fixes. It also adds containedBy and includeAll query methods, as well as abilities to fetch an object with includes.

2. Aggregate update

Since Parse 2.7.1, you can use the aggregate method on a query. This allows you to leverage the underlying database a little bit more. Now, the syntax for the aggregate method on Parse.Query has been updated.

You can execute a query using two stages: the match and the group stage.

1 // matches users whose name are Foo, and groups by their objectId 2 const pipeline = [{ group: { objectId: {} } }, { match: { name: 'Foo' } }]; 3 4 var query = new Parse.Query("Person"); 5 query.aggregate(pipeline)

Previously, you didn’t need the pipeline key in the pipeline object. Due to the underlying API, you must now explicitly include the pipeline key. The value should be an array of one or two stages, featuring group and match.

Look at Parse Official Documentation for more specific examples.

3. Under-the-hood optimizations

Some under-the-hood optimizations have been made. For example, a Parse LiveQuery will fetch Class Level Permissions (CLPs) along with data to prevent double database access.

4. Parse Reset Email

When requesting a password reset email, the server will return success even if that email is not saved. Additionally, password reset tokens expire when a user’s email is reset.

5. Cloud triggers update

With this release, you can share data between the beforeSave and afterSave triggers on the same object. For example:

JS


You can see more about changes on Parse Server in the official Parse 3.1 Changelog by clicking here.

6. LiveQuery Improvement

The Parse LiveQuery client allows you to subscribe to queries, and receive updates from the server as they come in. Traditional Queries are executed once by the client, so this is very helpful for cases like messaging, etc.

With Back4App you can also take advantage of this technology.

With the release of 3.x, the Parse community has improved the system for LiveQuery ACLs.

You can pass a session token now to the subscribe method of a live query, and the Parse Server will manage only returning results that this user has access to. For example, a user may have read/write access to certain ‘Messages’, but not all.

JS


The above code will automatically subscribe to all messages that the user has access to, relieving you from the responsibility of querying specific messages.

The main part of the changes pertains to how Cloud Code is handled. For this, see the migration guide below.

1 - Aligning technical fundamentals

We’ll start with an example cloud project using the 2.x release. That way we can navigate through the appropriate changes of syntax. You can see the repository for this example project.

If you’re familiar with async and await, you can skip this section.

The evolution of asynchronous code in Javascript looks something like this:

Any modern Javascript application will likely use all three. Callback functions involve passing a function as an argument to another function. This second function can execute the first at some point.

JS


Callbacks are essential but can be unwieldy when it comes to chaining many of them. Specifically, nesting several layers can be difficult to read, and error handling proves difficult. Hence in ES2015 the Promise was introduced.

JS


Promises improve the readability of asynchronous programming. They also make pipelines more explicit. But even bigger strides were made in ES2017 with the async / await constructs. Your code can now wait for the results of a Promise without relying on the then / catch blocks (which can also become tough to read).

JS


Perhaps for a very simple example, this may not seem more elegant than plain promises. But awaiting the results of an asynchronous function is often precisely what we want to do. Hence, it truly optimizes the readability of our code.

Support for async/await

As aforementioned, async/await was included in the ECMAScript 2017 specification (es8). For server code, versioning is hardly an issue since you can update to the version of Node.js that supports these features. Rest assured, Back4App’s environment supports recent stable versions. For browser code, transpilers like Babel will produce an es2016 compatible with code that uses async / await and works in modern browsers.

2 - Thinking about your code differently

The main change with Cloud Code involves what the developer does versus what the library does. Previously, you would explicitly manage the response. Since most Cloud Code will execute asynchronously - making database queries and writes - it makes more sense to return a Promise, reducing the boilerplate code.

The intuition behind Cloud functions is that there is minimal setup and configuration involved with writing server-side code. This release embodies that idea; keep this in mind as you’re refactoring and creating new functions.

To show how Cloud Code functions work in Parse Server 3.1, we rewrote a functional Cloud Code sample from a version of Parse Server before migration. You can find this code by clicking here. The same Cloud Code function is written in Parse 3.1 as shown below.

JS


3 - Adding all async markers

Any function that uses await must be declared with the async modifier. This simple refactoring will attach async to all Cloud Functions. It will also replace them with arrow functions as they are more succinct in this case (and what the updated official Parse guide uses).

JS


Your code will look like this after this refactoring

Nothing crazy so far. In the next step, we’ll get our money’s worth for this change.

4 - Removing references to response, employ await

Your code will look like this after this refactoring

This step is a little bit trickier. We need to:

  • Remove all references to the ‘response’ variable, returning a promise instead
  • In the case of multiple query/save functions, await the response

Check out the comment create method to see how this is done

JS


Note that:

  • Now a JavaScript Error is thrown instead of calling response.error. Parse will handle transforming this into a response for us.
  • Deleting a ‘Post’ or ‘Comment’ involves grabbing the object first, then destroying it. By using ‘await’, the destroy method can access the saved object outside of a block.

That completes all necessary refactoring for migration. That’s to say if you do up until this Step, congrats! Your code will run on Back4App Parse 3.1!

5 - Advanced Tricks (optional)

The following changes are optional but can shorten your code significantly. I find they reduce boilerplate.

You probably noticed a lot of manual checks for parameters or the authenticated user. These ensure that strange behavior doesn’t occur. For example, we’ve decided our ‘Post’ object needs text, so if no ‘text’ parameter is passed, the object will get saved without it. One way to prevent this is to check that text was passed.

But manual checks can be time-consuming and inelegant. In this section, we take advantage of object destructuring to implicitly complete these checks.

You should see the documentation above if you don’t know what destructuring is. But in short, it allows you to turn an object’s property into a variable with very concise syntax.

JS


Destructuring is less verbose than manual assignment. It also allows you to declare parameter variables on the fly which is nice:

JS


When combined with an es2015 notation for object initialization we can optimize our parameter checks.

We can do this:

JS


So for our Parse code, we can do this:

JS


If this is daunting, don’t fret. The full code example might help.

In short, ‘AssertParams’ is a utility function for throwing an error if a value is undefined. We can check for parameters in one motion by combining object destructuring and es2015 object initialization.

This removes eight or nine manual checks which start to become unsightly after a while.

6 - Upgrading on Back4App

Once you have migrated your code, you must do two more things to have it running on Back4App.

  1. Upgrade your Back4App server version
  2. Upload your new cloud code.

I’ve briefly mentioned the first step before. All you need to do is log into Back4App and go to your app’s dashboard. From there, just select “Server Settings” on the left, followed by the “Settings” button on the “Manage Parse Server” card. You may then select the Parse Server 3.1.1 radio button and hit “Save”.

Last but not least, you can upload your code via the Back4App CLI, or your dashboard using the manual upload. See this guide if you need more information on this step.

Notes on launching a new version

If your code is complex, it might be a good idea to run some tests before doing these two steps. Back4App has some guides on how to do this here and here.

Finally, it’s important to note that these changes are breaking. Using the code we wrote on a 2.x Parse Server will fail, and using 2.x code on a 3.1 server will also fail. Therefore, you must make sure to upgrade your Back4App parse version right when you upload your upgraded Cloud Code. If you have many users and are concerned about the code upload and version upgrade being slightly out of sync, you can do something like this.

JS


This code dynamically figures out the version and defines Cloud Functions based on that. After uploading this, you would change to 3.1, and then you could re-upload the code with the old part removed. Including the check at first ensures there isn’t a point where your code will crash. Since you can upgrade and upload within a couple of seconds, it’s usually not necessary.

Conclusion

At this guide, we demonstrated simply how to migrate your Cloud Code to the Parse 3.1 release. Remember to bump your Back4App version to 3.1 after you make these changes.

Also importantly, this guide demonstrated an improved syntax that Parse 3.1 leverages. Our refactorings cut the codebase from ~160 lines to ~90 and made it much more readable. For actual applications, this will pay dividends.