Tl;dr

Я создал шаблон Angular 2 здесь, который позволяет вам более легко разрабатывать приложения Angular 2 на платформе Salesforce. Сделать это было непросто и далеко не до конца, поэтому я приветствую любой вклад.

JavaScript и Salesforce

Представьте, если хотите, что эта статья представляет собой презентацию на ng-conf, Dreamforce, Texas JS или на какой-нибудь другой технической конференции. Если бы это было так, я бы, вероятно, начал с вопроса, сколько людей работали на платформе Salesforce, а затем, из этого числа, сколько людей пытались написать приложения javascript, которые работают на Salesforce. Я предполагаю, что где-то от 30 до 40 процентов людей поднимут руки прямо сейчас (оставшиеся 60-70 процентов, как мне кажется, не являются разработчиками).

Как разработчик JavaScript превратился в разработчика Salesforce, я привык к инструментам и гибкости, которые обеспечивает работа с JavaScript. У вас есть доступ к NPM и Bower, транспиляторам JavaScript, препроцессорам CSS, линтерам, локальным серверам и множеству других инструментов, которые сделают вас быстрым и продуктивным. С Salesforce вы ничего этого не получите.

Немного предыстории

Мой первый проект Salesforce был передан нашей компании из внешнего источника и сильно написан на Angular 1. Не было ни Gulp, ни Grunt, ни Webpack, ни Node. Просто Angular. Это само по себе не страшно. Люди все время пишут приложения на Angular без диспетчера задач. Однако одним из ключевых преимуществ разработки веб-приложений в такой среде, как Angular, является ваша способность запускать локальный сервер разработки. Эта функциональность также отсутствовала.

Что это значило для нашего проекта? Это означало, что каждый раз, когда мы хотели протестировать наши изменения или внести какие-либо небольшие изменения, нам приходилось ждать, иногда до двух минут, пока наш статический ресурс не развернулся в Salesforce. Затем нам пришлось обновить страницу и дождаться загрузки этого монолитного приложения Angular 1 только для того, чтобы обнаружить, что ошибка все еще существует или внесенное нами изменение не дало ожидаемого результата. Затем нам придется повторять этот процесс до тех пор, пока не будет достигнут ожидаемый результат.

Что касается времени, потраченного на эту стратегию разработки, я подсчитал, что мы теряли от 1 до 4 минут на итерацию и более часа в день на ожидание развертывания статических ресурсов. К сожалению, к тому времени, когда я придумал решение, мы были уже слишком далеко в проекте, чтобы внести изменения, необходимые для исправления нашего рабочего процесса.

Пока мы работали над этим проектом, я также работал над побочным проектом для презентации, которую планировал сделать на Angular 2. Я обнаружил, что Angular 2 намного проще в освоении и рассуждении, чем Angular 1, и хотел иметь возможность его использовать. в будущих проектах Salesforce. Я также не хотел, чтобы этот процесс разработки когда-либо снова повторялся. Мои цели для проекта были довольно простыми, я хотел создать шаблонное приложение Angular 2, которое можно было бы легко развернуть в Salesforce и которое позволяло бы легко выполнять локальную разработку. Также из-за ограничений REST API приложение должно иметь возможность использовать REST API локально, но в Salesforce следует использовать Visualforce Remoting, у которого нет ограничений API.

Начиная

Сделать само приложение было легко, в Интернете есть множество обычных 2-х руководств, а запуск и запуск приложения действительно может быть выполнен всего за 5 минут (с некоторой практикой). С помощью Gulp также легко настроить локальный сервер разработки. Как и ожидалось, сложнее всего было взаимодействие между приложением и Salesforce.

Первым препятствием, которое мне пришлось преодолеть, была проверка подлинности. В самой системе Salesforce это не проблема. Visualforce Remoting не требует аутентификации, кроме аутентификации, которую вы предоставляете при входе в Salesforce. REST API немного отличается. Именно здесь на помощь приходит замечательная библиотека под названием JSForce. JSForce описывается на своем веб-сайте как [] изоморфная библиотека JavaScript, использующая API Salesforce. Он предоставляет набор инструментов для выполнения всего, от аутентификации с помощью Salesforce до выполнения запросов и анонимного APEX. С помощью JSForce мне удалось решить проблему локальной аутентификации.

