Ваша первая программа и веб-приложение на WebAssembly (написано, протестировано и развернуто полностью в веб-браузере).
Компиляция и запуск кода на языке C с помощью Emscripten и GitHub Codespaces — локальная установка не требуется.
Делиться

Добро пожаловать в мою первую из короткой серии статей/уроков, посвященных созданию веб-приложений на основе WebAssembly, работающих полностью в веб-браузере, с возможностью изучения следующих тем: GitHub, его Codespaces, WebAssembly (или «WASM»), код на C, онлайн-версия Visual Studio Code, переадресация портов, HTML и JavaScript. Надеюсь, вам будет так же интересно, как и мне, во время подготовки этой статьи, и вы многому научитесь и ваше любопытство пробудится!
Говорят, чем больше узнаешь, тем больше кажется, что ничего не знаешь и что еще многому предстоит научиться. Именно такое чувство я испытывал и здесь, и это чувство на самом деле приятно.
Пойдем!
Будучи давним и убежденным сторонником клиентских веб-приложений, я всегда считал странным, что практически ничего не знал о WebAssembly. Но недавно мое мнение начало меняться, когда я нашел мотивацию, пытаясь создать свою новую веб-платформу для анализа молекулярных структур и моделирования в браузере (препринт первой версии можно найти здесь, если хотите узнать больше). Оказалось, что существуют высокоэффективные библиотеки и научные приложения, написанные на таких языках, как C, которые оказались полезными для моей платформы, например, Gemmi и FreeSASA. Для обоих уже кто-то проделал работу по созданию WASM-портов, которые я мог использовать сразу же.
Но мог ли я сделать это сам? То есть, мог ли я взять, скажем, фрагмент кода на C и скомпилировать его таким образом, чтобы он работал в браузере? Ответ был ДА! И более того, оставаясь верным своим принципам веб-разработки, я мог сделать все это исключительно в браузере, как я показываю здесь на примере FreeSASA.
Следующим этапом моего обучения стал самоурок, начавшийся ещё до освоения кода на C. Здесь я представляю его с подробными объяснениями того, как создать файлы, готовые к использованию WASM, прямо в браузере, бесплатно, без необходимости скачивать или устанавливать какое-либо программное обеспечение, и всего лишь с бесплатным аккаунтом GitHub.
Что такое WebAssembly и почему это важно — в двух словах.
Долгое время веб-браузер был в основном слоем представления: отлично подходил для интерфейсов и легковесного взаимодействия, но не для серьезных вычислений. Для ресурсоемких задач обычно требовались нативные приложения, среды Python или удаленные серверы. WebAssembly (WASM) меняет это. Он позволяет компилируемым языкам, таким как C, C++ и Rust, работать непосредственно в браузере со скоростью, близкой к нативной , превращая браузер в настоящую вычислительную платформу, а не просто в поверхность отображения.
На практике WebAssembly позволяет разработчикам компилировать существующий высокопроизводительный код в компактный бинарный формат, который браузеры могут эффективно выполнять. Вместо переписывания критически важной для производительности логики на JavaScript, разработчики могут повторно использовать оптимизированный системный код, накопленный за десятилетия, при этом распространяя приложения в виде простых веб-страниц. В результате получается программное обеспечение, которое работает быстрее, портативнее и значительно проще в распространении: пользователи могут открыть ссылку и запустить сложные приложения локально без установки, конфликтов зависимостей или настройки, специфичной для платформы .
Этот сдвиг имеет значение далеко за пределами одной лишь производительности. WebAssembly устраняет разрыв между доступностью веб-технологий и мощью нативного программного обеспечения, позволяя создавать адаптивные браузерные инструменты для моделирования, анализа данных, обработки мультимедиа, научных вычислений и интерактивной визуализации. JavaScript продолжает обрабатывать интерфейс и взаимодействие с пользователем, в то время как WASM выступает в качестве вычислительного движка, работающего за кулисами. Это разделение меняет возможности современных веб-приложений, и даже если вы этого не замечаете, это стало обычным явлением в современной веб-разработке.
Кросс-компиляция в WASM
На практике наличие WebAssembly позволяет нам:
- компилировать нативный код в переносимый бинарный формат.
- загрузить его непосредственно на веб-страницу.
- и выполнять его практически с нативной скоростью прямо в браузере.
Для специалистов по анализу данных и разработчиков научного программного обеспечения это открывает захватывающие возможности: теперь научное ПО может работать непосредственно в браузере, не требуя от пользователей установки каких-либо программ. Не нужно каждый раз устанавливать и загружать среды, управлять библиотеками, нет конфликтов зависимостей, нет ограничений операционной системы.
Всего лишь веб-страница, предоставляющая доступ к вашим инструментам по одному URL-адресу!
Подробное практическое руководство, которое можно запустить прямо в браузере.
В этом уроке мы создадим максимально компактное приложение WebAssembly, которое будет выводить на веб-страницу сообщение «Hello WASM!» и будет основано на коде на языке C:
#include int main() { printf("Hello WASM!n"); return 0; }
Мы скомпилируем этот фрагмент кода на языке C в WebAssembly, сгенерируем файлы среды выполнения браузера и запустим его непосредственно в браузере.
Самое главное: всё будет происходить онлайн, даже написание самого кода на языке C. Как только мы войдем в GitHub , мы не выйдем из браузера, пока всё не заработает!
Для разработки приложений на основе браузера мы будем использовать GitHub Codespaces .
Для компиляции C в WebAssembly используется Emscripten (запускается прямо из GitHub Codespaces), а для запуска сгенерированного веб-приложения — простой HTTP-сервер на Python (также запускаемый из GitHub Codespaces).
Кстати: что такое GitHub Codespaces? Это мгновенная облачная среда разработки, использующая контейнеры для предоставления вам распространенных языков программирования, инструментов и утилит для разработки. GitHub Codespaces также можно настраивать, что позволяет создать индивидуальную среду разработки для вашего проекта.
Настрой нашего мышления на рабочий процесс
В концептуальном плане наш рабочий процесс выглядит следующим образом:
C code --> Emscripten compiler--> WebAssembly module --> Browser execution
А затем мы рассмотрим все этапы так, как если бы следовали инструкциям из книги серии «Для чайников».
Шаг 1 — Создайте репозиторий GitHub
(Кстати, что такое GitHub? GitHub — это веб-платформа, своего рода социальная сеть для программистов, которая служит облачной площадкой для совместной работы над программными проектами. Она появилась на основе Git, программного обеспечения для контроля версий, позволяющего разработчикам хранить, отслеживать изменения и совместно работать над кодом в режиме реального времени.)
Сначала войдите в GitHub и создайте новый репозиторий. Например, в моей бесплатной учетной записи по состоянию на май 2026 года он выглядит так (см. красную стрелку в левом верхнем углу):

