Смешанные Clojure и ClojureScript сборки с Clojurephant - PullRequest
0 голосов
/ 08 апреля 2020

Я подумываю переместить проект из boot в Gradle с clojurephant в надежде использовать больше экосистемы Gradle. Этот проект создает один большой Uberjar, который содержит проект Clojure с Ring и Jetty, который, в свою очередь, поставляет приложение ClojureScript, созданное с перекадровкой.

При загрузке мне просто потребовалось boot-cl js, добавлено

(boot-cljs/cljs :optimizations :advanced)

в мою задачу сборки, которая также вызывает (pom), (aot) и (uber) (все стандартные загрузочные задачи), и все работало гладко.

С Clojurephant я обнаружил, что части Clojure и ClojureScript оказываются в разных подкаталогах. В частности, я нахожу под build

  • clojure/main
  • clojurescript/main
  • resources/main (по сути, копию моей папки проекта resources )

В дополнение к моему заблуждению, эти пути не преобразуются так, как я вижу, в структуру Uberjar, которую Gradle создает с помощью плагина тени

Некоторые выдержки из моего build.gradle:

plugins {
    id 'dev.clojurephant.clojure' version '0.5.0'
    id 'dev.clojurephant.clojurescript' version '0.5.0'
    id 'application'
    id 'com.github.johnrengelman.shadow' version '5.0.0'
    id 'maven-publish'
    id 'distribution'
    id 'com.meiuwa.gradle.sass' version '2.0.0'
}
// ...
clojure {
  builds {
    main {
      aotAll()
    }
  }
}
// ...
clojurescript {
  builds {
    all {
      compiler {
        outputTo = 'public/app.js'
        outputDir = 'public/js/out'
        main = 'com.example.mycljsstuff'
        assetPath = 'js/out'
      }
    }
    main {
      compiler {
        optimizations = 'advanced'
        sourceMap = 'public/app.js.map'
      }
    }
    dev {
      compiler {
        optimizations = 'none'
        preloads = ['com.example.mycljsstuff']
      }
    }
  }
}

EDIT: забыл упомянуть, что для загрузки я настраиваю функцию init, чтобы начать загрузку кода CL JS в файл с именем app.cljs.edn , С Clojurephant я нашел только способ установить основное пространство имен, а не функцию.

В конечном итоге мой вопрос заключается в том, как я могу настроить сборку ClojureScript, чтобы она работала в конце при доставке из Uberjar?

Кажется, что Clojure работает. Ring и Jetty работают и с радостью предоставляют первую веб-страницу stati c. Но все вещи CLJS / JS не могут быть найдены.

Я был бы очень рад просто получить некоторые ссылки на другие проекты, где я могу учиться, документацию или учебные пособия. Я не нашел много, а потом заблудился в понимании кода самого Clojurephant.

Ответы [ 2 ]

1 голос
/ 08 апреля 2020

Год за go на работе Мне удалось разделить объединенный проект CLJ & CL JS (backend / frontend) на 2 отдельных проекта: чистый Clojure для внутреннего интерфейса и чистый ClojureScript для внешнего интерфейса. Это решило многие проблемы, которые у нас были, и я бы никогда не попытался снова сохранить две кодовые базы в одном и том же проекте.

  • Бэкэнд-часть CLJ продолжала использовать Lein в качестве инструмента для сборки. Она не идеальна, но хорошо понятна.
  • Часть интерфейса CL JS была переведена из оригинального Figwheel (он же «1.0») в более новый Figwheel-Main (он же «2.0»). Следуя указаниям figwheel.org , мы решили реструктурировать сборку с использованием Deps / CLI (оригинальный комбинированный проект использовал Lein для всего). Переход от Lein к Deps / CLI стал настоящим победителем для работы CL JS.

Хотя Deps / CLI отлично работает для чистого кода Clojure, имейте в виду, что он изначально не поддерживает включение Java исходный код. У меня есть шаблон проекта , который вы можете клонировать, который показывает простой обходной путь для этого.

Для любого проекта CL JS, я весьма рекомендуем использовать Figwheel-Main вместо оригинального Figwheel, так как это основной тип обновления 2.0, который сделает вашу жизнь намного, намного лучше.

