We are a team of software developers proficient in standard front-end technologies such as AngularJS and RESTful APIs, etc. We are now starting a project on the Salesforce platform that mostly needs to perform CRUD operations and queries with Salesforce.

What is a good way to get into Salesforce development, with a flat learning curve, and without the need for a lot of server-side controllers based on Salesforce's proprietary language?

Also, since we are developing an SPA, we want to develop on local machines as much as possible, without having to redeploy to Salesforce during development frequently.

2 Answers 2


There are only a handful of things you need to know about Salesforce in the beginning. First, you should get an IDE: https://developer.salesforce.com/page/Force.com_IDE. Once you install the IDE and synchronize to your Salesforce organization (or a sandbox copy), you will see that it consists of classes, components, pages, staticresources, and triggers. To build an SPA, you do not need to create any controllers. All you need is a page and staticresources. Static resources contain your Javascript and CSS files and are typically simply ZIP files.

In order to create an SPA in Salesforce that performs only CRUD and search operations, you do not need to create any controller yourself. Just package your static resources into a ZIP file and name it yourDeployable.package and upload it together with a page like this one to your org:

<apex:page showHeader="true" sidebar="false" standardStylesheets="false">
    <link rel="stylesheet" href="{!URLFOR($Resource.yourDeployable, 'css/style.css')}"></link>
    <apex:stylesheet value="{!URLFOR($Resource.SLDS092, 'assets/styles/salesforce-lightning-design-system-vf.css')}" />

    <script src="{!URLFOR($Resource.yourDeployable, 'js/script.js')}"></script>
    <script src="{!URLFOR($Resource.yourDeployable, 'js/sdk/forcetk.mobilesdk.js')}"></script>
    <script src="{!URLFOR($Resource.yourDeployable, 'js/sdk/smartsync.js')}"></script>
    <script src="{!URLFOR($Resource.yourDeployable, 'js/sdk/angular-force.js')}"></script>
    <script src="{!URLFOR($Resource.yourDeployable, 'js/sdk/forcetk.ui.js')}"></script>
<body ng-app="myApp">
    <div class="container">
      <div ng-include="'{!URLFOR($Resource.yourDeployable, 'partials/header.html')}'"/>
      <div class="main" ng-view="ng-view"></div>
      <div ng-include="'{!URLFOR($Resource.yourDeployable, 'partials/footer.html')}'"/>

    <script type="text/javascript">
      // used by angular-force to log in.
      var configFromEnv = {};
      configFromEnv.sessionId = "{!$API.session_Id}";
      // used for templateUrls etc.
      var SalesforceURLPrefix = "{!URLFOR($Resource.yourDeployable, '')}/";
    <script src="/soap/ajax/35.0/connection.js" type="text/javascript"></script>
    <script type="text/javascript">
      // use this to get your user id:
      sforce.connection.sessionId = "{!$Api.Session_ID}";
    <script src="/soap/ajax/35.0/apex.js" type="text/javascript"></script>

You will see that this file includes scripts using URLs created though the syntax {!URLFOR($Resource.yourDeployable, 'js/script.js')}. This references the files inside your zip file.

Note that we have included four special libraries, forcetk.mobilesdk.js, smartsync.js, angular-force.js, and forcetk.ui.js. You can get those from some of the excellent samples found here: https://github.com/developerforce/MobilePack-AngularJS/. You can use them to access the standard back-end controllers from your Angular front-end. Walk through the samples and you will quickly see how this works. See https://github.com/developerforce/MobilePack-AngularJS/blob/master/samples/AngularVFBootstrap/src/staticresources/Archive/js/init.js for how to initialize your app (using the session ID we assigned to configFromEnv.sessionId in the apex page) and https://github.com/developerforce/MobilePack-AngularJS/blob/master/samples/AngularVFBootstrap/src/staticresources/Archive/js/app.js for how to query objects. Do not forget to AngularForce.login(). When you use the AngularForceObjectFactory in its raw form, you also have to remember to $scope.$apply().

Whereas this approach works in principle, it comes with a couple of problems. First, your views and templates (those that are typically referred to in Angular by templateUrl, are resolved relatively to the main page. However, if you package them into yourDeployable.package, URLFOR will assign an obscure numeric URL which is next to impossible to hardcode into all your template URLs. Because of that, we have added this line of code to the page:

var SalesforceURLPrefix = "{!URLFOR($Resource.yourDeployable, '')}/";

Now, convert that into an Angular constant and prefix all your templateURLs with it.

Ok, now you can get into the real development. But as soon as you do so, you will soon recognize that you have to do a lot of work to get your little changes in JS files and views up into the Cloud and see your changes. This can be automated, e.g. with grunt, but each deploy still can take up to 20 seconds. This can become quite annoying quickly. Note that the obvious solution, to serve all static resources including the main HTML page locally, does not work: We need to inject the session ID, which is only possible by using the APEX directives as in the above page.

This solution has worked well for us: Just create a copy of the above apex page, and replace all the {!URLFOR($Resource.yourDeployable, '...')} by references to localhost, and deploy it to Salesforce as well. Now serve all static resources (except the main HTML file) locally, and they will be linked and included from your main page on Salesforce. You will now run into two more easily fixable problems:

  • CORS and mixed content (HTTP/HTTPS) policies will prevent stuff from loading and your browser will explode with security warnings. Enable loading of unsafe scripts and get a plugin to disable the CORS policy for development purposes.
  • We have used absolute URLs in our templatesUrls, so those are not loaded from localhost. Fair enough, all we have to do is replace the SalesforceURLPrefix by localhost as well.

With this setup, we were able to develop a Salesforce SPA quite efficiently, with a minimal number of redeploys and zero server-side controllers.

  • I would add that when we created a quote configurator it was extremely helpful to just create the expected JSON objects that you would receive back from Salesforce and wire those in locally and use Node.js to build everything locally. Once completed, you can wire in the calls to SFDC which should be relatively simple to all the work you went through for the rest of the project. Commented Dec 18, 2015 at 0:34

Simon's answer is very great, and I recommend reading all of it.

But, I would ask you to make sure that developing ON Salesforce makes the most sense. Salesforce offers some VERY powerful REST (and SOAP) APIs, and pretty much anything you can do in the interface can be done via the API. Users would have to authenticate via OAuth (a very standard protocol which Angular &c all have methods of handling) and you could develop like any other SPA, just with the SFDC API instead of your own backend.

Writing on platform has a few advantages if you want to embed your work right into the UI, but if that's not a requirement (and it probably isn't), I wouldn't bother learning all the quirks of writing on platform unless you need to!

  • Thanks, @Christian, great answer. In fact, I would have chosen that approach myself, but the tight integration into the UI was a requirement. We had implemented an oauth prototype earlier, but the additional step to log in was not the best user experience. Commented Dec 18, 2015 at 0:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .