How to Migrate from Parse (Part 3, Migrating the Code)

Have you heard? Parse is shutting down its hosted service next month! If you’ve been soaking in the warm amniotic fluid of procrastination since January, then the time is nigh for your birth into the world of the self-hosted backend.

Fortunately, Go Nimbly is here to help. We’ve handled numerous migrations and have distilled the essentials into this three-part series. If you haven’t, you should take a look at Part 1 and Part 2 before starting here.

In Part 1, you migrated your data from Parse’s hosted service. In Part 2, I walked through deploying a Heroku app on Parse Server.

Getting Started

Today there are two main items on the agenda. The first is to point your front-end at your new Parse Server. This will vary based on the Parse SDK you’re using, but luckily they’re all fairly similar.

The second component is to port your cloud code. This will vary quite a bit based on your specific needs, but I’ll cover everything you’ll need to know.

To complete this final installment of our three-part guide should take less than two hours, but it’s likely your migration will require additional work.

Update Your SDK Initialization

There are a ton of different Parse SDKs. For this guide I’m going to show you how to update the JavaScript SDK and the iOS SDK.

Not using JavaScript or iOS? No worries! Parse has all the initialization code documented for your reading pleasure.

JavaScript

If you’re using NPM then you’ll want to make sure you’re installing the latest JavaScript SDK. Run npm install and check the logs for parse to make sure you’re on the latest version. At this time the latest version is 1.9.2.

If you prefer to load a pre-compiled version you can get it from NPM’s CDN:

https://npmcdn.com/parse/dist/parse.min.js

Find your Parse initialization. It should look something like this:

Parse.initialize("Your App ID", "Your Javascript Key");

Update your Parse initialization code so it looks like this instead:

Parse.initialize("Your App ID");
Parse.serverURL = "https://<your-heroku-app>.herokuapp.com/parse";

iOS

First you’ll need to run pod update. This will update your Parse SDK to the latest version.

Next you need to update your initialization. Typically the initialization code is found in your AppDelegate.m file.

For Swift the updated initialization will look like:

let configuration = ParseClientConfiguration {
$0.applicationId = "YOUR_APP_ID"
$0.server = "http://<your-heroku-app>.herokuapp.com/parse"
}
// Swift 3.0
Parse.initialize(with: configuration)

And in Objective-C it will look like:

[Parse initializeWithConfiguration:[ParseClientConfiguration configurationWithBlock:^(id<ParseMutableClientConfiguration> configuration) {
configuration.applicationId = @"YOUR_APP_ID";
configuration.server = @"http://<your-heroku-app>.herokuapp.com/parse";
}]];

Testing the Front-End

Give it a whirl! Parse should initialize successfully and you should be able to use PFQuery and PFObject. You can do a simple test by creating a new Parse object (JavaScript example):

var Foo = Parse.Object.extend("Foo");
var object = new Foo(); //create a new object
object.set("bar", 1); //set a value
object.save().then(function (savedObject) { //save the object
console.log("object ID: " + savedObject.id);
}, function (error) {
console.log(error);
}

No errors? Great!

Port Cloud Code

The steps I’ve documented here cover the most common issues when porting Cloud Code. However, Cloud Code is highly specific to each Parse app. For more help check out this Parse Server compatibility documentation.

Move your Cloud Code

Generally speaking, it’s better to keep your server code and front-end code in different repos. This makes it easier to deploy to Heroku and automate tests. Most projects built around the Parse hosted service have their cloud code in the same directory as their front-end code due to the nature of the Parse workflow. Time to rectify this.

I’m going to assume your Cloud Code is in your/project/CloudCode/cloud. This is typical for an app running on the Parse hosted service.

The simplest way to move your Cloud Code is to replace the go-nimbly-parse-server-example/cloud directory with the /CloudCode/cloud/ directory in your current project via drag-n-drop. However, this will leave behind the Git history for your Cloud Code. For any production app this is unacceptable. Instead follow this quick guide to migrate the CloudCode/cloud/ directory using a series of Git commands.

Update require() Paths

If you try to deploy your Cloud Code now it’s very likely you’ll see an error like this:

Error: Cannot find module 'aModule.js'

This is because the way require() works in Parse Server is a bit different than with the Parse hosted service. You need to update your paths from require('cloud/path/to/file'); to require('./cloud/path/to/file');.

Include Missing Libraries

The Parse hosted service was nice enough to include a bunch of commonly used libraries like Underscore.js and Moment.js. Check out the complete list of libraries to find out specifically which ones you are using.

For each library that you are using you need to create an entry in the dependencies listed in package.json. For example, if you want to add Underscore.js to your project you would add the following line in the dependencies object:

"underscore": "~1.8.0"

so that your dependencies look like

"dependencies": {
"express": "~4.11.x",
"kerberos": "~0.0.x",
"parse": "~1.8.0",
"parse-server": "*",
"underscore": "~1.8.0"
},

No More Parse.Cloud.useMasterKey()

Are you using Parse.Cloud.useMasterKey() in your Cloud Code? You need to pass {useMasterKey:true} into any function that requires the master key.

Your code changes should look something like this:

Parse.Cloud.define('getTotalMessageCount', function(request, response) {

// Parse.Cloud.useMasterKey() <-- no longer available!

var query = new Parse.Query('Messages');
query.count({ useMasterKey: true }) // count() will use the master key to bypass ACLs
.then(function(count) {
response.success(count);
});
});

No More Parse.User.current()

Parse.User.current() no longer exists in parse-server. Cloud Code that relies on Parse.User.current() needs to use request.user instead.

You may be using Parse.User.current() to perform queries for objects that have read permissions restricting access to a specific user. In this case you need to pass {sessionToken:token} into your query’s find() function:

// Parse Server Cloud Code
Parse.Cloud.define('getMessagesForUser', function(request, response) {
  //var user = Parse.User.current(); this no longer works
var user = request.user; // instead use this
var token = user.getSessionToken(); // get session token

var query = new Parse.Query('Messages');
query.equalTo('recipient', user);
query.find({ sessionToken: token }) // pass the session token
.then(function(messages) {
response.success(messages);
});
});

Next Steps

At this point your Parse Server should be functional. However, every app is different. Here are the things that some apps will still have to migrate:

  1. Are you using push? You need to configure your Parse Server for push.
  2. Are you using Cloud Jobs? This functionality is not included in Parse Server. You need to build your own solution.
  3. Does your app use PFFile? By default Parse Server uses your MongoDB database to store new files. This will get expensive quickly so it’s best to use a File Adapter. Check out Parse Server file adapters and the parse-files-utils repo.
  4. And you need to keep an eye on everything. You might want to consider a monitoring solution like New Relic APM.

That concludes it for our Parse Migration series! For help solving any of your Parse Server related issues contact our team at Go Nimbly. We have engineers with the skills you need to get your Parse migration ready for prime time.

Go Nimbly is the premier marketing and sales consultancy for SaaS companies. Founded and headquartered in San Francisco, Go Nimbly provides customers with a customized team to manage everything from strategy to execution for their marketing and sales systems. To learn more, visit gonimbly.com.