Наслаждайтесь!

0 голосов
/ 20 апреля 2020

Попытка ответить на мой собственный вопрос здесь, так как мне удалось его запустить.

Clojure

plugins {
    id 'dev.clojurephant.clojure' version '0.5.0'
    id 'application'
    id 'com.github.johnrengelman.shadow' version '5.0.0'
    // ... more to come further down
}
group = 'com.example'
version = '1.0.0-SNAPSHOT'
targetCompatibility = 1.8
mainClassName = 'com.example.myproject'

dependencies {
    implementation(
        'org.clojure:clojure:1.10.1',
        'ring:ring:1.8.0',
        // and many more
    )
    testImplementation(
        'junit:junit:4.12',
        'clj-http-fake:clj-http-fake:1.0.3',
        'ring:ring-mock:0.4.0'
    )
    devImplementation(
        'org.clojure:tools.namespace:0.3.0-alpha4',
        'cider:cider-nrepl:0.21.1',
        'org.clojure:java.classpath',
        'jonase:eastwood:0.3.11',
        'lein-bikeshed:lein-bikeshed:0.5.2'
    )
}

clojure {
  builds {
    main {
      aotAll()
    }
  }
}

clojureRepl {
  handler = 'cider.nrepl/cider-nrepl-handler'
}

Этого достаточно, чтобы получить исполняемый JAR, работающий -main из com.example.myproject namespace при вызове ./gradlew shadowJar из командной строки. Не уверен, что плагин application уместен здесь. Кроме того, ./gradlew clojureRepl раскручивает nrepl, к которому может подключиться Emacs / Cider.

ClojureScript

// Merge with plugins above. Reproduced only the CLJS relevant
// part here
plugins {
    id 'dev.clojurephant.clojurescript' version '0.5.0'
}

// Again, merge with dependencies above
dependencies {
    implementation(
        // ....
        'org.clojure:clojurescript:1.10.597',
        're-frame:re-frame:0.10.5',
        'reagent:reagent:0.7.0',
        // and a few more
    )
}

clojurescript {
    builds {
        all {
            compiler {
                outputTo = 'public/app.js'
                outputDir = 'public/state/'
                main = 'com.example.myproject.webui'
                assetPath = 'status/app.out'
            }
        }
        main {
            compiler {
                optimizations = 'advanced'
                sourceMap = 'public/app.js.map'
            }
        }
        dev {
            compiler {
                optimizations = 'none'
                preloads = ['com.example.myproject.webui']
            }
        }
    }
}

Это создает папку /public на верхнем уровне там JAR и app.js внутри этой папки, где его ожидает доставленный Ring файл HTML.

Одним из важных шагов для меня было вызвать мою init CL JS функцию в файле CL JS, которая раньше заботился о каком-то другом компоненте. Я не уверен, что эта установка полностью правильная и в конечном итоге сделает настройку figwheel. Возможно, тогда вызов init не будет необходим.

CSS

// Merge ....
plugins {
    id 'com.meiuwa.gradle.sass' version '2.0.0'
}
sassCompile {
    output = file("$buildDir/resources/main/public/")
    source = fileTree("${rootDir}/src/main/resources/public/")
    include("**/*.scss")
    exclude("**/_*.sass", "**/_*.scss")
}

Это скомпилирует мои app.scss в app.css в нужном месте, где мой HTML файл ищет его.

Pro & Con

После миграции я получаю бесплатно

  • Более быструю компиляцию локально и в CI после правильной настройки кэшей.
  • Лицензия и OW ASP отчеты о проверке депонирования с использованием плагинов com.github.jk1.dependency-license-report и org.owasp.dependencycheck, для которых существуют эквиваленты в leiningen, но не при загрузке (AFAIK).
  • Публикация Maven с аутентификацией по HTTP заголовок вместо имени пользователя / пароля, который недоступен при загрузке.

С другой стороны:

  • Гадкий синтаксис в моем файле сборки. Нет, правда.
  • Мне нужно вручную ввести номер порта nrepl в Emacs.
...