(Все изображения предоставлены автором)
Затем мы присваиваем ему имя и нажимаем «Создать репозиторий», оставляя все остальные поля без изменений по умолчанию:

На данном этапе созданный репозиторий может изначально выглядеть пустым. Для его инициализации необходимо создать файл, например, простой файл README:

Затем, после заполнения минимально необходимой информации, следующий экран выглядел так:

Затем вы активируете подтверждение изменений с помощью кнопки «Подтвердить изменения…» в правом верхнем углу, а затем, наконец, нажимаете «Подтвердить изменения» в появившемся окне.
Шаг 2 — Запустите GitHub Codespaces
Теперь мы готовы перейти на Codespaces, где начнём писать код!
(Кстати, GitHub Codespaces — это «мгновенная» веб-среда разработки, которая позволяет писать, запускать и отлаживать код полностью в браузере с помощью онлайн-версии Visual Studio Code.)
Кнопку для запуска Codespaces вы найдете, нажав кнопку <> Code на странице, которую вы попали туда после сохранения изменений, указанных выше:

После нажатия кнопки «Создать пространство кода в главном окне» через несколько секунд откроется онлайн-приложение Visual Studio Code, которое будет выглядеть примерно так:

Вы увидите, что приложение создает среду с уникальным именем. В моем случае это «vigilant-space-rotary-phone», но у вас будет другое имя. Если вы проверите текущий URL, вы увидите, что имя вашей среды также отображается там. Например, у меня это «https://vigilant-space-rotary-phone-someunreadblestuff.github.dev/».
Шаг 3 — Создайте программу на языке C.
В окне Проводника (слева) вы увидите, как по мере разработки приложения в списке появляется все больше и больше файлов. На данный момент у нас есть только один файл — README, который мы создали ранее.
Теперь нажмите «Создать файл» (см. красную стрелку ниже) и назовите его, добавив расширение .c. В этом файле будет храниться код нашего приложения:

