Зовнішні залежності

За певних обставин вам можуть знадобитися можливості бібліотеки, написаної на JavaScript, аналогу якої немає в ClojureScript, тобто вам буде потрібно підключити таку бібліотеку в проект.

Залежно від бібліотеки способів підключення може бути багато. Розглянемо деякі з них.

Бібліотеки, сумісні з модулями Google Closure

Якщо бібліотека сумісна з системою модулів в Google Closure Library, вам потрібно лише додати її до проекту і звернутися до неї через простір імен так само, як це роблять з просторами імен в ClojureScript.

Це найпростіший спосіб, бо модулі Google Closure напряму сумісні з ClojureScript, і ви спокійно можете використовувати їх у вашому коді.

Давайте спробуємо підключити такий модуль у проекті за допомогою шаблона mies.

lein new mies myextmods
cd myextmods

Далі створіть модуль Google Closure для експерименту:

.src/myextmods/myclosuremodule.js

goog.provide("myextmods.myclosuremodule");

goog.scope(function() {
  var module = myextmods.myclosuremodule;
  module.get_greetings = function() {
    return "Hello from google closure module.";
  };
});

Тепер відкрийте REPL та спробуйте імпортувати простір імен і викликати функцію з нього:

(require '[myextmods.myclosuremodule :as cm])
(cm/get_greetings)
;; => "Hello from google closure module."

ЗАУВАЖЕННЯ: ви можете відкрити ClojureScript REPL в Node.js, виконавши скрипт ./scripts/repl.

Бібліотеки, сумісні з модулями CommonJS

Завдяки популярності Node.js формат модулів CommonJS є найбільш вживаним в JavaScript бібліотеках незалежно від того, де вони використовуються: у клієнтських застосунках чи на сервері.

Подивимося, що вийшло. Створіть файл з модулем у форматі CommonJS (дуже схожий на модуль з попереднього прикладу):

.src/myextmods/mycommonjsmodule.js

function getGreetings() {
  return "Hello from commonjs module.";
}

exports.getGreetings = getGreetings;

Для того, щоб ми могли застосувати цю бібліотеку, нам треба підключити її за допомогою спеціальної конфігурації для компілятора. У полі :foreign-libs описуються модулі JavaScript: шлях до файлу, формат модуля та ім'я простору імен, під яким цей модуль буде доступний з ClojureScript.

Відкрийте файл scripts/repl.clj та замініть його вміст на цей:

(require
  '[cljs.repl :as repl]
  '[cljs.repl.node :as node])

(repl/repl
 (node/repl-env)
 :language-in  :ecmascript5
 :language-out :ecmascript5
 :foreign-libs [{:file "myextmods/mycommonjsmodule.js"
                 :provides ["myextmods.mycommonjsmodule"]
                 :module-type :commonjs}]
 :output-dir "out"
 :cache-analysis false)

ЗАУВАЖЕННЯ: Шлях до файлу модуля може бути не тільки локальним, а й у вигляді посилання на файл на іншому веб-сервері, який завантажиться автоматично.

Спробуємо застосувати цей модуль у REPL. Запустіть REPL за допомогою скрипта ./scripts/repl і спробуйте виконати наступні команди:

(require '[myextmods.mycommonjsmodule :as cm])
(cm/getGreetings)
;; => "Hello from commonjs module."

Бібліотеки без модулів

Хоча сьогодні більшість бібліотек побудована з використанням модулів, все ще існують такі, що просто експортують глобальний об'єкт. У вас може виникнути необхідність використовувати їх в ClojureScript.

Для застосування бібліотек, які використовують глобальні обʼєкти, слід створити конфігурацію, схожу на ту, що потрібна для модулів CommonJS. Відмінністю буде те, що в описі модуля не потрібно вказувати поле :module-type.

В результаті буде створений синтетичний простір імен, який треба імпортувати, щоб мати доступ до глобального об'єкту модуля у просторі імен js/. Простір імен називається синтетичним, бо не містить жодних об'єктів, він просто вказує компілятору на необхідність підключити залежність.

Перевіримо результат. Створіть файл з глобальною функцією:

.src/myextmods/myglobalmodule.js

function getGreetings() {
  return "Hello from global scope.";
}

Відкрийте scripts/repl.clj та змініть його вміст на цей:

(require
  '[cljs.repl :as repl]
  '[cljs.repl.node :as node])

(repl/repl
 (node/repl-env)
 :language-in  :ecmascript5
 :language-out :ecmascript5
 :foreign-libs [{:file "myextmods/mycommonjsmodule.js"
                 :provides ["myextmods.mycommonjsmodule"]
                 :module-type :commonjs}
                {:file "myextmods/myglobalmodule.js"
                 :provides ["myextmods.myglobalmodule"]}]
 :output-dir "out"
 :cache-analysis false)

Тепер спробуємо застосувати цей модуль в REPL:

(require 'myextmods.myglobalmodule)
(js/getGreetings)
;; => "Hello from global scope."

results matching ""

    No results matching ""