Writing ES2015 JavaScript on Parse Cloud Code

parse-cloud-code-browserify-babel

For the past few months my team at Blimp and I have been working on a new mobile app (coming soon) called Gasolina Móvil. This app will help customers in Puerto Rico pay for their gas right from their phone.

We decided to use Parse for this project because they have a wonderful product which works great on all the platforms we want to support. One of the things we like about Parse is that if you need to do something special on the server side you can just throw some JavaScript on their Cloud Code service and that’s it.

Once we started writing for Cloud Code we quickly felt the need to use modules from NPM and use the awesome JavaScript ES2015 syntax we are used to from all our other new projects. So, we had to do something.

This post describes how to create the setup we used for our project. If you just want to see the code, visit the repo on GitHub: GetBlimp/parse-babel-example.

Basic setup
The setup is pretty simple but there are some tricks you might need to know to get everything working.

The first step is to create a new Parse Cloud Code project using their command line tool.

$ parse new

It will ask you for your email and password and then ask you if you want to create a new app. Enter “n” to create a new app and then enter a name. I will use “my-cc-app”. On the next step it will ask you for a directory name but just hit enter to keep the default.

After the app is created you will get a curl command. Copy and paste that command on an empty file, you’ll need it later.

The command should look something like this:

curl -X POST \
-H "X-Parse-Application-Id: YOUR_APP_ID_HERE" \
-H "X-Parse-REST-API-Key: YOUR_API_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{}' \
https://api.parse.com/1/functions/hello

Now cd into the my-cc-app directory and run parse deploy to upload the code created by the parse new command. Once the code is deployed try running the curl command from earlier. You should see something similar to:

$ cd my-cc-app
$ cd parse deploy
$ curl -X POST \
-H "X-Parse-Application-Id: YOUR_APP_ID_HERE" \
-H "X-Parse-REST-API-Key: YOUR_API_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{}' \
https://api.parse.com/1/functions/hello

{"result": "Hello world!"}

Browserify + Babel.js
Now the fun part. We want to be able to write our code using ES2015 syntax so we need a way to transform that code into something that Cloud Code can run. For that we use Babel.js. We also want to be able to use our own modules and modules from NPM and for that we use Browserify.

Have in mind that Parse does provide a module system. The problem with it is that it uses a different convention for the module paths which makes testing in node.js very hard. Our setup with Browserify allows us to use the regular node.js paths making testing a lot esier.

Start by creating a package.json for the project:

$ npm init

NPM will ask you a few questions to create a package.json file. Just select all the defaults and complete the process. Now we want to install Browserify and Babelify, a Babel.js plugin for Browserify.

$ npm install --save-dev browserify babelify

Now you need to move the cloud directory created by the parse command line tool to a new directory called src.

$ mv cloud/ src/

Your file structure should look like this:

├── config
│ └── global.json
├── node_modules
│ ├── babelify
│ └── browserify
├── package.json
├── public
│ └── index.html
└── src
│ └── main.js

Now lets create some NPM scripts to automate the build and deploy process. We’ll do that in the package.json file.

// package.json
"scripts": {
  "postinstall": "npm run setup && npm run build",
  "setup": "mkdir -p cloud",
  "clean": "rm -rf cloud",
  "build": "browserify src/main.js -t babelify -o cloud/main.js",
  "deploy": "npm run build && parse deploy"
}

After adding these scripts to your package.json you can run them like this:

$ npm run setup
$ npm run deploy

The first command npm run setup will create a new cloud directory in your project and the second command will build your project and then upload it to Parse. After completing this two steps you can go ahead and run the initial curl command again to see the same results as before. If that’s the case, everything is working :).

Project organization
Now that we have all the tooling we need in place let’s organize the project by splitting our code into modules that we can then import and use anywhere we need them.

On our project we decided to have a very minimal main.js. In that file there’s just a bunch of imports and the Parse.Cloud.define lines which we pass an imported function to. Something like the example below:

// src/main.js
import helloController from './hello/controller';
Parse.Cloud.define('hello', helloController);
// src/hello/controller.js
export default function(request, response) {
  response.success('Hello World');
}

This way our controller functions live in their own files and become super easy to unit test. Another cool thing about this setup is that you can even use NPM modules and the build system will just take care of it. Let’s try and example.

$ npm install --save lodash.pluck

Now to use this module just open our src/hello/controller.js file and add the following code.

// src/hello/controller.js
import pluck from 'lodash.pluck';

export default function(request, response) {
  let users = [
    { user: 'barney', age: 36 },
    { user: 'fred', age: 40 }
  ];

  response.success(pluck(users, 'user'));
}
$ npm run deploy

If you now run the curl command again you should see the result of that operation.

webpack
After posting this blog post a few people suggested we should try using webpack instead of Browserify. I gave it a try and posted the code to GitHub. Take a look.

Conclusion
There you have it, this setup will allow you to write ES2015 and beyond thanks to Babel.js and it will allow you to better organize your code base thanks to Browserify. In our experience this setup is essential to writing good unit tests.

In a future post I will share what we had to do for the testing setup. Until then give this a try and let me know what you think on the comments below.