Создание 100% статически связанного однофайлового веб-приложения с React и Rust
Ссылка на оригинал - https://anderspitman.net/blog/static-react-rust-webapp/, автор публикации - Anders Pitman
В этом руководстве будут рассмотрены основы создания минимального приложения React, которое можно развернуть в виде статически связанного двоичного файла Rust. Для этого весь ваш код, включая HTML, JavaScript, CSS и Rust, упакован в один файл, который будет работать практически на любой 64-битной системе Linux, независимо от версии ядра или установленных библиотек.
Полный исходный код доступен на GitHub.
Зачем?
- Упрощенное развертывание: наличие статического двоичного кода означает, что вам просто нужно скопировать файл на сервер и запустить его.
- Кроссплатформенные собственные приложения с графическим интерфейсом. Одной из самых больших проблем при создании кроссплатформенного приложения с графическим интерфейсом пользователя является работа с библиотекой графического интерфейса, предназначенной для всех интересующих вас платформ. Такой подход позволяет вам использовать браузер пользователя для этой цели. Это несколько похоже на то, что выполняет Electron, но ваш бэкэнд в Rust, а не в JavaScript, и пользователь переходит к приложению из своего браузера. Здесь, безусловно, есть компромиссы, но это может хорошо работать для некоторых приложений. Впервые я познакомился с этим подходом путем синхронизации , которая написана на go, но делает нечто подобное.
- Потому что я был одержим статической связью столько, сколько себя помню, и я не совсем уверен, почему.
Предпосылки
- Среда сборки Linux
- Rust с cargo
- Узел с npm
Инициализируйте каталог проекта
Мы позволим Cargo управлять каталогом проектов для нас. Запустите следующие команды:
cargo new --bin react_rust_webapp cd react_rust_webapp
Создание приложения React
Сначала установите React, Babel и Webpack:
mkdir ui cd ui npm init -y npm install --save react react-dom npm install --save-dev babel-core babel-loader babel-preset-env babel-preset-react webpack webpack-cli
Затем создайте исходные файлы:
mkdir dist touch dist/index.html mkdir src touch src/index.js
Поместите следующий контент в dist/index.html:
<!doctype html> <html> <head> <title>Static React and Rust</title> </head> <body> <div id="root"></div> <script src="/bundle.js"></script> </body> </html>
И установите в src/index.js следующее:
import React from 'react'; import ReactDOM from 'react-dom'; ReactDOM.render( <h1>Hi there</h1>, document.getElementById('root') );
Нам также понадобится файл .babelrc:
{ "presets": [ "react", "env", ], }
И webpack.config.js файл:
const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader', } } ] } };
Теперь вы должны быть в состоянии проверить, работает ли интерфейс. Запускаем:
npx webpack --mode development
Это сгенерирует dist/bundle.js. Если вы запустите веб-сервер в dist каталоге, вы сможете успешно обработать пример содержимого.
Теперь для части Rust.
Настройка бэкэнда Rust
Перейти в react_rust_webappкаталог:
cd ..
Первое, что нам нужно сделать, это установить веб-фреймворк. Я обнаружил, что Руил отлично подходит для этого простого примера. Я тоже очень люблю Rocket.
Добавьте rouille к вашим зависимостям Cargo.toml:
[package] name = "react_rust_webapp" version = "0.1.0" [dependencies] rouille = "2.1.0"
Теперь измените, src/main.rs, чтобы иметь следующий контент:
#[macro_use] extern crate rouille; use rouille::Response; fn main() { let index = include_str!("../ui/dist/index.html"); let bundle = include_str!("../ui/dist/bundle.js"); rouille::start_server("0.0.0.0:5000", move |request| { let response = router!(request, (GET) ["/"] => { Response::html(index) }, (GET) ["/bundle.js"] => { Response::text(bundle) }, _ => { Response::empty_404() } ); response }); }
Как это работает?
Во время компиляции include_str! читает указанный файл и вставляет содержимое в виде статической строки в скомпилированный двоичный файл. Эта строка затем доступна как обычная переменная.
Код маршрута только устанавливает две конечные точки HTTP, "/" и "/bundle.js". Вместо того, чтобы возвращать файлы из файловой системы, как это обычно делается с веб-приложением, мы возвращаем содержимое статических строк из двоичного файла.
Чтобы узнать больше об использовании Rouille для более сложных вещей, обратитесь к их документам.
Запуск
Хорошо, теперь, если все прошло хорошо, мы сможем запустить его. Убедитесь, что ui/dist/bundle.js он уже создан, как указано выше. Затем запустите:
cargo run
Он должен запустить сервер через порт 5000. Если вы перейдете по адресу http://localhost:5000 в вашем браузере, вы должны увидеть «Hi there».
Статическое связывание
Эта часть может быть пропущена, если вам не нужно 100% статическое связывание. В любом случае Rust статически связывает большинство библиотек по умолчанию, за исключением таких вещей, как libc.
Если вы хотите продолжить, вам сначала нужно установить musl libc в вашей системе и убедиться, что команда musl-gcc находится в вашем PATH.
Затем повторите груз следующим образом:
cargo run --target=x86_64-unknown-linux-musl
Построение производства
Для меньших двоичных файлов соберите bundle.jsследующее (из с ui/):
npx webpack --mode production
И запустить груз следующим образом:
cargo build --release --target=x86_64-unknown-linux-musl
Вы должны получить статически связанный двоичный файл в react_rust_webapp/target/x86_64-unknown-linux-musl/release/
Заключение
Это только основы. С этим можно многое сделать, в том числе:
- Используется build.rsдля автоматической сборки приложения React при компиляции Rust.
- Взять номер порта из командной строки
- Сериализованные (возможно, JSON) запросы и ответы
- Запустите webpack как команду сценария npm
- Ориентируйтесь на другие ОС. Я еще не пробовал, но это должно быть в основном переносимо на MacOS и Windows, благодаря великолепной Rust / Cargo и универсальной доступности веб-браузеров.
- 4 reads
Не нашли ответ на свой вопрос? Возможно, вы найдете решение проблемы на нашем канале в Youtube! Здесь мы собрали небольшие, но эффективные инструкции. Смотрите и подписывайтесь на наш youtube-канал!