Для чего нужна данная статья? :
- Получить представление о разработке React и Rust.
- Найти компромисс между использованием библиотеки Rust в качестве собственного модуля или WebAssembly.
Узнать что такое:
- Реальная обработка видео потока с камеры
- Многомодельная ML-система:
YOLOv8 для обнаружения объектов
ResNet-50 для классификации
NLP модель для анализа текста - Распределенная обработка данных
- JWT аутентификация с OAuth2
- Оптимизированные WASM-модули для предобработки данных
Зачем Вам это уметь? :
1. Backend API + React Frontend
Архитектура:
- Rust (Actix-web/Rocket) → REST/GraphQL API
- React → SPA Frontend
Пример (Rust API):
// Actix-web API
use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};
#[get("/api/data")]
async fn get_data() -> impl Responder {
HttpResponse::Ok().json(serde_json::json!({"message": "From Rust!"}))
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new().service(get_data))
.bind("127.0.0.1:8080")?
.run()
.await
}
React Fetch:
function App() {
const [data, setData] = useState();
useEffect(() => {
fetch("http://localhost:8080/api/data")
.then(res => res.json())
.then(setData);
}, []);
return <div>{data?.message}</div>;
}
2. WebAssembly (WASM) в React
Использование:
- Вычисления в браузере
- Обработка изображений/аудио
- Криптография
Пример (Rust WASM):
// src/lib.rs
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u32 {
match n {
0 => 0,
1 => 1,
_ => fibonacci(n-1) + fibonacci(n-2),
}
}
React Integration:
import init, { fibonacci } from './wasm/pkg/wasm.js';
function App() {
const [result, setResult] = useState<number>();
useEffect(() => {
init().then(() => {
setResult(fibonacci(10));
});
}, []);
return <div>Fibonacci(10): {result}</div>;
}
3. Desktop Apps (Tauri)
Стек:
- Rust (Tauri Core)
- React (UI)
- SQLite (Встроенная БД)
Пример Tauri Command:
#[tauri::command]
fn read_file(path: String) -> Result<String, String> {
std::fs::read_to_string(path)
.map_err(|e| e.to_string())
}
React Вызов:
import { invoke } from '@tauri-apps/api';
function FileReader() {
const readFile = async () => {
const content = await invoke('read_file', { path: './data.txt' });
console.log(content);
};
return <button onClick={readFile}>Read File</button>;
}
4. CLI Tools для React Dev
Сценарии:
- Генерация компонентов
- Анализ производительности
- Конвертация форматов
Пример CLI на Rust:
// Генератор компонентов
use clap::Parser;
#[derive(Parser)]
struct Cli {
component: String,
}
fn main() {
let args = Cli::parse();
let content = format!(
"export const {} = () => <div>New Component</div>",
args.component
);
std::fs::write(format!("./src/{}.tsx", args.component), content).unwrap();
}
5. Game Dev (WebAssembly + WebGL)
Архитектура:
- Rust: Игровое ядро (Bevy Engine)
- React: UI Overlay
- WebGL: Рендеринг
Пример Bevy System:
fn movement_system(
mut query: Query<(&mut Transform, &Velocity)>,
time: Res<Time>
) {
for (mut transform, velocity) in query.iter_mut() {
transform.translation += velocity.0 * time.delta_seconds();
}
}
React UI Integration:
const GameUI = ({ score }) => (
<div className="overlay">
<HealthBar />
<Score value={score} />
</div>
);
6. Blockchain (Smart Contracts + dApps)
Стек:
- Rust: Solana/Polkadot контракты
- React: dApp Frontend
- Web3.js/ethers.js
Пример Anchor Program:
#[program]
mod my_program {
use super::*;
pub fn initialize(ctx: Context<Initialize>, data: u64) -> Result<()> {
ctx.accounts.my_account.data = data;
Ok(())
}
}
React Wallet Integration:
const ConnectButton = () => {
const connect = useWallet().connect;
return (
<button onClick={connect}>
Connect Solana Wallet
</button>
);
};
7. Real-Time Systems (WebSockets)
Архитектура:
- Rust: WebSocket Server (tokio-tungstenite)
- React: WebSocket Client
Rust Server:
async fn handle_connection(stream: TcpStream) {
let ws_stream = tokio_tungstenite::accept_async(stream).await.unwrap();
while let Some(msg) = ws_stream.next().await {
// Обработка сообщений
}
}
React Client:
const RealTimeFeed = () => {
const [messages, setMessages] = useState([]);
const ws = useRef(new WebSocket('ws://localhost:8080'));
useEffect(() => {
ws.current.onmessage = (e) => {
setMessages(prev => [...prev, e.data]);
};
}, []);
return <div>{messages.join('\n')}</div>;
};
8. Cross-Platform Mobile (React Native)
Интеграция:
- Rust: Нативные модули (JSI)
- React Native: UI
Пример Native Module:
#[no_mangle]
pub extern "C" fn native_add(a: i32, b: i32) -> i32 {
a + b
}
React Native Binding:
import { NativeModules } from 'react-native';
const { RustModule } = NativeModules;
const App = () => (
<Text>
Result: {RustModule.native_add(2, 3)}
</Text>
);
9. Machine Learning Inference
Сценарий:
- Rust: Сервер для инференса (ONNX)
- React: Визуализация результатов
Пример ML API:
async fn predict(
bytes: web::Bytes,
model: web::Data<Arc<ort::Session>>
) -> Result<Json<Value>> {
let input = preprocess(bytes);
let outputs = model.run(input)?;
Ok(Json(outputs))
}
React Upload:
const ModelUploader = () => {
const [file, setFile] = useState<File>();
const predict = async () => {
const formData = new FormData();
formData.append('file', file);
const res = await axios.post('/api/predict', formData);
// Визуализация
};
return <input type="file" onChange={e => setFile(e.target.files[0])} />;
};
10. Static Site Generation (SSG)
Архитектура:
- Rust: Генератор контента (Markdown → JSON)
- React: Gatsby/Next.js
Пример генератора:
fn generate_content(path: &Path) -> Result<()> {
let content = std::fs::read_to_string(path)?;
let html = markdown::to_html(&content);
let json = serde_json::to_string(&Frontmatter::parse(&content))?;
write_output(path, json, html)
}
Настройка среды разработки:
установите необходимые инструменты и библиотеки для React Native, вам нужно будет установить Node.js, React Native CLI и эмулятор или устройство Android или iOS.
Добавить поддержку Rust:
Вы можете использовать библиотеку Rust в качестве собственного модуля в своем приложении или скомпилировать код Rust в WebAssembly и использовать его в своем приложении. Если вы выберете первый вариант, вам нужно будет использовать менеджер пакетов Rust Cargo для создания библиотеки Rust, а затем использовать библиотеку мостов, такую как FFI, для вызова функций Rust из вашего приложения. Если вы выберете второй вариант, вам нужно будет использовать такой инструмент, как wasm-pack, для компиляции кода Rust в WebAssembly, а затем использовать библиотеку JavaScript, такую как wasm-bindgen, для вызова функций Rust из вашего приложения.
Что может понадобиться?:
wasm-pack: инструмент командной строки для сборки и публикации модулей WebAssembly, сгенерированных Rust. Он поставляется со встроенной поддержкой упаковки модулей в виде пакетов NPM, что упрощает их использование в проектах JavaScript.
cargo-web: подкоманда Cargo, которая может быть использована для создания кода Rust в WebAssembly и других целевых форматах, таких как JavaScript или собственные двоичные файлы. Он поддерживает цели wasm32-unknown-unknown и wasm32-unknown-emscripten.
wasm-bindgen: библиотека Rust, которая позволяет легко взаимодействовать между Rust и JavaScript. Он генерирует клеевой код, необходимый для вызова функций Rust из JavaScript и наоборот. wasm-bindgen также предоставляет такие функции, как автоматическое управление памятью и преобразование типов.
wargo: инструмент, который позволяет создавать модули WebAssembly из кода Rust с помощью Cargo. Он предназначен для упрощения процесса создания и публикации модулей WebAssembly и включает в себя такие функции, как автоматическая комплектация и оптимизация.
stdweb: библиотека Rust, предоставляющая набор API для взаимодействия с моделью DOM и другими веб-API. Он позволяет писать веб-приложения полностью на Rust, без необходимости Использования JavaScript. stdweb можно использовать для создания модулей WebAssembly или кода JavaScript.
wasm-micro-runtime: облегченная среда выполнения для WebAssembly, которая может быть встроена в приложения, написанные на C или Rust. Он предназначен для использования в средах с ограниченными ресурсами, таких как микроконтроллеры или устройства IoT.
wasm-opt: инструмент, который считывает WebAssembly в качестве входных данных, выполняет преобразование, оптимизацию, передает его, а затем выдает преобразованную WebAssembly в качестве выхода.
wasm2js: Инструмент, который компилирует WebAssembly в "almost asm.js".
wasm-gc: Небольшой инструмент для сбора мусора модуля WebAssembly и удаления всех ненужных экспортов, импортов, функций.
wasm-snip: инструмент, который заменяет тело функции WebAssembly недоступной инструкцией.
Создание API Rust:
используйте менеджер пакетов Cargo для создания нового проекта Rust. Вы можете использовать команду cargo new myapp для создания нового проекта с именем "myapp".
Пример:
$ cargo new notes-app --bin
Добавление зависимостей Cargo.toml:
[dependencies]
rocket = "0.5.0-rc.1"
serde = { version = "1.0", features = ["derive"] }
Создание REST API с использованием Rocket для CRUD операций:
#[derive(Debug, Serialize, Deserialize)]
struct Note {
id: u64,
title: String,
content: String, }
#[get("/notes")] fn get_notes() -> Json<Vec<Note>> {
// TODO: Implement getting all notes from the database }
#[get("/notes/<id>")] fn get_note(id: u64) -> Option<Json<Note>> {
// TODO: Implement getting a single note by ID from the database }
#[post("/notes", data = "<note>")] fn create_note(note: Json<Note>) -> Json<Note> {
// TODO: Implement creating a new note in the database }
#[put("/notes/<id>", data = "<note>")] fn update_note(id: u64, note: Json<Note>) -> Option<Json<Note>> {
// TODO: Implement updating a note by ID in the database }
#[delete("/notes/<id>")] fn delete_note(id: u64) -> Option<()> {
// TODO: Implement deleting a note by ID from the database }
#[launch] fn rocket() -> _ {
rocket::build()
.mount("/", routes![get_notes, get_note, create_note, update_note,
delete_note])
}
Создание нового проекта React:
используйте инструмент create-react-app для создания нового проекта React. Вы можете использовать команду npx create-react-app myapp для создания нового проекта с именем "myapp".
Пример:
import React, { useState, useEffect } from 'react';
import { StyleSheet, Text, View, TextInput, Button } from 'react-native';
export default function App() {
const [notes, setNotes] = useState([]);
useEffect(() => {
fetch('http://localhost:8000/notes')
.then(response => response.json())
.then(data => setNotes(data))
.catch(error => console.error(error));
},
[]);
const [title, setTitle] = useState('');
const [content, setContent] = useState('');
const handleSubmit = () => {
fetch('http://localhost:8000/notes', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title, content })
})
.then(response => response.json())
.then(data => setNotes([...notes, data]))
.catch(error => console.error(error));
setTitle('');
setContent('');
};
return (
<View style={styles.container}>
<Text style={styles.title}>Notes</Text>
{notes.map(note => (
<View key={note.id} style={styles.note}>
<Text style={styles.noteTitle}>{note.title}</Text>
<Text style={styles.noteContent}>{note.content}</Text>
</View>
))}
<TextInput
style={styles.input}
placeholder="Title"
value={title}
onChangeText={setTitle}
/>
<TextInput
style={styles.input}
placeholder="Content"
value={content}
onChangeText={setContent} />
Добавление поддержки Rust в React:
используйте инструмент wasm-pack для создания модуля WebAssembly из кода Rust. Вы можете использовать команду wasm-pack init --scope myusername для создания нового проекта Rust для WebAssembly. Затем используйте команду wasm-pack build --target web для сборки кода Rust в качестве модуля WebAssembly.
Загрузка кода Rust в React:
используйте библиотеку react-rust-wasm для загрузки модуля WebAssembly в приложение React. Вы можете использовать хук useRust для загрузки модуля и вызова функций Rust из компонентов React.
Интеграция кода Rust:
используйте библиотеку Rust или модуль WebAssembly, созданный ранее, чтобы добавить дополнительные функции в приложение.
Cоздание простого мобильного приложения
1.1 Создайте новый Rust-проект:
cargo new rust_library
cd rust_library
1.2 Напишите код на Rust:
Файл src/lib.rs:
#[no_mangle] pub extern "C"
fn add_numbers(a: i32, b: i32) -> i32
{ a + b }
Здесь #[no_mangle] говорит Rust компилятору не изменять имя функции, чтобы она была доступна для вызова из других языков, таких как JavaScript или C/C++.
1.3 Скомпилируйте Rust-код в статическую библиотеку:
Для Android:
cargo build --target aarch64-linux-android --release
Для iOS:
cargo build --target aarch64-apple-ios --release
2.1 Установите React Native CLI и создайте проект:
npx react-native init RustReactApp
cd RustReactApp
2.2 Интеграция с Rust через Native Modules
Для интеграции Rust в React Native мы используем нативные модули (Native Modules).
2.2.1 Android (Java):
Создайте RustModule.java в android/app/src/main/java/com/rustreactapp/:
package com.rustreactapp;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Callback;
public class RustModule extends ReactContextBaseJavaModule {
static {
System.loadLibrary("rust_library");
}
private native int addNumbers(int a, int b);
RustModule(ReactApplicationContext context) {
super(context);
}
@Override
public String getName() {
return "RustModule";
}
@ReactMethod
public void add(int a, int b, Callback callback) {
int result = addNumbers(a, b);
callback.invoke(result);
}
}
2.2.2 iOS (Objective-C):
Создайте RustModule.m в ios/RustReactApp/:
#import <React/RCTBridgeModule.h>
@interface RCT_EXTERN_MODULE(RustModule, NSObject)
RCT_EXTERN_METHOD(add:(NSInteger)a b:(NSInteger)b callback:
(RCTResponseSenderBlock)callback)
@end
Затем создайте RustModule.swift:
import Foundation
@objc(RustModule)
class RustModule: NSObject {
@objc(add:b:callback:)
func add(a: Int, b: Int, callback: RCTResponseSenderBlock) {
let result = add_numbers(Int32(a), Int32(b))
callback([NSNull(), Int(result)])
}
}
Не забудьте добавить библиотеку Rust в настройки Xcode, чтобы она была включена в сборку iOS.
3.1 Создайте простое приложение:
Файл App.js:
import React, { useState } from 'react';
import { Button, Text, View } from 'react-native';
import { NativeModules } from 'react-native';
const { RustModule } = NativeModules;
const App = () => {
const [result, setResult] = useState(null);
const handleAdd = () => {
RustModule.add(5, 3, (res) => {
setResult(res);
});
};
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Button title="Add 5 + 3" onPress={handleAdd} />
{result !== null && <Text>Result: {result}</Text>}
</View>
);
};
export default App;
Теперь вы можете запустить ваше приложение на Android или iOS:
npx react-native run-android
npx react-native run-ios
Real-Time Threat Detection System (RTTDS)
Архитектура:
- Frontend: React + TypeScript + WebAssembly + Redux Toolkit + WebSocket
- Backend:
Rust (Actix-Web) + Tokio + Diesel + PostgreSQL
Python ML Microservice (FastAPI + PyTorch + OpenCV + Transformers) - Инфраструктура:
Docker + Kubernetes
Kafka для потоковой обработки
Prometheus + Grafana для мониторинга
// backend/src/main.rs (Rust API Gateway)
#[actix_web::main]
async fn main() -> std::io::Result<()> {
use actix_web::{web, App, HttpServer};
use diesel::{r2d2::ConnectionManager, PgConnection};
type DbPool = r2d2::Pool<ConnectionManager<PgConnection>>;
let manager = ConnectionManager::<PgConnection>::new(
std::env::var("DATABASE_URL").unwrap()
);
let pool = r2d2::Pool::builder()
.build(manager)
.unwrap();
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(pool.clone()))
.service(web::resource("/analyze")
.route(web::post().to(analyze_handler))
.service(web::resource("/ws")
.route(web::get().to(websocket_handler)))
})
.bind("0.0.0.0:8080")?
.run()
.await
}
async fn analyze_handler(
stream: web::Payload,
pool: web::Data<DbPool>,
) -> Result<HttpResponse, Error> {
// Обработка медиапотока и взаимодействие с ML сервисом
}
ML Service (Python):
# ml_api/main.py
from fastapi import FastAPI, File
import torch
from transformers import pipeline
app = FastAPI()
@app.post("/detect")
async def detect_objects(data: bytes = File(...)):
model = torch.hub.load('ultralytics/yolov8', 'yolov8s')
results = model(data)
return results.pandas().xyxy[0].to_dict()
Интеграция React+WASM:
// frontend/src/components/VideoProcessor.tsx
import init, { process_frame } from '../wasm/lib.rs';
const VideoStream: FC = () => {
const processVideo = async (frame: VideoFrame) => {
await init();
const processed = process_frame(new Uint8Array(frame.data));
// Отправка на сервер через WebSocket
};
return (
<WebSocket url="ws://localhost:8080/ws">
{({ send }) => (
<VideoRecorder onFrame={processVideo} />
)}
</WebSocket>
);
};