WebAssembly позволяет запускать высокопроизводительный код, написанный на Rust, прямо в браузере. В сочетании с Vite и React вы получаете быстрый сборщик, горячую перезагрузку и современный фронтенд. В этом руководстве мы подробно разберём, как подключить Rust‑компиляцию к Vite‑React проекту, используя wasm-pack, и как использовать полученный модуль в компоненте React. Шаги просты: инициализируем Rust‑проект, собираем wasm‑модуль, интегрируем его в Vite, а затем импортируем в React. В результате вы получите чистый, быстрый код, который легко масштабировать и поддерживать.
Разбор задачи
Вы хотите ускорить критически важные части вашего веб‑приложения, используя Rust, а также сохранить привычную структуру Vite‑React. Основные требования:
- Сгенерировать wasm‑модуль из Rust кода.
- Подключить его к сборке Vite без лишних настроек.
- Импортировать модуль в React компонент и использовать экспортированные функции.
В результате вы получите производительный фронтенд с возможностью масштабировать бизнес‑логику, написанную на Rust.
Пошаговое решение
1. Создайте новый Vite‑React проект: npm create vite@latest my-app -- --template react. Установите зависимости: cd my-app && npm install. 2. Инициализируйте Rust‑проект внутри папки /pkg: cargo new --lib wasm_pkg. В Cargo.toml добавьте wasm-bindgen = "0.2" и wasm-pack = "0.10" как dev‑dependency. 3. Внутри wasm_pkg/src/lib.rs напишите простую функцию, экспортируемую в JavaScript: #[wasm_bindgen] pub fn add(a:i32,b:i32)->i32{a+b}. 4. Скомпилируйте wasm‑модуль: wasm-pack build --target web. 5. Скопируйте сгенерированные файлы из wasm_pkg/pkg в src/wasm вашего Vite‑проекта. 6. В Vite настройте алиас: в vite.config.js добавьте resolve: { alias: { "@wasm": path.resolve(__dirname, "src/wasm") } }. 7. В React компоненте импортируйте модуль: import init, { add } from "@wasm/wasm_pkg.js";. Вызовите init().then(() => console.log(add(2,3)));. 8. Запустите проект: npm run dev и проверьте работу функции в консоли. Всё готово – Rust‑код теперь работает в React через Vite.
Рабочий код
// src/index.js (React entry point)
import React, { useEffect, useState } from 'react';
import ReactDOM from 'react-dom/client';
// Динамический импорт wasm модуля, который Vite соберёт в separate chunk
const loadWasm = async () => {
// При build Vite будет генерировать wasm.js, который экспортирует init
const wasmModule = await import('./wasm/pkg/my_wasm');
// init принимает ArrayBuffer из wasm файла, Vite автоматически подключит его
await wasmModule.default();
return wasmModule;
};
function App() {
const [value, setValue] = useState(null);
useEffect(() => {
loadWasm().then(wasm => {
// Предположим, у нас есть экспорт foo::add
setValue(wasm.foo.add(2, 3));
});
}, []);
return Result from Rust: {value};
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render();
// vite.config.js (путь к wasm pkg)
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
build: {
target: 'esnext', // позволяет Vite использовать async/await
rollupOptions: {
output: {
// Обеспечиваем, чтобы wasm файл попал в dist
assetFileNames: assetInfo => {
if (assetInfo.name.endsWith('.wasm')) return 'assets/[name][extname]';
return 'assets/[name]-[hash][extname]';
}
}
}
}
});
Типичные ошибки
1. Проблема с импортом wasm – если в Vite не указать target ‘esnext’, async загрузка не сработает, и возникнет ошибка «fetch failed». Решение: изменить target в build config.
2. Отсутствие wasm-пакета в output – по умолчанию wasm может быть удалён. Добавьте assetFileNames в rollupOptions, как показано выше.
3. Неправильный путь к wasm файлу – если импортируется ‘./wasm/pkg/my_wasm’, но в dist он находится в другом месте, Vite автоматически создаёт ссылку. Убедитесь, что wasm-pack генерирует pkg в папке wasm/.
FAQ
Как скомпилировать wasm с wasm-pack?
В корне Rust‑проекта выполните wasm-pack build --target bundler --out-dir ../wasm/pkg. Это создаст JS обёртку и .wasm файл, которые Vite сможет импортировать.
Можно ли использовать async/await при работе с wasm?
Да, Vite поддерживает async/await в ESNext. Важно, чтобы wasmModule.default() возвращал Promise, который резолвится после загрузки .wasm.
Какие типы данных можно передавать в Rust из React?
В Rust можно использовать простые типы – i32, f64, string (через JsValue). Для сложных структур используйте wasm-bindgen с сериализацией JSON.
Заключение
В итоге, чтобы подключить Rust WebAssembly к Vite и использовать его в React, следуйте шагам:
- Соберите wasm с wasm-pack.
- Конфигурируйте vite.config.js (target и rollupOptions).
- Импортируйте wasm в React через динамический import.
- Используйте экспортированные функции.
Проверяйте, что wasm попал в dist, и избегайте типичных ошибок с импортом.
