Сборка Rust-модуля для браузера
Функция анализатора написана на Rust и получила экспорт wasm-bindgen. Чтобы браузер мог её вызвать, недостаточно скопировать lib.rs в каталог сайта. Сначала Cargo создаёт Wasm-модуль, затем wasm-bindgen подготавливает JavaScript-обвязку и итоговый бинарный файл. Оба этапа относятся к сборке, а не к выполнению анализа выбранного текста.
В примере закрепим Rust 1.99.0 и wasm-bindgen 0.2.129. Выпуск Rust подтверждён официальным объявлением, версия библиотеки — её документацией. Это выбор окружения серии; установка и компиляция при подготовке уроков не выполнялись. Нам предстоит отдельно подтвердить совместимость полного проекта.
Cargo описывает библиотеку
Полный файл Cargo.toml задаёт имя библиотеки, тип выходного артефакта и точную зависимость. В проекте используем edition 2021: номер edition относится к правилам языка и не является номером компилятора.
[package]
name = "mera"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
wasm-bindgen = "=0.2.129"
[profile.release]
opt-level = 3
cdylib нужен для внешнего модуля, rlib сохраняет обычное библиотечное представление Rust. Точное ограничение версии не означает, что все транзитивные зависимости уже разрешены. После разрешённой установки появится Cargo.lock, который следует сохранить. В архиве серии его нет, потому что Cargo не запускался.
Режим оптимизации выбирается для будущей release-сборки. Он не подтверждает, что конкретный алгоритм быстрее JavaScript. Размер файла, время загрузки и стоимость передачи текста также влияют на пользовательский результат. Для маленькой операции добавление бинарного модуля может оказаться лишней работой.
Целевая платформа
Укажем окружение в полном rust-toolchain.toml:
[toolchain]
channel = "1.99.0"
profile = "minimal"
targets = ["wasm32-unknown-unknown"]
Target описывает Wasm без встроенной операционной среды. Это не WASI-программа, которая автоматически получает интерфейсы файловой системы. Наш модуль вызывается браузерной обвязкой и получает текст аргументом. Чтение файла и обновление страницы остаются на стороне JavaScript.
При самостоятельной подготовке читатель установит нужный toolchain и target. Команды ниже являются инструкцией для будущего локального запуска, а не журналом выполненных действий:
rustup toolchain install 1.99.0 --profile minimal
rustup target add wasm32-unknown-unknown --toolchain 1.99.0
cargo install wasm-bindgen-cli --version 0.2.129 --locked
cargo build --release --target wasm32-unknown-unknown
CLI должен соответствовать версии wasm-bindgen, с которой собран модуль. Не устанавливайте произвольный latest рядом с закреплённой библиотекой, рассчитывая на совместимость любого формата метаданных. Различие версий может проявиться уже при обработке артефакта, до открытия браузера.
Обвязка для ES modules
После Cargo ожидается исходный артефакт target/wasm32-unknown-unknown/release/mera.wasm. Обработаем его для браузерных модулей:
wasm-bindgen target/wasm32-unknown-unknown/release/mera.wasm \
--target web --out-dir web/pkg --out-name mera
Параметр --target web создаёт вариант, который можно импортировать как ES module без отдельного bundler. CLI описан в руководстве wasm-bindgen. Другие targets имеют другой договор подключения; их файлы нельзя смешивать с инструкцией для web только из-за похожих имён.
В каталоге результата ожидаются JavaScript-модуль, файл с суффиксом _bg.wasm и описания типов. Браузеру нужны согласованные .js и .wasm. TypeScript-декларации помогают разработчику, но не заменяют бинарник. Исходный Wasm Cargo тоже не следует подставлять вместо обработанного файла, игнорируя сгенерированные связи.
Итоговые имена могут быть просмотрены после сборки; код загрузчика в этой серии использует web/pkg/mera.js, а обвязка ищет соответствующий бинарный ресурс. Переименование одного файла без другого способно нарушить загрузку. Поэтому пакет передаём целиком как единый артефакт.
HTTP вместо file URL
Открытие index.html через файловый URL не воспроизводит обычную выдачу модулей и ресурсов сайтом. Для будущего просмотра используем локальный HTTP-сервер, который обслуживает каталог web. В стандартной Python-среде команда может выглядеть так:
python3 -m http.server 4191 --bind 127.0.0.1 --directory web
Сервер должен выдавать Wasm с подходящим типом application/wasm. Если производственный хостинг настроен иначе, поведение потоковой инициализации может отличаться. Нельзя считать локальную компиляцию доказательством правильного MIME, путей и заголовков на удалённой площадке.
Наш проект не использует shared memory и не требует подключать потоки Wasm через SharedArrayBuffer. Позднее вычисление будет работать в обычном отдельном Web Worker. Это другая архитектура: отдельный поток браузера с собственным модулем не означает разделяемую линейную память и не требует добавлять неиспользуемые зависимости.
Что входит в передаваемый пакет
Исходники сохраняют Cargo-файлы, Rust и браузерные модули. Производные target, web/pkg и установленный CLI относятся к среде сборки. В исходном архиве отсутствует скомпилированный бинарник: мы не создавали его, не вычисляли размер и не открывали страницу. Поэтому ссылки на .wasm в коде являются ожидаемыми путями после описанной команды.
Для готового выпуска нужно будет записать версии инструментария, lockfile и идентификатор исходников. Отдельно фиксируется результат выполнения контрольных входов. Такие сведения позволяют отличить технически проверенный артефакт от просто сохранённого исходного проекта.
Что означает закрепление версии
Точные номера в Cargo и toolchain убирают одну источник случайного изменения, но не подтверждают воспроизводимость на любом компьютере. Разрешение зависимостей, состояние registry, платформа установленного инструмента и параметры сборки всё ещё влияют на процесс. Поэтому в будущем техническом отчёте нужно сохранить не только название Rust, но и фактические версии команд и lockfile.
В исходном архиве команды даны полностью и не скрыты за неизвестным скриптом. Читатель может проследить, какой артефакт получает каждый этап. Если имя crate изменится с mera на другое, нужно согласованно поправить входной путь CLI и загрузчик. Ошибка имени не означает, что WebAssembly недоступен в браузере: сначала следует проверить обычную структуру файлов.
При подключении к существующей сборке сайта удобно выделить отдельный этап подготовки вычислительного пакета. Он выдаёт согласованный каталог ресурсов, который затем копирует основной сборщик. Сам Rust не должен переписывать статьи или публичные маршруты. Такое разделение соответствует нашему опыту сохранения URL: новая технология обслуживает конкретную функцию, а адреса библиотеки остаются самостоятельным договором.
Наконец, промежуточный бинарник может содержать служебные данные для обработки wasm-bindgen. Не пытайтесь уменьшать его случайным удалением секций до генерации обвязки. Оптимизация размера требует понимания этапа, полного пакета и последующей проверки поведения.
Теперь понятно назначение двух этапов: Cargo компилирует библиотеку, wasm-bindgen готовит согласованную браузерную границу. В следующем уроке создадим загрузчик, который инициализирует модуль один раз, сообщает состояние интерфейса и преобразует массив результата в именованные поля.