После создания файла справа вводится код, например:
#include int main() { printf("Hello WASM tutorial!n"); return 0; }
Сочетание клавиш Ctrl+S (Cmd+S на Mac) позволяет сохранить файл, который теперь готов к компиляции.
Шаг 4: Обеспечение доступности Emscripten в рамках этой онлайн-сессии Visual Studio Code.
Но для компиляции кода на C в WebAssembly нам нужен Emscripten, которого пока нет в среде разработки. Emscripten — один из основных инструментов в экосистеме WebAssembly. Он компилирует код на C и C++ в файл .wasm, сопровождаемый совместимыми с браузером файлами среды выполнения, которые обеспечат интерфейс между HTML+JS-кодом приложения и самим файлом WASM.
Для «установки» Emscripten (я использую кавычки, потому что на ваш компьютер ничего на самом деле не устанавливается, так как всё происходит где-то в облаке!) вам нужно ввести несколько команд в терминале, как показано здесь для первой из них:

Первая команда, которую вы видите на картинке выше, просто копирует (или «клонирует») текущую версию Emscript из его репозитория на GitHub:
git clone https://github.com/emscripten-core/emsdk.git
В результате получится следующее:

Затем перейдите в папку emsd, которая содержит файлы, загруженные нами с GitHub, и выполните команду для их установки:

Выполнение этой процедуры займет некоторое время, и если все пройдет успешно (а так и должно быть), то в конце вы увидите следующее:

Далее мы активируем Emscripten:
./emsdk activate latest
И наконец, загрузите переменные среды:
source ./emsdk_env.sh
Для проверки установки введите следующее:
emcc --version
Теперь вы должны увидеть информацию о версии компилятора Emscripten.
Шаг 5 — Скомпилируйте программу в WebAssembly!
Оставаясь в терминале, мы поднимаемся на один уровень вверх по структуре папок, чтобы выйти из emsdk, где мы установили Emscripten, а затем запускаем команду компиляции emcc file.c -o file.html :

В левом верхнем углу проводника вы увидите несколько новых файлов:

На данный момент у нас есть только файл README и код на языке C, которые мы уже создали, а также файлы .wasm, HTML и JS, созданные с помощью Emscripten. Всё очень просто, видите!
Что же это за файлы и для чего они нужны?
- hello-wasm-tutorial.wasm — это скомпилированный исполняемый файл WebAssembly, то есть основная исполняемая логика, взятая из программы на языке C.
- Файл hello-wasm-tutorial.js — это связующий код JavaScript, который позволяет взаимодействовать с файлом WASM и остальной частью кода JavaScript, а следовательно, и с самим веб-приложением. Этот файл загружает модуль WASM, инициализирует память во время выполнения и управляет обменом данными между браузером и модулем WebAssembly.
- hello-wasm-tutoiral.html — это минималистичный шаблон веб-страницы, автоматически сгенерированный Emscripten. Открытие этой страницы запускает скомпилированное приложение.
Теперь перейдём к их тестированию!
Шаг 6: Тестирование (и дождитесь шага 7, чтобы переместить файлы на свой сервер!)
Чтобы протестировать наше wasm-приложение внутри веб-страницы, созданной самим Emscripten, нам нужно запустить «локальный» веб-сервер, где «локальный» снова заключен в кавычки, потому что на самом деле мы будем делать это в облаке (но «локальным» будет среда Codespaces, отсюда и название!).
Нам это необходимо, потому что приложение предназначено для работы через веб-сервер. К счастью, Python (который уже используется в облачной среде) предоставляет небольшой встроенный HTTP-сервер. Мы можем активировать этот сервер, выполнив следующую команду в терминале:
python3 -m http.server 8000
Вот результат выполнения этой команды, включая кнопку, которая запустит веб-приложение в новом окне:

При нажатии на эту кнопку вы увидите список файлов в каталоге, включающий все файлы, которые у нас уже есть:

И наконец, волшебство: когда вы нажимаете на hello-wasm-tutorial.html, вы видите, как загружается эта страница, которая, в свою очередь, вызывает программу wasm и затем отображает ее вывод (а для полноты картины я также показываю консоль браузера):

Понимание достигается упрощением HTML-кода (и помните, что есть шаг 7, чтобы переместить файлы с вашего сервера на ваш собственный!).
Как вы видите в приведенном выше примере (и на своем компьютере, если вы следовали инструкциям!), при компиляции нашего кода Emscripten сгенерировал громоздкую HTML-страницу с CSS, весь пользовательский интерфейс, включая сообщения о загрузке и другие сообщения о состоянии, кнопки и т. д. Это может быть хорошо для демонстраций, но на самом деле усложняет обучение.
Итак, прежде всего, нам нужно получить минимальный HTML-код, который запустит код wasm. И оказывается, для этого требуется совсем немного!
Просто создайте новый HTML-файл в проводнике:
Hello WASM tutorial, the simplest! Hello WASM tutorial, minimalist
Сохраните файл и вернитесь на страницу списка каталогов на сервере Python mini, нажмите «Обновить», чтобы увидеть новый файл, и откройте его. Теперь он будет выглядеть примерно так, где строковый вывод программы WASM отображается в консоли, потому что именно это мы вызываем в коде JavaScript:

Теперь вы можете изучить различные файлы (по сути, это простой HTML-код плюс JS-файл, созданный Emscripten, а код на C вы написали сами, поэтому вы уже знаете, что он делает!), чтобы понять это немного лучше.
Получение контроля над тем, что и когда выполняется, путем вызова функций программы на языке C из интерфейса HTML+JS (и следующий шаг — 7!).
Итак, давайте посмотрим, как создать веб-приложение с кнопкой, которая будет вызывать функцию из программы WASM, скомпилированной Emscripten из кода на языке C, и применять её результат непосредственно к HTML-документу.
Главное здесь — создать отдельные функции на языке C, не связанные с функцией main(), экспортировать их и перекомпилировать программу, чтобы получить новый файл WASM вместе с новым файлом JS, который будет взаимодействовать с HTML для обработки вызовов функций.
Предположим, мы изменим код на языке C следующим образом, сохранив предыдущую функцию main() и добавив функцию, которую будем вызывать с кнопки в HTML-коде:
#include void button_message() { printf("Hello from a function called specifically from the web page!n"); } int main() { printf("Hello WASM tutorial (main function!)!n"); return 0; }
Обратите внимание, что в основной функции мы изменили вывод функции printf(); это необходимо для того, чтобы точно знать, откуда берется текст.
Теперь выполним компиляцию с помощью следующей команды:
emcc hello-wasm-tutorial.c -o hello-wasm-tutorial.js -sEXPORTED_FUNCTIONS=_main,_button_message -sEXPORTED_RUNTIME_METHODS=ccall
Обратите внимание на три момента: (i) Мы не просим пересобрать всё веб-приложение, а только JS-файл-заглушку (в дополнение к WASM-файлу, конечно); (ii) Мы указываем, какие функции хотим экспортировать (в данном случае обе); (iii) Функции вызываются с подчеркиванием в начале.
Вы можете вернуться к сгенерированному Emscripten HTML-коду на сервере Python, и увидите, что он по-прежнему работает как обычно, только теперь с немного измененным текстом, поскольку мы изменили аргумент функции printf() в основной функции:

Конечно, поскольку созданная нами минималистичная HTML-страница использует тот же самый JS-файл-заглушку и тот же WASM-фреймворк, то изменения, внесенные нами в вызов printf() внутри main(), также влияют на нее (см. вывод в консоль):

Теперь мы можем создать новую веб-страницу, производную от минималистичной, где добавим кнопку, которая будет вызывать функцию button_message(), уже скомпилированную в файл WASM. Этот HTML-код по-прежнему вызывает тот же связующий JS-файл, и сам содержит дополнительный JS-код внутри тега
