Мы привыкли думать, что браузер — это «тонкий клиент»: максимум логики на сервере, а во фронте лишь HTML-шаблоны, немного CSS-гламура и горы JavaScript, чтобы прикрыть швы. Но реальность постепенно меняется. Всё чаще тяжёлые задачи—рендеринг трёхмерного редактора, обработка гигабайтных таблиц, машинное обучение прямо на странице—уходят из серверной части в “карман пользователя”. И если раньше на этих высотах царствовал JavaScript (а позже TypeScript и WebGL), то теперь инициативу перехватывает WebAssembly (WASM).
WebAssembly—это не очередной «надстройный» язык, а минимальный набор инструкций наподобие машинного кода, который любой современный браузер читает почти так же быстро, как процессор читает бинарь, скомпилированный под его архитектуру. Итог — нативная производительность плюс песочница безопасности.
Звучит красиво, но можно ли доверить WASM не только C++-игрушкам, а любимому интерпретируемому Python? Можно. Проект Pyodide берёт CPython 3.x, компилирует в WASM через Emscripten, кладёт поверх тонкую JS-прослойку и публикует на CDN. Итоговый файл весит несколько десятков мегабайт, но забирает с собой полноценную стандартную библиотеку и десятки портированных пакетов — NumPy, Pandas, Scikit-Learn, Matplotlib и даже networkx.
WASM крупным планом
Перед тем как нырять в код, давайте трезво посмотрим на плюсы и минусы.
Плюсы | Минусы | |
---|---|---|
Скорость | Двоичный формат читается молниеносно, JIT-компиляция минимальна. | Частые syscall-ы в JS-среду могут стать «бутылочным горлышком». |
Портативность | Один .wasm — все браузеры, все ОС. | Разные браузеры по-разному оптимизируют стек и память; производительность скачет. |
Безопасность | Песочница: нет доступа к диску, системным вызовам, памяти хоста. | …и это же ограничение мешает открывать сокеты TCP, писать на файловую систему, работать с GPU без WebGPU. |
Мультиязычность | Rust, C++, Go, Zig, Swift, Python — компилируется всё. | Не всякий runtime легко портируется: GC, трединг, системные сигналы — головная боль. |
Критическое замечание. В индустрии часто повторяют мантру «перформанс = WASM». Это упрощение. В многих случаях оптимизированный JavaScript (или даже WebGL+JS) справится быстрее, чем плохо скомпилированный WASM-модуль. Не случайно авторы крупных движков (Figma, AutoCAD Web) используют гибридный подход: вычислительные ядра — на WASM, а лёгкая логика — на TypeScript.
История Pyodide: от Firefox до Open Source
2018 год. Исследовательская команда Mozilla ищет способ показать, что WASM — не игрушка. В фокусе — Jupyter-ноутбуки: учёные мечтают обмениваться интерактивными статьями без тяжеловесных серверов. Разработчики берут ядро CPython, выстраивают скрипт сборки через Emscripten, патчат десятки C-модулей стандартной библиотеки.
2020 год. Mozilla режет расходы, команда распускается; Pyodide мигрирует в независимую организацию, а в 2021-м проект попадает под крыло фонда CPython-девелоперов. Сегодня Pyodide живёт на GitHub, собирается CI-пайплайном, проходит тесты CPython и выкладывается на CDN. Можно спорить о градусе коммерческой поддержки, но факт: релизы выходят стабильно, сообщество активно.
Семь примеров: от «Hello, World!» до дашборда
Предполагается, что вы умеете читать JS и Python. Если какие-то отрывки кажутся тривиальными — пролистывайте: ценность примеров — в паттернах, а не в самих трёх строчках кода.
1. «Hello, World!» на чистом Pyodide

