Создание 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, но делает нечто подобное.
  • Потому что я был одержим статической связью столько, сколько себя помню, и я не совсем уверен, почему.

Предпосылки

Инициализируйте каталог проекта

Мы позволим 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 и универсальной доступности веб-браузеров.

Не нашли ответ на свой вопрос? Возможно, вы найдете решение проблемы на нашем канале в Youtube! Здесь мы собрали небольшие, но эффективные инструкции. Смотрите и подписывайтесь на наш youtube-канал!

Смотреть на Youtube

Руководства и обзоры

1 Что нужно восстановить?

Видео

MP4, AVI и HD видео хранятся на телефоне и / или по ошибке удаляются вместе с фотографиями и другими медиафайлами.

Контакты

Номера телефонов друзей и знакомых из приложения «Контакты Android», журналы вызовов; Восстановление SIM-карты.

Фото

Удалены файлы JPG / PNG из Галереи Android; фото, загруженные на мобильный, файлы повреждены после восстановления.

Смс и сообщения

Чаты WhatsApp и Facebook, текстовые сообщения в соцсетях, информация на сим-карте

2 Где пропали файлы?

На sd-карте

Фотографии и документы хранятся на SD-картах. Часто на них случайно удаляются файлы

На телефоне

Программы для восстановления не распознают внутреннее хранилище телефона как диск, но есть другие решения.

На USB флешке

Эти небольшие устройства хранения данных часто выходят из строя или на них появляются ошибки чтения.

На HDD или SSD

Несмотря на то, что настольные платформы становятся все менее популярными, проблема потери файлов всегда оставалась.