Создание веб-приложений на Julia
Julia — это высокоуровневый, высокопроизводительный, универсальный язык программирования. «Высокий уровень» относится к его выразительному синтаксису, современным структурам данных и сложной системе типов, что позволяет программисту решать сложные задачи с помощью компактных и читаемых программ. Высокая производительность достигается благодаря уникальной системе компиляции just-in-time, которая превращает код высокого уровня в машинные инструкции для любой из многочисленных поддерживаемых архитектур Julia, включая GPU. Julia является универсальным языком, потому что удобно использовать его в любых областях задач. Единственные области, где Julia может оказаться неидеальным выбором из-за накладных расходов на компиляцию, — это встроенные и системы реального времени (хотя даже это может измениться в будущем).
Изначально Julia задумывалась как новый язык для научных и технических вычислений. С момента своего относительно недавнего публичного выпуска в 2012 году её уникальное сочетание передовых концепций в проектировании языка с непревзойденной производительностью привело к быстрому и энтузиастическому принятию во многих областях науки и инженерии. Это один из всего четырёх языков, которые были использованы на суперкомпьютерах для петафлопных вычислений (остальные — Fortran, C и C++).
Из-за акцента на технических вычислениях в сообществе Julia, большинство книг, онлайн-документации и учебных материалов ориентированы на ученых и инженеров, которые заинтересованы в использовании языка для моделирования, анализа данных и визуализации результатов; это, безусловно, верно для моей собственной книги, например. Тем не менее, Julia также является отличным выбором для других типов приложений.
Основные выводы
- Два мощных подхода: Julia предлагает два различных метода создания веб-приложений — PlutoSliderServer для интерактивных приложений на основе блокнотов и HTMX + WebSockets для пользовательских веб-приложений с полным контролем над дизайном интерфейса.
- Высокопроизводительный бэкенд: возможности Julia по компиляции в режиме Just-in-Time и научным вычислениям делают её отличным выбором для веб-приложений с высоким объёмом вычислений, особенно тех, которые связаны с анализом данных, визуализацией или математическими расчётами
- Простая интеграция виджетов: PlutoSliderServer предлагает богатую коллекцию готовых виджетов через PlutoUI, позволяя разработчикам создавать интерактивные приложения без глубоких знаний HTML/JavaScript
- Коммуникация в реальном времени: Оба подхода используют WebSockets для отзывчивого взаимодействия между фронтендом и бэкендом в реальном времени, обеспечивая плавный пользовательский опыт
- Интеграция научных вычислений: Поддержка Julia символов Unicode, математической нотации и обширных научных библиотек делает её идеальной для образовательных и научно-ориентированных веб-приложений.
- Гибкое развертывание: Приложения могут быть развернуты с использованием контейнеров (systemd-nspawn, Docker) с настройками обратного прокси (Apache/Nginx) для безопасного и масштабируемого хостинга.
- Обработка медиа: Подход HTMX поддерживает прямое внедрение медиа с использованием кодированных в Base64 URL-адресов данных, устраняя необходимость в отдельном хранении файлов и запросах.
Джулия в интернете?
Недавно я использовал Julia в качестве серверного языка для интерактивных веб-сайтов, чтобы демонстрировать концепции физики. Поскольку доступной информации о том, как создавать подобные проекты, было очень мало, мне пришлось собирать необходимые знания из различных источников и дополнять картину большим количеством экспериментов и тестирования. Эта статья является кульминацией этого процесса и отражает моё желание представить в одном месте полный гид по созданию интерактивных веб-приложений с использованием Julia.
Я обнаружил, что Julia является идеальным языком для этой цели. Все достоинства, которые делают его настолько подходящим для вычислительных задач в науке, делают его приятным в использовании на серверной части веб-приложения, особенно если оно связано с физическими вычислениями. В дополнение к уже упомянутым функциям, Julia позволяет использовать греческие буквы и символы Unicode в названиях переменных, что позволяет научному программисту придать строкам кода знакомый вид, делая их более похожими на его или её любимые уравнения. Широкая коллекция графических и аудиобиблиотек Julia предоставляет удобные решения для создания диаграмм, анимаций или звуков, чтобы иллюстрировать научные концепции, которые я стремлюсь объяснить на своих веб-страницах.
В Julia также почти тривиально легко создавать фоновые задачи или выполнять вычисления параллельно на нескольких процессорах, что является факторами, способными улучшить отзывчивость через веб. Я обнаружил, что в Julia есть отличные библиотеки для сетевого взаимодействия, особенно важные для работы с WebSockets, что оказалось ключевым элементом для моей задачи. Части моих программ для обработки коммуникации с браузером оказались удивительно компактными и легкими для написания, а производительность была отличной, что в конечном итоге убедило меня в успешности эксперимента и сделало описанные здесь методы моими любимыми способами создания такого рода интерактивных сайтов.
В этой статье я описываю два метода создания интерактивных веб-приложений с использованием Julia. Первый метод использует веб-сервер PlutoSliderServer, который позволяет превратить блокнот Pluto в веб-приложение, которое можно безопасно разместить в открытом доступе в интернете. Этот метод можно использовать даже если вы не знакомы с HTML или JavaScript, так как вы можете создавать приложение из большого набора готовых виджетов, которые автоматически задают значения переменных в ваших программах на Julia. Второй метод более универсальный и позволяет создавать любые веб-приложения, которые только можно вообразить. Он основан на HTMX и некотором простом (необязательном) JavaScript на фронтенде, обмен данными осуществляется через WebSockets с вашими бэкенд-программами на Julia. Все термины и идеи, упомянутые в этом абзаце, я объясню в последующих разделах, так что не пугайтесь, если я упомянул что-то незнакомое. Все это стоит изучить.
СерверПлутонСлайд
Pluto — это вычислительная тетрадь, которая использует веб-браузер в качестве интерфейса. Это эволюция популярной тетради Jupyter, которая улучшает концепцию, исправляя несколько проблем в дизайне Jupyter. В то время как Jupyter может служить интерфейсом для многих разных языков (название является комбинацией Julia, Python и R, его первоначальных партнёров), Pluto работает и, вероятно, всегда будет работать только с Julia.
Подобно Jupyter, Pluto изначально был предназначен для предоставления удобного интерфейса к языковому ядру, работающему локально на той же машине, что и веб-браузер, который обрабатывает интерфейс Pluto. Хотя существуют решения, позволяющие Pluto работать через веб, для моих целей здесь я не хочу просто открывать блокнот для пользователя.
В идеале я хочу простой способ перевести блокнот Pluto на веб-страницу с интерактивностью, обеспечиваемой виджетами с четко определенным поведением; я не хочу, чтобы посетители страницы могли выполнять произвольный код на Julia, что возможно в полном интерфейсе Pluto.
PlutoSliderServer предлагает идеальное решение. С помощью этого подхода вы создаете блокнот Pluto, который включает любые вычисления, медиа и пояснительный текст (с использованием Markdown или HTML), которые вы хотите. Взаимодействие с пользователем обеспечивается большой коллекцией виджетов (включая популярный элемент управления слайдером, отсюда и название) из пакета PlutoUI. Каждый виджет привязан к значению переменной, и когда пользователь изменяет значение переменной, соответствующий код немедленно выполняется на сервере с новым значением, отображая результаты.
Здесь я пройду через каждый шаг, необходимый для создания и обслуживания веб-приложения с этим подходом. URL-адреса ведут вас на две страницы, которые я создал с использованием этой технологии, а также на ссылку на вводный курс Массачусетского технологического института по вычислительному мышлению, который широко использует PlutoSliderServer в своих онлайн-лекциях.
- Введение в вычислительное мышление. А. Эдельман, Д.П. Сандерс и К.Е. Лейзерсон, лекторы. Примеры MIT HTMX
- Симуляция акустики щипковых струнных инструментов
- Моделирование двумерной вихревой динамики
Установка и настройка
Я объясню все, что вам нужно для этого путешествия, но поездка будет немного легче, если у вас будет хотя бы небольшое знакомство с Julia и её системой пакетов.
Первым шагом является установка Julia, если она у вас ещё не установлена. Я рекомендую обновиться, если ваша установленная версия старее версии 1.8. Я проверял все примеры из этой статьи на версии 1.10; версия 1.11 недавно стала доступна, но у меня возникли некоторые проблемы с совместимостью пакетов в этой версии хотя бы с одним из примеров, поэтому версия 1.10 может быть более стабильной, по крайней мере, пока не будут решены проблемы с Pluto в последнем выпуске.
Чтобы установить Julia на любую широко используемую операционную систему, посетите сайт Julia и нажмите большую зеленую кнопку Download. Когда Julia будет установлена и запущена, вам понадобятся несколько пакетов. «Пакет» в Julialand — это библиотека функций и структур данных, которую вы можете импортировать и использовать в своих программах.
Для разработки приложения PlutoSliderServer вам потребуется пакет Pluto. Запустите Julia REPL (интерактивный терминал с циклом чтения-вычисления-вывода) в терминале, введя julia. Конечно, вы также можете использовать Visual Studio (VS) Code или вашу любимую среду разработки, и процедура будет в основном такой же. Хотя сейчас вы можете продолжить разработку веб-приложений PlutoSliderServer в вашей стандартной среде Julia, лучшей практикой будет создание отдельной среды для каждого проекта, чтобы предотвратить конфликты пакетов в будущем и поддерживать порядок в вашей работе. «Среда» в Julia — это просто каталог на вашем файловом хранилище, содержащий два специальных файла, поддерживаемых Julia, которые перечисляют пакеты с разрешёнными зависимостями, необходимыми для вашего проекта, вместе со всеми файлами вашей программы. Последние представляют собой текстовые файлы с расширением .jl.
После того, как вы решите, где в файловой системе будет расположен ваш новый проект, нажмите кнопку правого квадратного кронштейна (] ) в режиме, чтобы активировать режим пакета. Подсказка изменится с зеленой julia> на синий pkg> . Новой подсказке предшествует обозначение в скобках, указывающее на вашу текущую среду. Первоначально вы находитесь в среде по умолчанию для версии Юлии, которую используете (в этом примере, версии 1.10).
Следующий шаг — активировать новую среду, которую вы выбрали для своего проекта; Команда для этого также показана на рисунке. На этом этапе, если вы нажмете клавишу Backspace, вы вернетесь в нормальный режим Repl. Тем не менее, вы хотите остаться в режиме упаковки немного дольше, чтобы добавить один пакет, необходимый для всей разработки в Pluto: пакет pluto . В режиме пакета, в приглашении pkg> введите команду
add Pluto
скачать и предварительно скомпилировать программные файлы пакета (необходимо подключение к Интернету). Процесс может занять от менее минуты до нескольких минут в зависимости от скорости вашего интернет-соединения и вашего компьютера.
Блокноты Pluto содержат собственные окружения, полностью инкапсулированные внутри самих блокнотов. Такая организация помогает сделать их переносимыми, а вычисления — воспроизводимыми, что является важным фактором для ученых, которые составляют существенную часть их пользовательского сообщества. Поэтому любые дополнительные пакеты, необходимые для вычислений в блокноте, не будут добавляться в REPL, а будут импортироваться прямо в блокнот. Julia и Pluto управляют этими пакетами «за кулисами».
Разработка блокнота
Вы разработаете свой ноутбук в веб -интерфейсе, предоставленном Pluto. Следующим шагом при запуске этого интерфейса, то есть установлением соединения между веб -браузером и процессом Юлии на вашем компьютере, является выход из режима пакета в командах REPL и выполнение в обычной зеленой Юлии> Подсказка:
using Pluto Pluto.run()
После нескольких сообщений в REPL и небольшой задержки в вашем браузере по умолчанию откроется новое окно с интерфейсом Pluto.
Чтобы заменить эту стартовую страницу на пустую тетрадь Pluto, нажмите на элемент управления с надписью Create a new notebook, где вы начнете разработку вашего веб-приложения. Первый шаг, чтобы оставаться организованным, — это нажать на текст Save notebook в верхней части страницы, чтобы присвоить тетради имя и место в файловой системе. Теперь вы можете размещать любой код в любых ячейках тетради; переставлять ячейки для логичного, педагогически полезного оформления тетради; а также нажимать на маленькие иконки в виде глаза слева от активных ячеек, чтобы решать, будут ли ваши пользователи видеть их содержимое или только результаты. Если вы ранее не использовали Pluto или Jupyter (который следует схожим принципам), на этом этапе может быть полезно обратиться к одной из соответствующих статей или книг, упомянутых в другой части этой статьи; однако интерфейс и поведение приложения достаточно интуитивны.
Если вы использовали Jupyter, но не имеете опыта работы с Pluto, вы должны быть в курсе одного важного различия: в Jupyter ячейки выполняются сверху вниз, а в Pluto их порядок на странице не влияет на выполнение. Ячейки в Pluto выполняются в логическом порядке, следуя графу их зависимостей. Если вы вызываете выполнение какой-либо ячейки, автоматически выполняются все ячейки, результаты которых зависят от результата этой ячейки, следуя цепочке зависимостей до полного завершения. Таким образом, вы можете располагать ячейки так, чтобы это имело наибольший презентационный смысл, а также менять их порядок позже, не влияя на результаты. Эта свобода расположения ячеек сохраняется и в веб-приложении, в которое превращается ваш ноутбук: пользователь сможет управлять элементами управления в любом порядке и всегда будет видеть воспроизводимый, правильный результат.
Вы можете использовать практически любой пакет в ноутбуке, просто импортируя его с помощью оператора using в любой ячейке; последующие загрузки и компиляции происходят автоматически. Единственным обязательным пакетом для любого ноутбука, предназначенного для PlutoSliderServer, является PlutoUI, который содержит код виджетов, с которыми взаимодействуют пользователи. Помимо привычного слайдера, PlutoUI предоставляет большую и полезную коллекцию виджетов, с помощью которых вы можете создавать разнообразные интерактивные сценарии.
Каждый виджет выполняет одну и ту же функцию: он устанавливает или связывает значение переменной с значением, определяемым взаимодействием пользователя с элементом управления. Чтобы вставить виджет на страницу, используйте макрос bind, передавая ему первый аргумент с именем переменной для связывания и второй аргумент, описывающий, какой виджет использовать. Каждый раз, когда пользователь взаимодействует с одним из этих виджетов, значение связанной с ним переменной (возможным образом) изменяется, и выполняется всякая ячейка, зависящая от значения этой переменной (с последующим выполнением всех ячеек, зависящих от результата этой ячейки). Эта техника, таким образом, идеально подходит для демонстрации таких вещей, как показ того, как решение уравнения зависит от значения параметра.
Ниже изображение иллюстрирует использование макроса bind для создания виджетов. В блокноте сначала выполняется необходимый импорт в первой ячейке (обычно это скрыто от конечных пользователей приложения). Вторая ячейка использует синтаксис макросов Julia для вызова макроса, чтобы связать значение ползунка (который может принимать целые значения от 1 до 10) с переменной x. На рисунке значение установлено на 6 с помощью ползунка. Третья ячейка показывает использование макроса NumberField с аргументом ключевого слова, задающим значение по умолчанию. Обратите внимание, что в Pluto результат ячейки отображается над содержимым ячейки.
Последняя ячейка использует нестандартную строковую литералу Markdown для представления строки Markdown. Определение этой строковой литералы не включено ни в Julia, ни в Pluto (ни в PlutoUI), а находится в другом пакете, который автоматически импортируется во всех заметках Pluto, поскольку использование Markdown для создания текстовых ячеек настолько распространено. Строка содержит интерполируемые переменные и использует синтаксис Markdown для курсива и полужирного шрифта. Вы также можете использовать HTML, если Markdown не предоставляет всех необходимых возможностей, либо с помощью нестандартной HTML-литералы (html»<здесь размещается разметка>»), либо с помощью функции HTML(), которая способна включать интерполируемые переменные, которые не работают в HTML-литерале. Ещё более гибкий способ использования HTML в Pluto — это пакет HypertextLiteral, который я широко использую в примере «Вселенная Птолемея».
Когда этот блокнот будет доступен через Интернет с помощью PlutoSliderServer, пользователь сможет использовать ползунок и поле ввода для установки значений x и y, но не сможет изменить код в ячейке, которая вычисляет их сумму. Видим ли этот код или нет — выбор за вами, в зависимости от вашей цели для блокнота.
Настройка сервера
Вы собираетесь разместить веб-страницу в публичном интернете, которая позволяет посетителям запускать программы на языке Julia на удалённом сервере. Хотя взаимодействие через PlutoSliderServer специально ограничено, всегда существует вероятность того, что пользователь найдёт способ, либо злонамеренно, либо случайно, сделать что-то, что не предусмотрено вашими планами (например, процесс Julia, работающий на сервере, потенциально имеет доступ к файловой системе). Это программное обеспечение не даёт никаких гарантий безопасности; разработчику необходимо самостоятельно принять меры, чтобы ограничить возможный ущерб.
Лучший и рекомендуемый способ обеспечить эту дополнительную безопасность — ограничить процесс Julia на сервере какой-либо виртуальной средой, такой как контейнер, из которого невозможно увидеть корневую файловую систему машины. Использование такого контейнера делает наихудший сценарий развитием событий — разрушение самого контейнера; серверная машина останется без повреждений, и администратор сможет снова запустить контейнер.
Среди нескольких широко используемых стратегий контейнеризации моим фаворитом является та, которая встроена в большинство систем Linux: systemd-nspawn. Если вы используете сервер на Linux и у вас пока нет собственного предпочитаемого решения для контейнеров, я советую изучить, как использовать systemd-nspawn для защиты и изоляции серверной среды. Еще один популярный вариант, о котором вы, возможно, уже слышали, это Docker. Не важно, какую технологию контейнеров вы используете, важно то, что вы предпринимаете меры для изоляции процесса Julia на вашем сервере.
При простом тестировании блокнота с сервером слайдера вы, конечно, можете делать всё на своём локальном компьютере, где контейнер не потребуется.
После настройки вашего контейнера и установки Julia на него, вы должны запустить REPL Julia в контейнере, создать окружение, как указано выше (или просто использовать окружение по умолчанию), и импортировать пакет PlutoSliderServer, который включает Pluto как зависимость.
Следующим шагом является настройка веб-сервера на хост-машине (не внутри контейнера). Следующие инструкции будут конкретно для Apache, так как именно на нем я тестировал свои решения. Настройка для Nginx будет довольно похожей.
Цель состоит в том, чтобы настроить Apache для работы в качестве шлюза или обратного прокси, чтобы перехватывать обычные HTTPS-запросы к вашему публичному серверу и перенаправлять их на веб-сервер PlutoSliderServer, работающий в вашем контейнере. Ваши посетители не должны ничего знать о сервере слайдера; они будут взаимодействовать с вашим веб-приложением так же, как с любой обычной веб-страницей.
Для Apache сначала установите или активируйте необходимые модули для включения проксирования: модули proxy, proxy_html и proxy_http. Они могут быть уже установлены; проверьте это в каталоге /etc/apache2/mods-enabled. Далее добавьте строки из Списка 1 в соответствующий раздел файла конфигурации для вашего виртуального домена, если он у вас есть, или для конфигурации по умолчанию. Для Apache файлы находятся в /etc/apache2/sites-enabled/.
- ProxyRequests Off
- AllowEncodedSlashes On
- ProxyPass "/sliders/" "http://127.0.0.1:2345/" nocanon
- ProxyPassReverse "/sliders/" "http://127.0.0.1:2345/" nocanon
Список показывает конфигурацию прокси для моих страниц слайдера, где в URL я использую /sliders/. Настройте эти строки в соответствии с конфигурацией вашего сервера. Директивы передают запросы с браузера пользователя на порт 2345 на локальной машине, который является портом по умолчанию, используемым пакетом PlutoSliderServer. Вы можете изменить порт, если используете его для чего-то другого (см. ниже). Адрес 127.0.0.1 относится к локальной машине и позволяет взаимодействовать с сервером слайдера, работающим в контейнере. Обратите внимание, что внутри машины-сервера связь идет по http — то есть в виде обычного текста. Хотя это приемлемо на данный момент, вам следует настроить Apache (Nginx и т.д.) так, чтобы связь через Интернет осуществлялась по https.
Последний шаг — написать несколько небольших скриптов для запуска Julia и PlutoSliderServer в контейнере. Для выполнения этого последнего шага вы должны быть вошедшими в систему как root внутри контейнера.
Просто запускать Julia из терминала не сработает, так как процесс завершится, когда вы выйдете из контейнера. Даже использование nohup не является надежным способом поддерживать работу Julia. Для этой цели используйте команду systemd-run, которая, как и systemd-nspawn, встроена в большинство современных дистрибутивов Linux (по крайней мере, тех, которые используют systemd, который, хотя и не всеми любим, стал стандартом).
Конкретно, создайте файл со скриптом запуска:
#! /usr/bin/bash echo "Notebook server starting" julia echo "Done." Name it (say) servenotebooks, and make it executable with:
chmod 755 servenotebooks
Как вы можете видеть, весь сценарий просто запускает Julia. Вызов его с systemd-run делает процесс Julia постоянным; в этом и заключается вся его цель.
Одна проблема может возникнуть, которую вам придется решить в зависимости от пакетов, которые вы используете в своем блокноте. Некоторые пакеты предполагают, что Julia запускается на компьютере с графическим дисплеем (например, на системе X Window); однако, как правило, это не так при запуске Julia на сервере. Это создает проблему в одном из моих примерных блокнотов, который использует пакет Javis для создания анимаций. Javis даже не будет компилироваться, если не обнаружит систему для графического вывода.
Одним из решений этой проблемы, если вы с ней столкнетесь, является установка X Windows на сервер. Другим решением является установка программы xvfb-run, которая создаёт виртуальную среду X Window для запуска программы. Чтобы использовать это решение, просто замените julia в приведённом выше скрипте запуска на xvfb-run julia.
Когда Julia запускается, она выполняет скрипт Julia .julia/config/startup.jl в вашем домашнем каталоге. Поскольку Julia будет запускаться в этом контейнере только для работы PlutoSliderServer, вы можете настроить это в скрипте запуска. Создайте (или отредактируйте, если он уже существует) файл по указанному пути, добавив в него следующее содержимое:
using PlutoSliderServer run_directory( "/<the/notebook/directory>/"; Export_offer_binder=false)
Первая строка импортирует единственный пакет, необходимый для работы с ноутбуками; этот пакет был добавлен на предыдущем шаге. Вторая строка запускает сервер слайдера в режиме, в котором он следит за директорией, куда вы хотите поместить ваши ноутбуки (замените /<the/notebook/directory>/ на это местоположение). В этом режиме вы можете добавлять, удалять или загружать обновленные версии всех ваших ноутбуков, и сервер слайдера учтет изменения и будет предоставлять текущее состояние директории. Вам не нужно перезапускать сервер или предпринимать какие-либо другие действия.
Ключевой аргумент (то, что стоит после точки с запятой) для run_directory сообщает серверу не добавлять определённую кнопку на те блокноты, которые вы не хотите отображать. Чтобы увидеть список всех доступных опций для этой функции, войдите в режим справки в Julia REPL, набрав ? <имя функции>.
С этим шагом завершено, ваш сервер готов и работает. Вы можете проверить его состояние с помощью команды journalctl или остановить его с помощью команды systemctl kill. Используйте
julia --startup-file=no
команда, если вы когда-либо захотите запустить Julia в вашем контейнере без выполнения скрипта запуска.
Веб-приложения HTMX
PlutoSliderServer идеален, если у вас уже есть блокнот Pluto, который вы хотите превратить в веб-приложение, или если ваше задуманное приложение хорошо подходит для набора виджетов PlutoUI и структуры блокнота.
В этом разделе я описываю другой способ создания интерактивных веб-приложений, использующих Julia на серверной стороне для вычислений. С помощью этих методов вам не нужны Pluto или какие-либо другие пакеты Julia, кроме тех, которые используются для ваших вычислений, и пакета HTTP, который предоставляет функции для обмена данными через WebSocket.
Взаимодействия на фронтенде построены вокруг HTMX, небольшой библиотеки JavaScript, которая расширяет возможности HTML, позволяя большему количеству элементов отправлять сообщения на сервер и легко заменять фрагменты страницы ответами сервера, вместо того чтобы перезагружать всю страницу при каждом запросе (подобно методу AJAX для обработки запросов и ответов, но с расширенными возможностями и более простой в использовании, без необходимости явного написания JavaScript). Это улучшение как раз то, что нужно для плавного интерактивного опыта.
Этот метод также использует расширение WebSocket для HTMX. PlutoSliderServer использует WebSockets, чтобы сделать взаимодействие более отзывчивым, хотя вам не нужно было об этом знать при настройке клиента и сервера. Метод, описанный в этом разделе, также использует WebSockets по той же причине.
Посетите сайты в разделе «Примеры HTMX» в Таблице 1, чтобы увидеть два примера веб-приложений, которые я создал с использованием методов из этого раздела. Эти примеры дают представление о том, какие вещи вы можете создавать, хотя единственным ограничением является ваше воображение.
Вам нужно будет импортировать небольшую библиотеку HTMX и её расширение WebSocket на вашу HTML-страницу. Вы можете импортировать их напрямую с URL-адресов, указанных в документации, но я предпочитаю скачать их на свой сервер и загружать локально, чтобы избежать потенциальных проблем, включая доступ к сайту HTMX. Если посетитель может попасть на вашу страницу, библиотека HTMX гарантированно загрузится. Недостатком является потеря возможного преимущества кэширования браузера пользователя при первом посещении, но это не имеет большого значения, так как эти JavaScript-библиотеки довольно компактны.
Разместите что-то вроде следующих двух строк ближе к верхней части HTML-страницы вашего веб-приложения:
<script src="/htmx.js"></script> <script src="/ws.js"></script>
Этот пример предназначен для случая, когда вы разместили файлы в корне вашего веб-каталога, но, конечно, вы можете поместить их в другое место. Вторая строка загружает расширение WebSocket.
Поскольку у вас не будет доступа к коллекции виджетов PlutoUI, вам потребуется некоторое знакомство с HTML, чтобы эффективно использовать описанный здесь метод. Кроме того, полезно знать немного чистого JavaScript, на случай если вы захотите кастомизировать взаимодействие с пользователем сверх того, что могут предоставить HTMX и HTML (хотя с помощью этих двух технологий вы можете добиться многого без использования JavaScript вообще).
Следующий пример иллюстрирует различия в определении виджетов между PlutoUI и HTML. В предыдущих примерах создавался ползунок в блокноте Pluto с
@bind x Slider(1:10)
В HTML ближайший эквивалент:
<input type="range" name="s" min="1" max="10">
Однако эти два примера уже показывают большую разницу в поведении. Вызов макроса @bind в блокноте Pluto непосредственно устанавливает значение x при манипуляции ползунком пользователем, и все ячейки блокнота, которые зависят от значения этой переменной, немедленно выполняются (а также все последующие ячейки в цепочке зависимостей). Всё, что вам нужно сделать, это написать программы, использующие x, и разместить макрос @bind для ползунка там, где это имеет смысл в вашей презентации.
В случае с HTML тег <input> просто отображает ползунок на странице. Чтобы что-то произошло при перемещении ползунка пользователем, нужно сделать немного больше. Пример 2 показывает фрагмент HTML-страницы для минимального ползунка, который добавляет три атрибута к тегу input для ползунка (тег здесь разбит на три строки).
- <label> Pick a number
- <input data-hx-ext="ws" data-ws-send
- data-ws-connect="wss://<your/server/url>/"
- type="range" name="s" min="1" max="10">
- </label>
- <p id='sr'></p>
Все эти атрибуты вызывают функции из расширения HTMX WebSocket (см. раздел «Валидация и префикс данных»). Новые атрибуты в списке 2 указывают соответственно, что элемент (ползунок) использует расширение, что он отправляет данные через веб-сокет и что данные будут отправлены по указанному адресу. Протокол WSS предназначен для зашифрованного общения по WebSocket (аналогично HTTPS), который следует всегда использовать при работе через публичный Интернет. Для тестирования на локальной машине вы можете заменить адрес на ws://127.0.0.1:PORT
Проверка и префикс данных: Префикс данных в трёх новых атрибутах в теге <label> в Примере 2 является необязательным, в том смысле, что его отсутствие не повлияет на работу клиента. Он предназначен для того, чтобы страница была корректным HTML; настраиваемые атрибуты, такие как hx-ext, не входят в состав HTML, поэтому валидаторы будут выдавать предупреждения; однако они игнорируют любой атрибут, начинающийся с data-. Поддержка префикса data- является особенностью HTMX. Обратите внимание, что страницы PlutoSliderServer не проходят валидацию, и их исходный код не может быть полезно проанализирован любопытным пользователем, что является недостатком. Страницы, созданные с помощью HTMX, могут быть корректным HTML, и их код разборчив при просмотре через «Посмотреть исходный код».
и используйте номер порта, который вы настроили, вместо PORT. Наконец, элемент заключен в тэг
Каждый раз, когда пользователь изменяет положение ползунка, значение, связанное с name s, упаковывается в сообщение и передается через открытый WebSocket на Julia, работающую на сервере. Клиент отправляет сообщение после того, как пользователь прекращает взаимодействие с элементом управления (например, отводя мышь), поэтому вам не нужно беспокоиться о массивной цепочке сообщений, отправляемых во время движения ползунка.
В перечне 3 показана минимальная рабочая программа на Julia, которая определяет сервер, способный реагировать на слайдер из предыдущего примера. Для начала создайте окружение для вашего проекта Julia в режиме пакетов REPL, как и ранее, и добавьте пакеты HTTP и JSON.
- using HTTP, JSON
- const PORT = 8660
-
- function startserver()
- WebSockets.listen("127.0.0.1", PORT) do ws
- for msg in ws
- d = Meta.parse(JSON.parse(msg)["s"])
- WebSockets.send(ws, """<p data-hx-swap-oob='true' id='sr'> You picked $d </p>""")
- end
- end
- end
Пакет JSON существует для одной функции: JSON.parse(), которая извлекает переменные из сообщений, отправленных клиентом. Информация, возвращаемая сервером, всегда представлена в виде HTML-фрагментов, а не JSON: это философия, лежащая в основе HTMX.
Переменные, извлекаемые из сообщений браузера, всегда являются строками. В этом примере строка передается в Meta.parse(), часть Julia Base, которая преобразует строки в выражения Julia; в данном случае она используется для преобразования строки в Int.
Пакет HTTP предоставляет две функции связи, вокруг которых вы будете строить свои приложения. WebSockets.listen() принимает второй аргумент, указывающий IP-адрес для прослушивания, и третий аргумент — для порта прослушивания. Эта функция открывает WebSocket-подключение по указанному адресу и порту. Адрес, показанный в списке, относится к локальной машине, либо к вашему компьютеру для разработки, либо к контейнеру сервера, на который вы в конечном итоге развернете приложение.
Вы заметите, что при запуске этого или подобного кода REPL блокируется с сообщением о том, что Julia слушает WebSocket. Если вы хотите продолжить работу в REPL, пока эта программа работает, возможно, чтобы запустить другие серверы, пакет HTTP предоставляет другую, неблокирующую версию функции. Она та же самая, но с восклицательным знаком; вызов становится следующим:
WebSockets.listen!("127.0.0.1", PORT)
В программе, которую вы запускаете на сервере с помощью команды systemd-run, вы можете запустить любое количество прослушивающих WebSocket-серверов с использованием неблокирующей версии вызова, но последний должен использовать блокирующую версию, чтобы программа оставалась активной и продолжала прослушивать подключения.
Первым аргументом функции WebSockets.listen() является функция-обработчик, которая принимает один аргумент Websocket; здесь она предоставляется как анонимная функция, созданная с помощью ключевого слова do в Julia. Эта функция отвечает за обработку входящих сообщений, поэтому в нее следует включить команду, которая отправляет результат обратно клиенту — это осуществляется с помощью вызова WebSockets.send(). Цикл for поддерживает соединение открытым до тех пор, пока пользователь его не закроет, что обычно происходит при закрытии веб-страницы. Листинг 3 показывает типичный шаблон использования пакета HTTP для связи через WebSockets и является тем шаблоном, который я использую в более сложных примерах, приведенных в разделе HTMX Examples в Таблице 1.
Более подробно функция startserver() в Листинге 3:
- Начинает прослушивать сообщения WebSocket на локальной машине через PORT
- Парсит каждое полученное сообщение, извлекает значение, связанное с именем s, и присваивает его переменной d
- Сразу же отправляет сообщение обратно клиенту, состоящее из HTML-фрагмента с вставленным значением, присвоенным d
Пример, возвращаемый фрагментом HTML, содержит элемент абзаца с двумя атрибутами. Первый, hx-swap-oob (с необязательным префиксом data, чтобы поддерживать соответствие стандартам HTML), указывает HTMX, что фрагмент должен быть вставлен вне основного потока и заменить существующий элемент с id=’sr’. В контексте HTMX термин «вне основного потока» означает, что элемент, который нужно заменить, не тот же самый, что и элемент, отправивший сообщение: сам слайдер заменяться не должен, заменяется другой элемент — в данном случае абзац.
Обращаясь к Листингу 2, обратите внимание на существующий пустой абзац с id=‘sr’. Он служит в качестве заполнителя и готов к замене после того, как пользователь переместит ползунок. На изображении ниже показано, как этот минимальный пример выглядит в браузере после того, как пользователь установил ползунок в положение, соответствующее числу 6. Пустой абзац был заменен на тот, который представлен в Листинге 3, и содержит текст You picked 6.
Примеры 2 и 3 иллюстрируют принципы использования библиотеки JavaScript HTMX и пакета Julia HTTP вместе для создания интерактивной страницы с вычислениями на Julia на сервере. Используя этот метод с небольшими знаниями HTML и JavaScript, вы можете создавать любые приложения, которые только можете себе вообразить. Часто в таких приложениях потребуется вставлять на страницу не только текст: возможно, изображения, видео или звук. Очевидный способ сделать это — сохранить медиафайл, который генерирует ваша программа на Julia, на сервере и отправить на страницу элемент, который загружает этот файл. Это обычно тот способ, которым, например, работает тег изображения, ссылаясь на URL изображения для загрузки через его атрибут src.
У этого разумного подхода есть как минимум два незначительных недостатка: он требует отправки дополнительного запроса клиентом, что увеличивает задержку взаимодействия, и засоряет ваш сервер медиафайлами, которые нужно будет удалить. Если удалять их слишком рано, страницы ваших пользователей могут пытаться загрузить ресурсы, которых уже нет, а если оставлять их слишком долго, они будут занимать место на вашем сервере.
Элегантным решением этих проблем является использование недостаточно часто применяемой функции, встроенной в HTML: URL data. С помощью этой функции можно отправлять любые виды мультимедиа, поддерживаемые веб-браузером (например, изображения, звуки и т.д.), напрямую в потоке данных в составе ответа сервера, вместо того чтобы отправлять URL файла, который браузеру потом придется запросить. Не требуется создание или хранение файлов. Мультимедиа становится частью страницы, так же как и её текстовое содержимое, а не отдельным ресурсом.
Чтобы использовать эту функцию в ваших веб-приложениях, вам потребуется способ кодирования бинарных мультимедийных данных в текст. Среди множества способов сделать это стандартом в браузерах является кодирование Base64, которое в Julia предоставляется пакетом IBase64.
Листинг 4 показывает серверную программу из Листинга 3 с несколькими добавленными строками, которые создают график на основе введенных пользователем данных на слайдере, кодируют его и отправляют клиенту для вставки на страницу. Программа импортирует пакеты Plots и Base64 для создания и кодирования графики. В начале функции startserver() объект буфера ввода-вывода присваивается переменной io. Этот объект буфера вам понадобится для преобразования бинарного потока в текстовый блок.
- using HTTP, JSON, Plots, Base64
- const PORT = 8660
-
- function startserver()
- io = IOBuffer();
- x = 0.0:2PI/1000:2PI
- WebSockets.listen("127.0.0.1", PORT) do ws
- for msg in ws
- d = Meta.parse(JSON.parse(msg)["s"])
- @info d
- @info typeof(d)
- WebSockets.send(ws, """<p hx-swap-oob='true' id='sr'>You picked $d</p>""")
- p = plot(x, sin.(d .* x); label="sin($(d)x)")
- show(io, MIME"image/png"(), p)
- data = base64encode(take!(io))
- WebSockets.send(ws, """<img data-hx-swap-oob='true' id='plot' src='data:image/png;base64,$data' alt='sin(1/x)'>""")
- end
- end
- end
Внутри цикла for вы можете увидеть четыре новые строки. Сначала программа создаёт простой график функции sin(), используя значение, выбранное пользователем, и присваивает этот график переменной p. Следующие две строки считывают данные графика в io как изображение PNG, преобразуют его в текст (кодированный в Base64) и сохраняют в переменной data.
Последняя строка в цикле for содержит дополнительный вызов send(), который отправляет график клиенту, заменяя существующий элемент изображения (идентифицируемый по его id) на элемент изображения, в котором график встроен в атрибут src. Как видно из примера, необходимо указать браузеру MIME-тип данных и сообщить, что они закодированы с использованием base64.
Список 4 также показывает, что вы не ограничены отправкой одного ответа на каждое полученное сообщение, а можете отправлять любое их количество, нацеливая их на любой набор элементов на странице.
Клиентский код для этого примера будет таким же, как в Списке 2, с добавлением строки
<img alt='' src='' id='plot'>
создать элемент-заполнитель для графика.
На изображении ниже показан скриншот браузера после того, как пользователь переместил ползунок, чтобы выбрать число 8. Если вы реализуете клиент и сервер из листингов 3 и 4 и поиграете с ползунком в своем браузере, вы увидите, что график обновляется быстро, обеспечивая хороший интерактивный опыт, особенно если сервер работает на той же машине, что и ваш браузер. Естественно, если сервер и клиент взаимодействуют через Интернет, качество опыта будет зависеть от скорости сети, и отклик не всегда будет плавным и интерактивным, что является неизбежным недостатком всех приложений, которые зависят от вычислений, выполняемых на удаленном сервере. Основной способ минимизировать такие проблемы — избегать отправки больших объемов данных в ответ на действия пользователя. Если, например, вы отправляете изображение, воспользуйтесь сжатыми форматами файлов (например, JPEG) и ограничьте разрешение, чтобы максимально уменьшить количество данных.
Другим источником задержек во взаимодействии является время, необходимое для выполнения вычислений на сервере. В этом случае скорость Julia помогает и является одной из причин, по которой этот язык является хорошим выбором для подобных приложений: для типичных вычислений, поддерживающих виды педагогических целей, которые иллюстрируют мои примеры, время вычислений составляет доли секунды, и время вычислений не является основным фактором, ограничивающим опыт взаимодействия.
Вы можете реализовать пример из этого раздела с помощью метода PlutoSliderServer; выбор того или иного метода зависит от ваших планов на дальнейшую разработку, того, нравится ли вам работать с блокнотами Pluto, и имеет ли для вас значение наличие HTML-страницы, которая проходит валидацию. Для примера приложения, использующего методы, описанные в этом разделе, но которое было бы неудобно создавать с помощью PlutoSliderServer, см. пример динамики вихрей в Таблице 1. Вы можете изучить исходный код клиента обычным способом, и на странице объясняется, как получить исходный код серверного компонента.
Последний пример
Еще один пример, немного развивая предыдущий, послужит демонстрацией нескольких дополнительных элементов управления и покажет, как использовать стили для оформления страницы. Кроме того, этот пример на самом деле делает что-то почти полезное.
Математическая задача нахождения точек пересечения тригонометрических функций, как правило, имеет только численные решения. На изображении ниже показан скриншот браузера с приложением, которое позволяет пользователю выбрать два параметра: один для амплитуды функции тангенса и другой для частоты функции косинуса. Пользователь также может выбрать два цвета с помощью двух инструментов выбора цвета. При нажатии кнопки Найти пересечения на странице появляются два новых элемента: график двух функций в выбранных цветах и таблица, содержащая все их точки пересечения в диапазоне (0, 1).
Список 5 содержит полный HTML-код страницы клиента, за исключением заголовка и другой административной разметки HTML, а список 6 содержит полный серверный программный код.
- <form data-hx-ext="ws" data-ws-send data-ws-connect="ws://127.0.0.1:8660">
- <h2>Calculate intersections of <code><input style='width:3em;' type="number" name="t" min="0.1" max="1" value='1' step='0.1'>tan(x)</code> and <code>cos(<input style='width:2.5em;' type="number" name="c" min="1" max="40" value='4'>x)</code><br> between 0 and 1</h2>
- Choose colors for the two curves:
- <input type='color' name='c1' value='#990000'>
- <input type='color' name='c2' value='#000099'><br>
- <input type='submit' style='font-size:2em; margin-top:1em;' value='Find intersections'><br>
- <img alt='' src='' id='plot'>
- <table id='ztable'></table>
- </form>
- using HTTP, JSON, Base64, Roots
- const PORT = 8660
-
- function startserver()
- io = IOBuffer();
- x = 0.0:0.001:1.0
- WebSockets.listen("127.0.0.1", PORT) do ws
- for msg in ws
- lc1 = JSON.parse(msg)["c1"]
- lc2 = JSON.parse(msg)["c2"]
- c = Meta.parse(JSON.parse(msg)["c"])
- t = Meta.parse(JSON.parse(msg)["t"])
- f1(x) = cos(c * x)
- f2(x) = t * tan(x)
- f(x) = f1(x) - f2(x)
- z = round.(find_zeros(f, (0, 1)), digits=3)
- y = round.(f1.(z), digits=3)
- ztable = []
- for zero in zip(z, y)
- append!(ztable, "<tr><td>$(zero[1])</td><td>$(zero[2])</td></tr>")
- end
- ztable = join(ztable)
- p = plot([f1 f2]; xrange=(0, 1), lc=[lc1 lc2], lw=2, xlabel="x", ylabel="y", label=["cos($c x)" "$(t)tan(x)"])
- show(io, MIME"image/png"(), p)
- data = base64encode(take!(io))
- WebSockets.send(ws, """<img data-hx-swap-oob='true' id='plot' src='data:image/png;base64,$data' alt='sin(1/x)'>""")
- WebSockets.send(ws, """<table data-hx-swap-oob='true' id='ztable' style='width:13em; float:right;'> <caption> $(length(z)) intersections found </caption> <tr><th>x</th><th>y</th></tr> $ztable </table>""")
- end
- end
- end
К этому моменту функция большинства элементов в этих программах должна быть ясна. Код сервера не содержит ничего принципиально нового: лишь несколько дополнительных переменных и использование пакета Roots для вычисления пересечений функций. Обратите внимание на включение атрибутов стиля в возвращаемые фрагменты HTML и на использование переменных в подписях к графикам и заголовке таблицы. Первые две строки внешнего цикла for извлекают две переменные, установленные селекторами цвета, оставляя их в виде строк для прямого использования в вызове plot().
Пример 5 иллюстрирует использование форм с HTMX. Вместо того чтобы размещать атрибуты связи HTMX в элементе ввода, как вы видели в Примере 2, вы можете разместить их в открывающем теге form. Когда пользователь нажимает кнопку отправки формы, все переменные, определенные элементами ввода внутри формы, отправляются через WebSocket в одном сообщении.
Часто задаваемые вопросы
1. Хороша ли Джулия для веб-разработки?
Да, Julia отлично подходит для веб-разработки, особенно для приложений, которые требуют:
- Высокопроизводительные вычислительные бэкенды
- Научные вычисления и анализ данных
- Математические визуализации в реальном времени
- Образовательные и исследовательские приложения
Пример кода — Простой веб-сервер на Julia:
using HTTP function handle_request(req::HTTP.Request) return HTTP.Response(200, "Hello from Julia Web Server!") end HTTP.serve(handle_request, "127.0.0.1", 8080)
Преимущества:
- Быстрое выполнение благодаря JIT-компиляции
- Отличные библиотеки для научных вычислений
- Простая параллелизация для повышения производительности
- Чистый, читаемый синтаксис
- Сильная система типов
2. Как мне выбрать между PlutoSliderServer и HTMX для веб-приложений на Julia?
Выберите PlutoSliderServer, когда:
- Вы хотите преобразовать существующие блокноты Pluto в веб-приложения
- Вам необходима быстрая прототипизация с минимальным количеством фронтенд-кода
- Ваше приложение хорошо подходит для взаимодействия в стиле блокнота
- Вы предпочитаете готовые виджеты вместо индивидуального HTML
Выбирайте HTMX + WebSockets, когда:
- Вам нужен полный контроль над дизайном фронтенда
- Вы хотите создавать пользовательские интерфейсы
- Вам нужны сложные взаимодействия, выходящие за рамки базовых виджетов
- Вы хотите корректный HTML, который проходит проверку
Пример кода — Настройка PlutoSliderServer:
using PlutoSliderServer # Start server monitoring a directory run_directory( "/path/to/notebooks/"; Export_offer_binder=false )
Пример кода — Сервер HTMX WebSocket:
using HTTP, JSON WebSockets.listen("127.0.0.1", 8660) do ws for msg in ws data = JSON.parse(msg) response = "<p>Received: $(data["value"])</p>" WebSockets.send(ws, response) end end
3. Как мне работать с WebSockets в веб-приложениях на Julia?
Julia обеспечивает отличную поддержку WebSocket через пакет HTTP.jl. Вот как реализовать обмен данными по WebSocket:
Сторона сервера WebSocket:
using HTTP, JSON, Base64 function start_websocket_server() WebSockets.listen("127.0.0.1", 8660) do ws for msg in ws # Parse incoming message data = JSON.parse(msg) # Process the data (example: create a plot) x = 0:0.1:2π y = sin.(x .* parse(Float64, data["frequency"])) # Create plot and encode as Base64 io = IOBuffer() p = plot(x, y, label="sin($(data["frequency"])x)") show(io, MIME"image/png"(), p) plot_data = base64encode(take!(io)) # Send response back to client response = """ <img src='data:image/png;base64,$plot_data' style='max-width: 100%; height: auto;'> """ WebSockets.send(ws, response) end end end
HTML на стороне клиента с HTMX:
<script src="/htmx.js"></script> <script src="/ws.js"></script> <input type="range" data-hx-ext="ws" data-ws-send data-ws-connect="ws://127.0.0.1:8660" name="frequency" min="1" max="10" value="1"> <div id="plot-container"></div>
4. Каковы лучшие практики развертывания веб-приложений на Julia?
Лучшие практики безопасности:
# Use containers for isolation sudo systemd-nspawn -D /path/to/container # Set up reverse proxy with Apache ProxyPass "/app/" "http://127.0.0.1:8660/" nocanon ProxyPassReverse "/app/" "http://127.0.0.1:8660/" nocanon
Контейнеризация крайне важна для веб-приложений на Julia, так как они выполняют произвольный код на вашем сервере. systemd-nspawn создаёт изолированную среду, которая предотвращает доступ вредоносного кода к вашей хост-системе. Конфигурация обратного прокси обеспечивает прохождение внешнего трафика через функции безопасности Apache (завершение SSL, ограничение скорости и др.) перед тем, как он достигнет вашего приложения на Julia.
Пример сценария развертывания:
#!/bin/bash # Start Julia web server with systemd systemd-run --unit=julia-webapp --setenv=JULIA_PROJECT=/path/to/project julia --project=/path/to/project -e "using MyWebApp; start_server()"
Использование systemd-run гарантирует, что ваш веб-сервер на Julia работает как полноценная системная служба с возможностью автоматического перезапуска, ведением журналов и управлением процессами. Флаг --setenv=JULIA_PROJECT обеспечивает использование Julia правильной пакетной среды, предотвращая конфликты зависимостей.
Оптимизация производительности:
# Use non-blocking WebSocket listeners for multiple services WebSockets.listen!("127.0.0.1", 8660) do ws # Handle first service end WebSockets.listen!("127.0.0.1", 8661) do ws # Handle second service end # Final blocking listener to keep process alive WebSockets.listen("127.0.0.1", 8662) do ws # Handle main service end
Неблокирующая функция listen! позволяет одновременно запускать несколько WebSocket-сервисов, не блокируя основной поток. Это важно для архитектуры микросервисов, где разные процессы Julia обрабатывают различные аспекты вашего веб-приложения. Финальный блокирующий вызов listen поддерживает основной процесс в рабочем состоянии.
Ключевые моменты:
- Безопасность: Всегда используйте контейнеры или виртуальные окружения для работы в продакшене
- Масштабируемость: Рассмотрите возможность балансировки нагрузки для приложений с высоким трафиком
- Мониторинг: Внедрите ведение журналов и проверку состояния для рабочих развертываний
- SSL/TLS: Всегда используйте HTTPS в производственной среде с правильным управлением сертификатами
- Ограничения ресурсов: Установите лимиты памяти и ЦП, чтобы избежать исчерпания ресурсов
5. Как интегрировать возможности научных вычислений Julia с веб-приложениями?
Юлия отлично совмещает научные вычисления с веб-разработкой. Вот как можно это использовать:
Пример математической визуализации:
using Plots, Base64, HTTP, JSON function create_interactive_plot(params) # Complex mathematical computation x = range(0, 4π, length=1000) y = sin.(params.frequency .* x .+ params.phase) .* exp.(-params.damping .* x) # Create publication-quality plot p = plot(x, y, title="Damped Oscillation: f=$(params.frequency), φ=$(params.phase)", xlabel="Time", ylabel="Amplitude", linewidth=2, color=:blue) # Convert to web-compatible format io = IOBuffer() show(io, MIME"image/png"(), p) base64encode(take!(io)) end # WebSocket handler for real-time updates WebSockets.listen("127.0.0.1", 8660) do ws for msg in ws params = JSON.parse(msg) plot_data = create_interactive_plot(params) html_response = """ <img src='data:image/png;base64,$plot_data' style='max-width: 100%; border: 1px solid #ccc;'> """ WebSockets.send(ws, html_response) end end
Основные преимущества:
- Прямой доступ к научным библиотекам (Plots.jl, DifferentialEquations.jl и др.)
- Высокопроизводительные математические вычисления
- Легкая интеграция исследовательского кода в веб-интерфейсы
- Поддержка сложных типов данных и математической нотации
Иди вперёд и программируй
Добродетели, которые сделали Джулию столь успешной в области научных вычислений и инженерии — простота разработки в сочетании с безкомпромиссной производительностью — также делают её хорошим выбором для серверной части веб-приложений. В этой статье вы узнали о двух подходах к созданию интерактивных веб-сайтов для образования, получения информации и развлечений. Вы можете решить принять один из них, оба или ни один из них (или, как я, применять оба подхода к разным проектам). Я обнаружил, что работа с Джулией в сочетании с веб-технологиями была одним из самых приятных и полезных приключений в программировании для меня. Я надеюсь, что вы получите столько же удовольствия, сколько и я, создавая проекты, которые трудно себе представить. Пожалуйста, делитесь новостями о своих творениях, отправляя мне письмо по электронной почте или оставляя комментарии на моём сайте.
Этот материал основан на статье от ADMIN и доступен вам благодаря сотрудничеству с Linux-Console.net.
Спасибо за обучение вместе с сообществом Linux-Console.net.








Добавить комментарий