Разбор по шагам
Этап | Что делает | Почему важно |
---|---|---|
Подключаем pyodide.js | Скрипт кладёт глобальную функцию loadPyodide() и загрузчик WASM. | Файл весит ~2 МБ (gzip) + WASM-модуль ~8–10 МБ. |
await loadPyodide() | Скачивает .wasm , инициализирует виртуальную ФС и рабочий поток. | Первый вызов — самый долгий, дальше модуль кэшируется. |
runPythonAsync() | Асинхронно передаёт строку кода в интерпретатор. | Версия без Async блокирует главный поток. |
Вывод результата | По умолчанию print() идёт в консоль; мы явным возвратом передаём строку в JS. | Чётко разделяем «что печатать» и «что возвращать». |
2. Выводим результат прямо в DOM

Что нового по сравнению с примером 1?
- Импорт модулей внутри строки.
Любойimport
возможен, если модуль уже встроен в Pyodide или был загружен черезpyodide.loadPackage()
. - Возврат значения вместо вывода
print
.
Это удобнее: не нужно парсить stdout, мы сразу получаем JavaScript-число илиPyProxy
.
3. Вызов Python-функции из JavaScript (двусторонний мост)

Фишки
py.globals.get()
возвращает PyProxy — JS-объект, проксирующий Python-объект.
➜ Важно вручную уничтожать большие объекты (.destroy()
), иначе память утечёт.- Вы можете в обратную сторону передавать JS-функции в Python через
pyodide.registerJsModule()
.
4. NumPy — быстрые матрицы в браузере

Оптимизация. Для больших матриц лучше не возвращать tolist()
, а пересылать memoryview
или сериализовать NumPy-массив в SharedArrayBuffer
(пока экспериментально).
BLAS. Pyodide собирает OpenBLAS без многопоточности → скорость ≈ CPython без MKL.
5. Matplotlib: рисуем график без серверов
Проблема: Matplotlib — это «толстый» C-бэкэнд + множество зависимостей. В Pyodide он собран в варианте Agg
, который рендерит PNG в памяти.

Можно заменить Matplotlib на Plotly или Vega-Lite, где рендеринг уходит в SVG/WebGL, но тогда вам придётся делать расчёты в Python и передавать данные в JS-визуализацию.
6. Web Worker: тяжёлая математика не блокирует UI
Архитектура

Каждый Worker — самостоятельный WASM-инстанс; общий кеш пакетов не шарится.
Чтобы не тянуть второй раз те же мегабайты, инициализируйте Pyodide один раз и храните Promise в глобальной переменной внутри worker.

UI-счётчик секунд продолжает тикать, а тяжёлый Python-цикл работает вдали от основного потока.
7. Дашборд: CSV → Pandas → график + таблица
Файловая структура

Ключевые идеи
- Загрузка CSV: читаем файл через
FileReader
, передаём строку в Python через глобальную переменнуюcsv_data
. - Гибкая метрика: выпадающий список
select
даёт четыре сценария: общие продажи, по категориям, по регионам, помесячно. - Pandas-группировки:
groupby
+agg
возвращают DataFrame; форматируем числа как$1 234.56
. - Matplotlib без UI-блокировки: рендерим график в буфер, достаём
base64
, вставляем<img>
. - HTML-таблица:
DataFrame.to_html()
вставляется прямиком вinnerHTML
. Автоматически получаем<thead>/<tbody>
, которые легко сортировать сторонними библиотеками.

