Sadly, Parse.com is shutting down on 28 January 2017. In the previous series, I walked you through the entire journey of building a blog system from scratch. But everything was based on Parse.com, and if you are still using those techniques, your website will unfortunately stop working by then.
If you still like Parse.js (as do I), and want to continue using it, there's good news. The lovely folks there made it open source so we can run our own copy on all popular web hosting services. This tutorial aims to help you to make that change and migrate from Parse.com to your own Parse Server on Heroku.
I’m not an expert in back end, but this is the easiest way I found that worked. If you see any flaws and have better methods to share, definitely leave a comment below.
If you follow this episode, the server migration by itself won’t be too complicated. With Docker, it’s even quite easy to set up a local Parse Dashboard, so you can still see and play with your data with ease.
However, this tutorial series was made based on version 1.2.19 of Parse.js; in order to connect to a standalone Parse server, we need to update the application to run version 1.9.2. By version 1.5.0, Parse took out support for Backbone, and that means we need some major changes in the code. We will be adding Backbone back to the page, and using a mixture of Parse and Backbone there.
That’s quite a long intro, but don’t be too scared. You may need to debug here and there during the migration, but you should be fine. You can always check my source code or leave a comment below—I and this fantastic community here will try our best to help you.
Set Up and Migrate to Parse Server
First thing first, let’s start making a Parse Server. Parse already made this very easy with a detailed migration guide and a long list of sample applications on all popular platforms like Heroku, AWS, and Azure.
I will walk you through the easiest one that I know: the Heroku + mLab combo. It’s free to begin with, and you can always pay for better hardware and more storage within the same system. The only caveat is that the free version of Heroku would “sleep” after being idle for 30 minutes. So if users visit your site when the server is “sleeping”, they may have to wait for a few seconds for the server to wake up before they can see the data. (If you check the demo page for this project and it doesn’t render any blog content, that’s why. Give it a minute and refresh.)
This part is largely based on Heroku’s guide for Deploying a Parse Server and Parse’s own migration guide. I just picked the simplest, most foolproof path there.
Step 1: Sign Up and Create a New App on Heroku
If you don’t have a Heroku account yet, go ahead and make one. It’s a very popular platform for developing and hosting small web apps.
After you are registered, go to your Heroku Dashboard and create a new app—that will be your server.
Give it a name if you want:
Step 2: Add mLab MongoDB
Now you need a database to store the data. And let’s add mLab as an add-on.
Go to Resources > Add-ons, search for “mLab”, and add it:
Sandbox is enough for development—you can always upgrade and pay more to get more storage there.
Once you've added mLab, you can grab the MongoDB URI of it.
Go to Settings > Config Variables in your Heroku Dashboard and click on Reveal Config Vars.
There you can see the MongoDB URI for your database. Copy it, and now we can start migrating the database.
Step 3: Database Migration
Go to Parse.com and find the app you want to migrate. The open-source version of Parse Server only supports one app per server, so if you want to have multiple apps, you need to repeat this process and create multiple servers. Now just pick one.
Within that app, go to App Settings > General > App Management, and click on Migrate.
And then paste in the MongoDB URI you just copied, and begin migration.
Soon you should see this screen:
That means now you should have all your data in your mLab MongoDB. Easy enough, right?
But don’t finalize your app yet—let’s wait till we can see and play with that same data from our local Parse Dashboard, and then go back and finalize it.
Step 4: Deploy Parse Server
Now, with the database already migrated, we can deploy the Parse Server.
If you don’t have a GitHub account yet, go ahead and make one. It’s probably the most popular place where people share and manage their code.
With your GitHub account, fork the official Parse Server example repo.
Then, go back to your Heroku Dashboard. Under Deploy > Deployment method, choose GitHub and connect to your GitHub account.
After that, search for parse and find your parse-server-example
repo and connect.
If everything works, you should see it being connected like this:
Now, scroll down to the bottom of the page. Under Manual Deploy, click Deploy Branch.
You will see your Parse Server being deployed, and soon you will see this screen:
Click on the View button and you will see this page:
That means your server is now happily running! And the URL you see is the URL of your server. You will need it later.
I know it feels unreal to see this simple line and know the server is up. But believe me, the powerhouse is running there. And your app can read and write from it already.
If you want to double-check, you can run something like this:
$ curl -X POST \ -H "X-Parse-Application-Id: myAppId" \ -H "Content-Type: application/json" \ -d '{}' \ https://example.herokuapp.com/parse/functions/hello .. {"result":"Hi"}%
Set Up a Local Parse Dashboard
If you are a command-line ninja, you will probably be fine from here. But if you are like me and enjoy the friendly interface of the Parse Dashboard, follow this part to set up your own Parse Dashboard on your local machine, so that you can visually see and play with your Parse data the way you are used to.
Again, you can install your dashboard in a handful of ways. I am just going to show you the simplest way in my experience, using Docker.
Step 1: Install Docker
If you don’t have Docker, install it first (Mac | Windows).
It puts an entire environment in a box, so you don’t need to follow the quite complicated local installation tutorial and jump through hoops in Terminal.
Step 2: Build Parse Dashboard Image
With your docker running, clone the Parse Dashboard repo to your computer and go into that repo.
$ git clone https://github.com/ParsePlatform/parse-dashboard.git Cloning into 'parse-dashboard'... remote: Counting objects: 3355, done. remote: Total 3355 (delta 0), reused 0 (delta 0), pack-reused 3354 Receiving objects: 100% (3355/3355), 2.75 MiB | 2.17 MiB/s, done. Resolving deltas: 100% (1971/1971), done. $ cd parse-dashboard/
For absolute GitHub newbies, just download it as a zip file.
Unzip it and put it in a location you can remember. Open your terminal app if you are on Mac, type cd
(you need a space after cd there) and drag the folder in.
Then hit Enter.
You should see something like this, and that means you are in the correct place.
~$ cd /Users/moyicat/temp/parse-dashboard-master ~/temp/parse-dashboard-master$
Now, you can quickly check if your Docker is installed correctly by pasting in this command:
docker -v
If it shows the version you are on, like this:
Docker version 1.12.5, build 7392c3b
It’s installed, and you can go on.
If instead, it says:
-bash: docker: command not found
You need to double-check if you have installed Docker correctly.
With Docker correctly installed, paste in this command and hit Enter:
docker build -t parse-dashboard .
That will build you a local image (feel free to ignore docker jargon) for Parse Dashboard.
You will see many lines scrolling. Don’t panic—just give it a while, and you will see it end with something like this:
Successfully built eda023ee596d
That means you are done—the image has been built successfully.
If you run the docker images
command, you will see it there:
REPOSITORY TAG IMAGE ID CREATED SIZE parse-dashboard latest eda023ee596d About a minute ago 778.1 MB
Step 3: Connect Parse Dashboard to Parse Server
Now, that’s just an image, and it’s not a running server yet. When it runs, we want it to be connected to the Parse Server and the MongoDB we just built.
To do that, we first need to create a few keys in Heroku, so it can tell who to grant access to the data.
Go to your Heroku Dashboard and go to Settings > Config Variables again. This time, we need to add two variables there: APP_ID
and MASTER_KEY
. APP_ID
can be anything easy to remember, while MASTER_KEY
had better be a really long and complicated password.
Now with those keys, we can write a simple config file in the root directory of your Parse Dashboard folder. You can use everything from vim
to TextEdit
or Notepad
—the goal is to make a plain text config.json
file with this content:
{ "apps": [{ "serverURL": "your-app-url/parse", "appId": "your-app-id", "masterKey": "your-master-key", "appName": "your-app-name" }], "users": [{ "user":"user", "pass":"pass" }] }
And of course, replace your-app-url
with the “View” link URL (the page that says “I dream of being a website”), but keep the /parse
there at the end; replace your-app-id
and your-master-key
with the config variables you just added; and give your app a name and replace your-app-name
with it.
Save the file and run the ls
command in Terminal to make sure you put the config.json
in the correct place.
~/temp/parse-dashboard-master$ ls CHANGELOG.md Dockerfile PIG/ Procfile bin/ package.json src/ webpack/ CONTRIBUTING.md LICENSE Parse-Dashboard/ README.md config.json scripts/ testing/''
If you see config.json
in this list, you are good to move on.
Now run the pwd
command to get the place you are in:
$ pwd /Users/moyicat/temp/parse-dashboard-master
Copy that path.
Then paste in this command to create a Docker container (again, you can ignore this jargon) and run your Parse Dashboard. Remember to replace my path with the path you just got.
docker run -d \ -p 8080:4040 \ -v /Users/moyicat/temp/parse-dashboard-master/config.json:/src/Parse-Dashboard/parse-dashboard-config.json \ -e PARSE_DASHBOARD_ALLOW_INSECURE_HTTP=1 \ --name parse-dashboard \ parse-dashboard
From top to bottom, this command does these things (which you can also ignore):
L1: Tell Docker to start a container L2: Make it run on port 8080, you can change it to any port you want L3: Get the config.json you just made as use it as the configuration L4: Enable HTTPS on your local (otherwise you will meet an error message) L5: Give it a name you can remember. You can change it to anything you want, too. L6: Tell Docker the image you want to use. parse-dashboard is the name we used in the docker build command earlier.
If everything runs through, it will return a long string to you with no error message. Like this:
4599aab0363d64373524cfa199dc0013a74955c9e35c1a43f7c5176363a45e1e
And now your Parse Dashboard is running! Check it out at http://localhost:8080/.
It might be slow and show a blank page initially, but just give it a couple of minutes and you will see a login screen:
Now you can log in with user
as the username and pass
as the password—it’s defined in the config.json
in case you didn’t realize earlier. You can change them to whatever you want, too.
And you will see this familiar interface from your local machine and can play with your data (now in mLab MongoDB) the way you always do.
A couple of final notes on this local dashboard:
Firstly, you can stop and start this container from now on at any time with these two commands:
docker stop parse-dashboard docker start parse-dashboard
So when you restart your computer, you don’t need to follow the previous steps again, just tell it to start again.
And secondly, if you have multiple Parse servers, you don’t need to create multiple Parse dashboards. Just add multiple apps in the config.json
like this:
{ "apps": [{ // info for first server "serverURL": "", "appId": "", "masterKey": "", "appName": "" }, { // info for second server "serverURL": "", "appId": "", "masterKey": "", "appName": "" }], "users": [...], }
Every time you make changes to config.json
, you need to restart the Docker container:
docker restart parse-dashboard
And then you will see the changes you made.
Step 4: Finalize the Migration
Now play with your new Parse Dashboard, and if everything works, you can now go back to Parse.com and finalize the migration.
Then, if you check your applications and dashboard, you will find that they all magically point to your new server with no problem.
Update the Code to Run on Parse 1.9.2
This is great! I wish it could stay that way and we could end this tutorial early. But as I mentioned, your old Parse.js app is still relying on Parse.com servers to point it to the correct new server. And it will stop working after 28 January 2017.
To make it run forever (finger crossed) we need to stop using the JavaScript keys to point to the app (which relies on Parse.com to find out which database to point to), and directly point to our parse server.
Step 1: Update the JavaScript Libraries
First let’s update the Parse.js file we are using in index.html
.
Instead of using the version 1.2.19:
<script src="//www.parsecdn.com/js/parse-1.2.19.min.js"></script>
Switch to the newest version:
<script src="//npmcdn.com/parse/dist/parse.min.js"></script>
Also, let’s add lodash and Backbone. Now that Parse has stopped supporting Backbone, we need to include it to keep using the Views and Router.
<!-- Lodash --> <script src="//cdn.jsdelivr.net/lodash/4.17.3/lodash.min.js"></script> <!-- Backbone.js --> <script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>
Step 2: Point to Your Parse Server
Then, let’s go into site.js
.
The first thing there is to update the Parse.initialize()
function so it points to your own Parse Server.
Previously it may look like this:
Parse.initialize("HC87tn6aA7c3sYx9X0vwwLVXeqHDRMYYmrUBK5zv", "3piNGGnRMhvWo8u9pKD9TDc1MJlWhlvK78Vr3fHo");
Now, point it to your Parse server.
Parse.initialize("moyicat-parse-blog-git"); // Your App Name Parse.serverURL = 'https://moyicat-parse-blog-git.herokuapp.com/parse'; // Your Server URL
Step 3: From React to Backbone
Moving on, let’s do a quick update to change all the Parse.View
, Parse.Router
, and Parse.history
to Backbone.View
, Backbone.Router
, and Backbone.history
. Those are no longer supported by Parse, so we need to have a fallback.
It’s not the most pleasant thing in the world to mix and match Class
like that, but if you want to make the least changes to your code and have it running, this might be the easiest way.
Step 4: From Collection to Query; From fetch
to find
Now, one other thing that Parse stopped supporting is Collection
. And it’s much more thorny than the other three. Switching from Parse.Collection
to Backbone.Collection
won’t work. We need to rewrite the logic using Parse queries.
I will use the Blogs
collection as an example to show you how we can update our blog to work with the new Parse.js.
Previously, we first defined a Class
for Blogs
:
Blogs = Parse.Collection.extend({ model: Blog, query: (new Parse.Query(Blog)).descending('createdAt') });
And then in the BlogRouter.start()
function we created an instance of that class to contain the collection of blocks.
this.blogs = new Blogs();
After that, we call fetch()
on that collection to get blogs data. Like in BlogRouter.index()
:
this.blogs.fetch({ success: function(blogs) {...}, error: function(blogs, error) {...} });
Now, we can just delete that Class declaration and make BlogRouter.blogs
a Parse query:
this.blogs = new Parse.Query(Blog).descending('createdAt');
And when we call it, instead of fetch()
we use find()
.
this.blogs.find({ success: function(blogs) {...}, error: function(blogs, error) {...} });
This part may take a while since we have quite a few different use cases over this series. You may need to debug a little bit—at this point, even if the data is fetching correctly, the page won’t render correctly yet. If you prefer to see things render as you fix them, read through till the end, and then start changing your code and debugging.
Step 5: Check the View Objects
When all the data is fetching correctly, the next thing to check on is the data you pass into your View
objects.
Previously, we could pass anything we wanted in to a View object. In this example, we passed the username
directly into the blogsAdminView
so we could greet users by their usernames.
var blogsAdminView = new BlogsAdminView({ username: currentUser.get('username'), collection: blogs });
This would also stop working when we change the View
to be extended from the Backbone.View
object. We can only pass in model
and collection
now.
So we need to pass in the currentUser
as a model:
var blogsAdminView = new BlogsAdminView({ model: currentUser, collection: blogs });
And change the BlogsAdminView
accordingly.
Again, you might need to test and debug around a little bit to make everything work.
Step 6: Update the Handlebar Templates to Adapt to the New Data Structure
And finally, between the version changes, the Parse Object data structure also changed a bit.
Before, every object looked like this:
{ objectId: '', title: '', ..., }
Now, this is the new structure:
{ id: '' // the objectId, attributes: { title: '', ..., }, ..., }
This means we need to update our Handlebar templates, too, to render the new data correctly:
For example, previously for the categories in the sidebar we wrote the following template:
<script id="categories-tpl" type="text/x-handlebars-template"> <div class="sidebar-module"> <h4>Categories</h4> <ol class="list-unstyled"> {{#each category}} <li><a href="#/category/{{objectId}}">{{name}}</a></li> {{/each}} </ol> </div> </script>
Now we need to update {{objectId}}
to be {{id}}
and {{name}}
to be {{attributes.name}}
.
<script id="categories-tpl" type="text/x-handlebars-template"> <div class="sidebar-module"> <h4>Categories</h4> <ol class="list-unstyled"> {{#each category}} <li><a href="#/category/{{id}}">{{attributes.name}}</a></li> {{/each}} </ol> </div> </script>
Now your page will render.
Again, if you don’t remember the logic of the site completely clearly, you might need to jump through some hoops a little bit here. If you get stuck, you can always check my source code.
Conclusion
There you have it. Hopefully it can help you save your data before Parse.com shuts down—or revive your code when you need it. You will lose all the data after 28 January 2017, but if you update the code, it will function again.
Again, I’m incredibly sad that Parse.com won’t be running any longer and this tutorial series won’t work for newcomers (unless they keep referring back to this final part). But hopefully it helped a few people to learn how to code a website.
From this point on, whether you choose to migrate or to learn a new language, it’s totally up to you. I hope it will be a little easier because you learnt some useful concepts here.
Best wishes! And leave me a comment if you find this series helpful.
Comments