Следующим шагом было создание приложения с нужной мне функциональностью. Всякий раз, когда я создаю API, службу Angular или что-то еще, где я хочу, чтобы он вел себя определенным образом, я стараюсь работать в обратном направлении. Сначала я напишу полный сценарий использования сервиса, а затем запрограммирую сам сервис. Итак, я приступил к созданию небольшого приложения для управления контактами.

Как только у меня появилась нужная мне функциональность, я начал взламывать сам сервис. Первым шагом было создание и запуск поддержки REST API, что с использованием JSForce было довольно простым делом. Затем у меня возникла мысль: «Есть ли у JSForce способ выполнять методы на контроллерах APEX, как это делает Visualforce Remoting?» К сожалению, ответ был отрицательным. JSForce имеет всевозможные методы для взаимодействия со всеми API, которые есть в Salesforce, включая REST, SOAP, Batch, Bulk, Tooling и Chatter API; но у него не было возможности выполнять удаленные действия извне Salesforce.

После долгих поисков я обнаружил, что то, что я хотел сделать, по крайней мере, не невозможно. Это просто ужасно документированный процесс, как и большинство API Salesforce. Для тех, кто не в курсе, Salesforce неравнодушен к SOAP как формату API. SOAP расшифровывается как простой протокол доступа к объектам и предполагает использование конвертов XML, передаваемых туда и обратно для создания, чтения, обновления и удаления данных. В то время как JSON (формат связи REST) ​​широко используется и поддерживается многими языками программирования, XML - нет.

В итоге мне пришлось отправить Salesforce такой конверт:

Где AngularAppController - это имя контроллера, на котором я пытаюсь выполнить метод, sessionId - это идентификатор сеанса, который я получил при аутентификации с помощью JSForce, executeQuery - это имя метода на контроллере, а query - первый и единственный аргумент, который принимает метод.

Сам метод контроллера выглядит так:

Любой, кто знаком с Salesforce и APEX в частности, заметит несколько странностей в моем коде APEX. Во-первых, это класс global. К сожалению, чтобы собрать все это вместе, мне пришлось использовать WebServices в дополнение к RemoteActions. webServices для работы требуется, чтобы класс был global. Другая странность заключается в том, что я использую вместе WebService и RemoteAction. Перед попыткой я не был уверен, возможно ли это, но у меня не было никаких проблем.

Разные форматы

Теперь у меня возникла интересная головоломка. Поскольку я был вынужден использовать SOAP API для локального выполнения методов APEX, я получал ответы в виде полезных данных XML. Однако с помощью Visualforce Remoting я получаю ответы в виде объектов JSON. Так началась, наверное, самая сложная часть этого путешествия. Если бы я хотел, чтобы эта служба работала как локально (с помощью SOAP и XML), так и удаленно (с помощью JSON), мне нужно было отформатировать данные из обоих ответов, чтобы у меня был согласованный API. Это означало преобразование ответа SOAP в JSON, который напоминал ответ VFR (Visualforce Remoting).

Эта часть проекта привела меня к пути, который потребовал преобразования XML в JSON, удаления пространств имен из ключей, удаления атрибутов, которые не возвращает VFR, и, наконец, получения данных в правильном формате. По завершении я смог использовать данные любого вызова точно так же.

Заключение

Я мог бы углубиться во многие аспекты этого проекта, но в итоге эта статья стала бы длиннее, чем необходимо. Не стесняйтесь проверить репозиторий моего Salesforce Angular 2 Boilerplate здесь и не стесняйтесь отправлять запросы на вытягивание, проблемы и задавать мне вопросы. Я доступен в твиттере @ iDev0urer.

Если вам понравилась эта статья, нажмите кнопку рекомендовать! Мое эго благодарит вас.