Оптимизация подсветки
- Замените
to_html()
на собственный шаблон, если нужен лёгкий DOM и стили Tailwind. - Для интерактивности подключите
sortable.js
и добавьте атрибутclass="sortable"
к<table>
.
Подводные камни и честная критика
- Размер дистрибутива. Даже «малый» Pyodide > 20 МБ. При слабом интернете пользователь уйдёт, не дождавшись. Возможно, стоит предложить ленивую-загрузку: сначала интерфейс, потом бандл.
- Ограниченный multithreading. Стандартный CPython полагается на pthread или win32-треды. В WASM-песочнице тредов нет (хотя работает экспериментальный
SharedArrayBuffer
). Поэтому async IO + корутины остаются спасением. - Garbage collector x2. JS коллекционирует свои объекты, Pyodide — свои. Между ними — прозрачные «прокси». Если забыть вызвать
result.destroy()
у крупного NumPy-массива, получите утечку в RAM браузера. - Библиотеки с C-расширениями. Нет портированной
.so
-шки — нет пакета. SciPy, Pillow, PyTorch — всё это либо урезано, либо работает в экспериментальных форках. - Безопасность ≠ приватность. Да, WASM-код в песочнице. Но ваша логика, ключи API, токены OAuth оказываются на клиенте. Залогинился пользователь — он же и может декомпилировать. Поэтому для платных сервисов Pyodide — скорее демо-инструмент, чем финальное решение.
Альтернативы, которые стоит сравнить
- PyScript — проект Anaconda, который поверх Pyodide даёт HTML-теги
<py-script>
и «магические» импорты. Красиво для демонстраций, но сейчас тормозит сильнее, чем «голый» Pyodide. - Brython / Transcrypt — транспиляторы Python→JavaScript. Не нужен WASM, грузится быстро, но не работают C-расширения, нет настоящего GIL, язык — подмножество Python.
- Rust + PyO3 — можно написать ядро на Rust, связать с Python-скриптами, а всё тяжёлое скомпилировать в WASM. Будет быстрее, но сложнее в сборке.
Что выбрать?
Цель | Решение | Комментарий |
---|---|---|
Демо-ноутбук без сервера | Pyodide или PyScript | Быстро, эффектно, подходит для статей Medium или курсов. |
Прод-ML-виджет на лендинге | WASM-ядро + JS-UI | Держите модель в WASM, визуализацию — в JS. |
Вычисления, требующие GPU | WebGPU + JS/TS | Pyodide пока не умеет напрямую использовать GPU. |
Полноценное веб-приложение с базой данных | Django/FastAPI + JS-фронт | Серверное решение всё ещё удобнее для авторизации, транзакций, фоновых задач. |
Итог
WebAssembly уже не фантазия, а рабочий инструмент. Pyodide доказал, что даже тяжеловесный интерпретатор Python может жить в браузере без серверов и Docker-контейнеров. Однако слепо верить в «серебряную пулю» не стоит. Разработка под WASM — это компромисс между скоростью, весом бандла и поддержкой экосистемы.
Стоит ли пробовать? Да, если у вас:
- образовательная платформа, где студентам нужен интерактив;
- офлайн-дашборд для данных, которые нельзя слать на чужой сервер;
- прототип, который должен работать на GitHub Pages без бекэнда.
Стоит ли переносить туда всё? Скорее всего, нет. Корпоративные приложения требуют авторизации, ролей, хранилища и логирования, которые проще (и дешевле) держать на сервере.
Вопрос на дом. Возьмите свой средний Jupyter-ноутбук с аналитикой, попробуйте запустить через Pyodide и замерьте время загрузки. Если пользователь видит первый график быстрее, чем за 3-4 секунды, — технология подходит. Если нет — оптимизируйте или верните расчёт на сервер.
Что дальше?
- Подождать стабильного
wasmtime
в браузерах — возможно, это ещё ускорит выполнение. - Следить за появлением WebGPU-бэкэнда в Matplotlib или Altair.
- Поэкспериментировать с одностраничным приложением, где WASM-Python генерирует PDF-отчёт на клиенте.
Так мир фронтенда и Python сближается: меньше HTTP-запросов, больше свободы пользователю. Главное — не перемещать вычисления бездумно. Ведь «сервер» — это не ругательное слово, а правильный инструмент, если задача того требует.
***✨ А что думаете вы? ✨
Делитесь мыслями в комментариях — ваше мнение вдохновляет нас и других!
Следите за новыми идеями и присоединяйтесь:
• Наш сайт — всё самое важное в одном месте
• Дзен — свежие статьи каждый день
• Телеграм — быстрые обновления и анонсы
• ВКонтакте — будьте в центре обсуждений
• Одноклассники — делитесь с близкими
Ваш отклик помогает нам создавать больше полезного контента. Спасибо, что вы с нами — давайте расти вместе! 🙌