После месяца работы с GSoC мы выпускаем нашу первую WebAssembly-версию webpack-sources, основного пакета для управления и создания исходных карт для ваших кодов. Мы используем Rust для разработки нашего проекта и связываем двоичный файл WebAssembly с интерфейсом JavaScript, чтобы вы могли легко загрузить его как модуль Node.js. Мы собираемся поделиться с вами нашей работой в этом и следующих постах.

Репозиторий проекта и пакет npm:

Ранний последователь: исходники webpack в WebAssembly

API нашего пакета на 100% совместимы с используемым в настоящее время weback-sources, это означает, что вы можете подключать и воспроизводить наш пакет npm, не меняя какой-либо фрагмент кода в Webpack!

Чтобы заменить webpack-sources нашим пакетом, вы можете получить его через yarn, используя:

$> yarn add webpack-sources@npm:wasm-webpack-sources

Убедитесь, что вы используете Node.js версии 8 или выше для поддержки модуля WebAssembly. Обратная совместимость, возвращающаяся к чистой реализации JavaScript при использовании более ранних версий Node.js, не была завершена в этом выпуске (^ 0.1.2).

Важное примечание: этот пакет все еще находится в стадии разработки и не используется в производственной среде.

Почему именно webpack-исходники?

В качестве сборщика модулей Webpack эффективно управляет вашими кодами из разных файлов. При обработке ваших кодов Webpack сохраняет их в виде строк в разных «источниках». Источник в Webpack может представлять фрагмент кода, контент и связанное имя файла из файла или даже манипуляции с кодами, такие как конкатенация кодов или замена в определенных позициях.

Исходники реализованы как классы в соответствии с различными целями, вы можете найти такие источники, как RawSource, OriginalSource, ConcatSource и ReplaceSource в пакете. Кроме того, webpack-sources создает исходные карты для ваших файлов с двумя основными зависимостями: source-map и source-list-map. Когда вы указываете devtool в конфигурации Webpack, webpack-sources создает полезную информацию о сопоставлении для улучшения процесса отладки.

Если вы забыли об исходной карте, вот небольшое напоминание.

Мы выбрали webpack-sources в качестве первого шага по нескольким причинам:

  • Чувствительность к производительности. Как уже упоминалось, многие операции со строками в Webpack выполняются с помощью webpack-sources. Кроме того, при создании исходных карт нам необходимо кодировать информацию о положении кодов с помощью Base64 VLQ, что дорого с вычислительной точки зрения.
  • Простой ввод-вывод: модули WebAssembly работают быстро, но передача значений между WebAssembly и JavaScript не является тривиальной. Когда аргументы и возвращаемые значения слишком сложны (например, объекты и массив строк), требуется много времени, чтобы переместить эти значения в память WebAssembly и восстановить структуры данных, что приводит к так называемой «проблеме пересечения границ». webpack-sources принимает ваши коды в качестве входных данных и выводит обработанный код с соответствующей исходной картой. Ввод и вывод просты: строка на входе и строка (и) на выходе, и это именно то, что мы хотим.
  • Простая структура проекта: webpack-sources теперь выпущен как пакет npm и зависит от двух внутренних пакетов: source-map от Mozilla и source-list-map от команды Webpack (они также выпускаются как пакеты npm, но не используются непосредственно в Webpack. ). При преобразовании цели будет лучше преобразовать все ее зависимости, чтобы сократить время передачи значений между WebAssembly и JavaScript. Таким образом, внутренние зависимости означают, что нам не нужно беспокоиться о предоставлении доступа к API этих пакетов.

WebAssembly на Rust

Мы выбираем Rust, чтобы переписать пакет и его зависимости и скомпилировать в двоичные файлы WebAssembly. Вы можете спросить, почему мы предпочитаем Rust вместо C ++? Мы пришли к такому решению по нескольким причинам:

  • Безопасность памяти. Как вы, возможно, знаете, Rust гарантирует безопасность памяти, вводя некоторые строгие правила компилятора. Эта функция так важна для низкоуровневого языка программирования без сборки мусора и избавит нас от многих проблем в будущих работах.
  • Управление пакетами. Поскольку разработчик избалован npm, Cargo, менеджер пакетов Rust по умолчанию, вполне достаточен, чтобы позволить вам выбрать Rust вместо C ++.
  • Набор инструментов WebAssembly. Нет сомнений в том, что существует множество зрелых инструментов, которые помогут нам в разработке WebAssembly на C ++, например emscripten. Однако сейчас для Rust публикуется все больше и больше инструментов с фантастическими функциями! Например, wasm-bindgen - это инструмент для создания интерфейса JavaScript для загрузки двоичного файла WebAssembly. Он создает функции на JavaScript для обертывания экспорта WebAssembly и предоставляет высокоуровневый API для передачи и возврата сложных данных, не требуя от разработчиков написания этих кодов управления памятью вручную. Таким образом, с помощью этих инструментов мы можем разработать наш модуль WebAssembly на более высоком уровне.

Линь выступил в JSConf EU 2018, в котором говорилось о Rust с WebAssembly. Вы можете обратиться к его сообщению Первый модуль Baby’s Rust + WebAssembly: передайте привет JSConf EU! ».

Что дальше?

Если вы попробовали наш проект, вы можете обнаружить, что производительность хуже, чем у исходной реализации JavaScript. В качестве первого шага по внедрению двоичных файлов WebAssembly в Webpack мы сосредоточились на «заставить его работать» в первый месяц. Действительно, мы согласны с тем, что производительность - это основная цель. Мы обнаружили некоторые возможные проблемы и решим их в будущих работах.

В этой серии публикаций мы познакомимся с нашей работой по преобразованию с Rust и wasm-bindgen. Мы прилагаем усилия к решениям интерфейса JavaScript для совместимости с API. В то же время на этом этапе рассматривается «проблема пересечения границ» из-за передачи значений между WebAssembly и JavaScript. Подробности мы расскажем в следующих статьях.

использованная литература