ホームページ > ウェブフロントエンド > CSSチュートリアル > Svelte、Redis、およびRustを使用したクロスプラットフォームデスクトップアプリケーションの構築方法

Svelte、Redis、およびRustを使用したクロスプラットフォームデスクトップアプリケーションの構築方法

Joseph Gordon-Levitt
リリース: 2025-03-21 11:14:11
オリジナル
903 人が閲覧しました

Svelte、Redis、およびRustを使用したクロスプラットフォームデスクトップアプリケーションの構築方法

CloudFlareは、グローバルに複製されたキー価値ストレージレイヤーであるWorkers KVと呼ばれる優れた製品を提供しています。何百万ものキーを処理できます。各キーは、リクエストがどこから来ても、ワーカースクリプトの非常に低いレイテンシでアクセスできます。労働者KVは驚くべきものです。寛大な無料層を含む価格も販売されています。

しかし、CloudFlare製品ラインの長期ユーザーとして、私は1つのことが欠けていることを発見しました:ローカルの内省。私は多くの場合、アプリケーションに数千または数十のキーを持っています。すべてのデータを照会したり、並べ替えたり、実際に存在するものを確認する方法を望んでいることがよくあります。

最近、CloudFlareに参加することができました!さらに重要なことは、「クイックウィークウィーク」(別名The Weekly Hackathon)の前にこの四半期に参加しました。私は十分な仕事のバックログを蓄積していないので(まだ)、私を信じてください、私は自分の願いを満たすためにこの機会をつかむでしょう。

ポイントに戻って、Svelte、Redis、Rustを使用して構築されたクロスプラットフォームのデスクトップアプリケーションであるWorkers KV GUIをどのように構築したかを教えてください。

フロントエンドアプリケーション

Web開発者として、これはおなじみのリンクです。私はそれを「単純な部分」と呼びたいと思っていますが、すべてのHTML、CSS、JavaScriptフレームワーク、ライブラリ、またはパターンを使用できることを考えると、麻痺を選択するのは簡単です。あなたが好きなフロントエンドの技術スタックを持っているなら、それは素晴らしい、それを使ってください!このアプリでは、Svelteを使用することを選択しました。私にとっては、本当にシンプルになり、シンプルに保つからです。

さらに、Web開発者として、私たちはすべてのツールを携帯したいと考えています。もちろんできます!繰り返しますが、プロジェクトのこのフェーズは、典型的なWebアプリケーション開発サイクルと変わりません。 Yarn Dev(またはいくつかのバリアント)を主なコマンドとして実行し、自宅で感じることが期待できます。 「シンプルな」テーマを維持するために、Sveltekit、Svelteの公式フレームワークとツールキットを使用するためのツールキットを使用することにしました。最適化されたビルドシステム、優れた開発者エクスペリエンス(HMR!を含む!)、ファイルシステムベースのルーター、およびSvelte自体が提供するすべての機能が含まれます。

フレームワーク、特に自分でツールを処理するものとして、Sveltekitは自分のアプリケーションとそのニーズについて純粋に考えることができます。実際、構成に関して私がする必要がある唯一のことは、クライアントでのみ実行される単一ページアプリケーション(SPA)を構築したいことをSveltekitに伝えることです。言い換えれば、ほとんどのアプリケーションがサーバー側のレンダリングの恩恵を受けることができるため、実際には合理的な仮定であるサーバーが必要だと仮定して、Sveltekitを明示的にオプトアウトする必要があります。これは、この目的のために特別に作成された構成プリセットである @Sveltejs/Adapter-Staticパッケージを添付するのと同じくらい簡単です。インストール後、私の構成ファイル全体が次のようになります:

 <code>// svelte.config.js import preprocess from 'svelte-preprocess'; import adapter from '@sveltejs/adapter-static'; /** @type {import('@sveltejs/kit').Config} */ const config = { preprocess: preprocess(), kit: { adapter: adapter({ fallback: 'index.html' }), files: { template: 'src/index.html' } }, }; export default config;</code>
ログイン後にコピー

index.htmlの変更は私の個人的な好みです。 SveltekitはApp.htmlをデフォルトの基本テンプレートとして使用しますが、古い習慣を変更することは困難です。

わずか数分で、私のツールチェーンは、スパを構築していることをすでに知っていて、すでにルーターの準備ができていて、開発サーバーを利用できるようになりました。さらに、TypeScript、PostCSS、および/またはSASSサポートも、必要に応じてSvelte-Preprocessが原因で利用できます(そして私はそれが必要です)。準備ができて!

アプリケーションには2つのビューが必要です。

  1. 接続の詳細を入力する画面(デフォルト/ウェルカム/ホームページ)
  2. 実際にデータを表示する画面

Sveltekitの世界では、これは2つの「ルーター」に翻訳されます。これは、SveltekitがこれらのルートがSRC/ROTES/INDEX.SVELTE(ホームページ)およびSRC/ルート/Viewer.Svelte(データビューアーページ)として存在することを規定しています。実際のWebアプリケーションでは、2番目のルートが /Viewer URLにマッピングされます。これはまだ当てはまりますが、デスクトップアプリケーションにはナビゲーションバーがないことを知っています。つまり、URLは目に見えないことを意味します...それが私にとって理にかなっている限り、このルートにどのように名前を付けるかは関係ありません。

少なくともこの記事では、これらのファイルの内容はほとんど無関係です。好奇心が強い人のために、プロジェクト全体がオープンソースであり、SvelteまたはSveltekitの例を探している場合は、チェックアウトできます。レコードが壊れているリスクがあるため、ここでのポイントは、私が通常のWebアプリケーションを構築していることです。

この時点で、私は自分の意見をデザインし、有効に見えるものを手に入れるまで、偽の、ハードコーディングされたデータを投げます。私はすべてが美しく見え、すべてのインタラクティブ(ボタンクリック、フォームの提出など)が完成するまで約2日間ここに滞在しました。私はそれを「実行可能な」アプリケーションまたはモデルと呼びます。

デスクトップアプリケーションツール

現時点では、完全に機能的なスパがすでに存在しています。 Webブラウザで実行され、Webブラウザで開発されています。おそらく直感に反して、これはデスクトップアプリケーションの完璧な候補になります!しかし、それをする方法は?

あなたは電子のことを聞いたことがあるかもしれません。これは、Webテクノロジーを使用してクロスプラットフォームデスクトップアプリケーションを構築するための最も有名なツールです。それで構築された非常に人気のある成功したアプリケーションがたくさんあります:Visual Studio Code、WhatsApp、Atom、Slackなど。独自のChromiumインストールと独自のnode.jsランタイムでWebリソースをバンドルすることで機能します。言い換えれば、電子ベースのアプリケーションをインストールすると、追加のクロムブラウザとプログラミング言語の完全なセット(node.js)が付属しています。これらはアプリケーションコンテンツに組み込まれており、アプリケーションの依存関係であり、どこでも一貫して実行されることを保証するため、避けることはできません。ご想像のとおり、このアプローチにはいくつかのトレードオフがあります。アプリケーションは非常に大きく(つまり、100MBを超える)、多くのシステムリソースを使用して実行します。アプリを使用するには、背景は新しい/個別のクロムを実行します。これは、新しいタブを開くのとまったく同じではありません。

幸いなことに、いくつかの選択肢があります。私はSvelte NodeguiとTauriを評価しました。どちらのオプションも、Chromeのコピーを埋め込むのではなく、オペレーティングシステムが提供するネイティブレンダラーに依存することにより、大幅なアプリケーションサイズと使用率の節約を提供します。 Nodeguiは、ネイティブビューにコンパイルされた別のデスクトップ/GUIアプリケーションフレームワークであるQTに依存することにより、これを行います。ただし、これを行うには、NodeguiがコンポーネントQTコンポーネントに変換できるように、アプリケーションコードにいくつかの調整を行う必要があります。私はこれが確かに機能すると信じていますが、私は自分のスベルトファイルを調整せずに自分が知っていることを正確に使用したいので、このソリューションには興味がありません。対照的に、タウリは、オペレーティングシステムのネイティブWebViewerをラッピングすることで節約を達成します。たとえば、MacOSのCocoa/WebKit、Linux上のGTK-Webkit2、WindowsのEdgeでWebKit。 WebViewersは実際にはブラウザであり、Tauriはそれらが既にあなたのシステムに存在するため、それらを使用しています。つまり、当社のアプリケーションは純粋にWeb開発製品を維持できることを意味します。

これらの節約により、最小のタウリアプリは4MB未満で、平均アプリの重量は20MB未満です。私のテストでは、最小のNodeGUIアプリケーションの重量は約16MBです。最小の電子アプリケーションは、120MBに簡単に到達できます。

言うまでもなく、私はタウリを選びました。 Tauri Integration Guideに従うことで、 @Tauri-Apps/CLIパッケージを開発者に追加し、プロジェクトを初期化しました。

 <code>yarn add --dev @tauri-apps/cli yarn tauri init</code>
ログイン後にコピー

これにより、SRCディレクトリの横にSRC-Tauriディレクトリが作成されます(Svelteアプリケーションが配置されている場所)。これは、すべてのタウリ固有のファイルが配置されている場所であり、組織に最適です。

Tauriアプリを作成したことはありませんが、構成ドキュメントを見た後、Package.ProductNameやWindows.Title値などのアイテムを除き、ほとんどのデフォルト値を維持することができます。実際、私が行う必要がある唯一の変更は、開発および出力情報のためにSveltekitと整合する必要があるビルド構成です。

 <code>// src-tauri/tauri.conf.json { "package": { "version": "0.0.0", "productName": "Workers KV" }, "build": { "distDir": "../build", "devPath": "http://localhost:3000", "beforeDevCommand": "yarn svelte-kit dev", "beforeBuildCommand": "yarn svelte-kit build" }, // ... }</code>
ログイン後にコピー

Distdirは、構築された生産対応資産の場所に関連しています。この値はtauri.conf.jsonファイルの場所から解析されるため、../プレフィックスがあります。

DevPathは、開発中にプロキシされるURLです。デフォルトでは、Sveltekitはポート3000で開発サーバー(設定可能)を生成します。最初のフェーズでは、ブラウザでLocalHost:3000アドレスにアクセスしているので、これも例外ではありません。

最後に、タウリには独自の開発とコマンドの構築があります。複数のコマンドやスクリプトの構築の手間を避けるために、タウリはbeforedevevcommandとbeforebuildcommandフックを提供し、タウリコマンドが実行される前に任意のコマンドを実行できるようにします。これは微妙だが強力な利便性です!

Sveltekit CLIは、Svelte-Kitバイナリ名からアクセスできます。たとえば、Yarn Svelte-Kitビルドを書くと、YarnにローカルSvelte-Kitバイナリを取得するように指示し(Dev依存性を介してインストール)、SveltekitにBuildコマンドを実行するように指示します。

これにより、ルートレベルのパッケージ。JSONには次のスクリプトが含まれています。

 <code>{ "private": true, "type": "module", "scripts": { "dev": "tauri dev", "build": "tauri build", "prebuild": "premove build", "preview": "svelte-kit preview", "tauri": "tauri" }, // ... "devDependencies": { "@sveltejs/adapter-static": "1.0.0-next.9", "@sveltejs/kit": "1.0.0-next.109", "@tauri-apps/api": "1.0.0-beta.1", "@tauri-apps/cli": "1.0.0-beta.2", "premove": "3.0.1", "svelte": "3.38.2", "svelte-preprocess": "4.7.3", "tslib": "2.2.0", "typescript": "4.2.4" } }</code>
ログイン後にコピー

統合後、私の生産コマンドはまだYarnビルドであり、Tauri Buildを呼び出して実際にデスクトップアプリケーションをバンドルするように呼びますが、Yarn Svelte-Kitビルドが正常に完了した後にのみ(BeforeBuildCommandオプションを介して)。私の開発コマンドはまだYarn Devであり、Tauri DevとYarn Svelte-Kit Devコマンドを並行して実行します。開発ワークフローは完全にタウリアプリケーション内にあり、現在はLocalHost:3000をプロキシできており、HMR開発サーバーの利点を引き受けることができます。

重要:タウリは執筆時点でまだベータ版です。とはいえ、それは非常に安定していて、よく計画されていると感じています。私はプロジェクトとは関係ありませんが、タウリ1.0はおそらくすぐに安定したバージョンになるでしょう。タウリメンテナーからの返信を含め、タウリの不一致が非常に活発で親切であることがわかりました!彼らは、プロセス全体を通して私の錆の初心者の質問のいくつかにさえ答えました。 :)

Redisに接続します

この時点で、それは水曜日の午後の速い勝利の週でした、そして、私は金曜日のチームのデモの前にそれを終えることに正直に緊張し始めました。なぜ?私は週の半分を過ごしてきたので、たとえ実行可能なデスクトップアプリケーション見栄えの良いスパを持っていても、それはまだ何もしません。私は一週間、同じ偽のデータを見てきました。

WebViewにアクセスできるため、Fetch()を使用して、必要なワーカーKVデータに対して認証されたREST API呼び出しを作成し、すべてをローカルストレージまたはIndexEdDBテーブルに捨てることができると思うかもしれません。ただし、これはデスクトップアプリケーションのユースケースに関する私のアイデアではありません。

すべてのデータを何らかのブラウザー内のストレージに保存することは完全に実行可能ですが、機械にローカルに保存します。これは、チームメンバーが同じことをしようとする場合、誰もが自分のマシン上のすべてのデータを取得して保存する必要があることを意味します。理想的には、このワーカーKVアプリケーションには、外部データベースに接続して同期するオプションが必要です。このようにして、チームのセットアップで作業するとき、誰もが同じデータベースキャッシュに調整して時間を節約できます。これは、数百万のキーを扱うときに重要になり始めます。これは、前述のように、労働者kvを使用する場合は珍しくありません。

しばらくの間それについて考えた後、私はRedisをバックエンドストレージとして使用することにしました。これは重要な価値ストアでもあるためです。 Redisはすでにキーを一流の市民として扱っており、私が望むソートとフィルタリングの動作を提供するので、これは素晴らしいことです(つまり、自分で実装するのではなく作業に合格することができます!)。その後、もちろん、Redisはローカルまたはコンテナで簡単にインストールして実行できます。誰かがそのルートに行くことを選択した場合、サービスプロバイダーとしてホストされたRedisがたくさんあります。

しかし、どうすればそれに接続できますか?私のアプリは基本的にSvelteを実行しているブラウザタグですよね?はい - しかし、それ以上のものです。

ご覧のとおり、Electronの成功の一部は、はい、Webアプリケーションがすべてのオペレーティングシステムでうまくレンダリングされることを保証することですが、Node.jsランタイムももたらします。 Web開発者として、それは私のクライアントに直接バックエンドAPIを含めるようなものです。基本的に、「...しかし、私のマシンで実行されます」という問題は、すべてのユーザー(無意識)がまったく同じローカルホスト設定を実行しているために消えます。 node.jsレイヤーを介して、ファイルシステムと対話したり、複数のポートでサーバーを実行したり、node_modulesの束を含めることができます。強力なもの。

私たちはタウリを使用しているので、この超大国を失うことはありません!それは同じですが、わずかに異なります。

Node.jsランタイムを含める代わりに、タウリアプリケーションは低レベルのシステム言語であるRustを使用して構築されます。これは、タウリ自体がオペレーティングシステムと相互作用し、ネイティブのWebViewerを「借用」する方法です。すべてのタウリツールキットは(Rust経由で)コンパイルされており、構築されたアプリケーションを小さく効率的に保ちます。ただし、これは、アプリケーション開発者である私たちが、構築されたアプリケーションに他のクレート(「NPMモジュール」と同等)を含めることができることも意味します。もちろん、労働者KV GUIがRedisインスタンスに接続できるようにするRedisクライアントドライバーとして機能する、名前のあるRedis Crateもあります。

さびにおいて、Cargo.TOMLファイルはPackage.jsonファイルに似ています。これは、依存関係とメタデータが定義される場所です。タウリのセットアップでは、src-tauri/cargo.tomlにあります。これも、タウリに関連するすべてがこのディレクトリにあるためです。貨物には、依存関係レベルで定義された「機能フラグ」の概念もあります。 (私が考えることができる最も近い類推は、npmを使用してモジュールの内部構造または名前付きサブモジュールのインポートにアクセスすることですが、錆びると、機能フラグがパッケージの構築方法に影響するため、まったく同じではありません。)

 <code># src-tauri/Cargo.toml [dependencies] serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.0.0-beta.1", features = ["api-all", "menu"] } redis = { version = "0.20", features = ["tokio-native-tls-comp"] }</code>
ログイン後にコピー

上記は、Redis Crateを依存関係として定義し、「Tokio-Native-TLS-Comp」関数を選択します。これは、TLSサポートに必要なドキュメントが述べています。

わかりました、だから私はついに必要なものすべてを持っています。水曜日が終わる前に、私のレディスと私のスベルートの話をしなければなりません。周りを見回した後、私はすべての重要なことがSRC-Tauri/main.rsファイルで起こっているように見えることに気付きました。私は#[コマンド]マクロを書き留めましたが、その日のタウリの例で以前にそれを見たことがあることを知っているので、サンプルファイルのさまざまな部分をコピーして、どのバグが表示されているかを確認して錆びたコンパイラに従って消えることを学びました

最終的に、Tauriアプリは再び実行することができ、#[コマンド]マクロが基礎となる関数を何らかの形でラップして、「コンテキスト」値(それらを使用することを選択した場合)を受信し、事前に比較されたパラメーター値を受信できるようにしました。さらに、言語として、Rustは多くのタイプ変換を実行します。例えば:

 <code>use tauri::{command}; #[command] fn greet(name: String, age: u8) { println!("Hello {}, {} year-old human!", name, age); }</code>
ログイン後にコピー

これにより、Greetコマンドが作成され、実行されると、名前と年齢の2つのパラメーターが期待されます。定義すると、名前値は文字列値であり、年齢はU8データ型、つまり整数です。ただし、両方が欠落している場合、タウリはエラーをスローします。これは、コマンドの定義が何もオプションであると述べていないためです。

タウリコマンドをアプリケーションに実際に接続するには、メイン関数内にあるタウリ::ビルダーの組み合わせの一部として定義する必要があります。

 <code>use tauri::{command}; #[command] fn greet(name: String, age: u8) { println!("Hello {}, {} year-old human!", name, age); } fn main() { // start composing a new Builder chain tauri::Builder::default() // assign our generated "handler" to the chain .invoke_handler( // piece together application logic tauri::generate_handler![ greet, // attach the command ] ) // start/initialize the application .run( // put it all together tauri::generate_context!() ) // print<message> if error while running .expect("error while running tauri application"); }</message></code>
ログイン後にコピー

タウリアプリケーションはコンパイルし、「挨拶」コマンドがあることを知っています。また、WebViewを制御しています(すでに説明しました)が、そうすることで、Tauri APIと書いた他のコード(Greet Commandsなど)で構成される現在の端(WebViewコンテンツ)とバックエンドの間のブリッジとして機能します。タウリでは、2つの世界が互いに通信できるように、橋の間にメッセージを送信できます。

フロントエンドは、任意の(既に含まれている) @tauri-appsパッケージから機能をインポートするか、window.tauriグローバル変数(クライアントアプリケーション全体に使用できる)に依存することにより、この「ブリッジ」にアクセスできます具体的には、コマンド名とパラメーターのセットを受け入れるInvokeコマンドに興味があります。引数がある場合、キーが錆機能が期待するパラメーター名と一致するオブジェクトとして定義する必要があります。

SVELTEレイヤーでは、これを行うことで、錆層で定義されている挨拶コマンドを呼び出すことができます。

 <code>function onclick() { __TAURI__.invoke('greet', { name: 'Alice', age: 32 }); } Click Me</code>
ログイン後にコピー

このボタンがクリックされると、ターミナルウィンドウ(タウリ開発コマンドが実行される場所)が印刷されます。

 <code>Hello Alice, 32 year-old human!</code>
ログイン後にコピー

繰り返しますが、これはprintln!このコードがまだ錆/システム側で実行されているため、ターミナルのコンソールウィンドウ(ブラウザコンソールではありません)に表示されます。

また、Tauriコマンドからクライアントにコンテンツを送信することも可能です。そのため、挨拶をすばやく変更しましょう。

 <code>use tauri::{command}; #[command] fn greet(name: String, age: u8) { // implicit return, because no semicolon! format!("Hello {}, {} year-old human!", name, age) } // OR #[command] fn greet(name: String, age: u8) { // explicit `return` statement, must have semicolon return format!("Hello {}, {} year-old human!", name, age); }</code>
ログイン後にコピー

私が何度も呼び出して、少し怠zyであることに気づいて、私はこれらを統合するために軽量のクライアントアシスタントを抽出しました:

 <code>// @types/global.d.ts ///<reference types="@sveltejs/kit"></reference> type Dict<t> = Record<string t=""> ; declare const __TAURI__: { invoke: typeof import('@tauri-apps/api/tauri').invoke; } // src/lib/tauri.ts export function dispatch(command: string, args: Dict<string> ) { return __TAURI__.invoke(command, args); }</string></string></t></code>
ログイン後にコピー

次に、以前のGreeter.svelteを次のようにリファクタリングします。

 <code>import { dispatch } from '$lib/tauri'; async function onclick() { let output = await dispatch('greet', { name: 'Alice', age: 32 }); console.log('~>', output); //=> "~> Hello Alice, 32 year-old human!" } Click Me</code>
ログイン後にコピー

素晴らしい!したがって、木曜日であり、Redisコードをまだ書いていませんが、少なくともアプリケーションの脳の2つの半分を一緒に接続する方法を知っています。イベントハンドラーのすべてのTODOを交換し、実際のコンテンツに接続する時が来ました。

ここからは非常にアプリケーション固有のものあるため、ここで詳細を省略します。さらに、詳細を探索することが、プロジェクトがオープンソースである理由です!

高レベルでは、指定された詳細でRedis接続が確立されると、 /Viewerルートで同期ボタンにアクセスできます。このボタンがクリックされた場合(およびその時だけ- コストのために)、JavaScript関数が呼び出されます。これは、CloudFlare Rest APIに接続し、各キーの「Redis_set」コマンドをディスパッチする責任があります。このRedis_setコマンドは、すべてRedisベースのコマンドと同様に、さびた層で定義され、実際にRedisにキー価値のペアを書き込む責任があります。

Redisからデータを読むことは非常によく似たプロセスです。たとえば、 /視聴者が起動するとき、すべてのキーをリストして準備ができている必要があります。 Svelte用語では、 /Viewerコンポーネントがインストールされているときにタウリコマンドをスケジュールする必要があることを意味します。これはここでほとんど逐語的に起こります。さらに、サイドバーのキー名をクリックすると、有効期限(もしあれば)、メタデータ(存在する場合)、および実際の値(既知の場合)など、キーに関する「詳細」がさらに「詳細」に表示されます。コストとネットワークの負荷を最適化するために、必要に応じてキーの値のみを取得する必要があると判断しました。これにより、リフレッシュボタンが導入されます。このボタンは、クリックしたときに残りのAPIと再び対話し、コマンドをスケジュールしてRedisクライアントがキーを個別に更新できるようにします。

私は急いでやろうとはしていませんが、JavaScriptとRustコードの間に相互作用が成功したら、すべての相互作用が表示されます!私の木曜日と金曜日の朝の残りの部分は、新しいリクエストの繰り返しペアを定義するだけです。

結論は

私にとって - 私は他の多くのJavaScript開発者にとってそうだと思います - 今週の課題は錆を学ぶことです。私はあなたがこれを以前に聞いたことがあると思います、そしてあなたは将来間違いなくそれを再び聞くでしょう。所有権のルール、借入小切手、およびシングルキャラクター構文マーカーの意味(これらのマーカーは、簡単に検索することはできません)は、私が遭遇したほんのいくつかの障害です。タウリ・ディスコードの助けと親切に再び感謝します!

これはまた、タウリを使用することは挑戦ではないことを意味します。それは大きな安reliefです。将来、タウリを再び使用することを計画していると確信しています。特に、必要に応じてWebViewerを使用できることがわかっている場合はそうです。さびセクションを掘り下げたり/または追加することは「余分な素材」であり、アプリケーションが必要な場合にのみ必要です。

知りたい人のために、私はそれを言及する別の場所を見つけることができないので、macosでは、労働者KV GUIアプリの重量は13 MB未満です。この結果にとても興奮しています!

もちろん、Sveltekitもこのスケジュールを可能にします。ツールベルトの構成の半日を節約しただけでなく、インスタントHMR開発サーバーは、ブラウザを手動でリフレッシュする数時間、そしてタウリビューアを節約するかもしれません。

あなたがここでそれを見たなら、それは印象的です!あなたの時間と注意をどうもありがとうございました。リマインダーとして、プロジェクトはGitHubで利用でき、最新のプリコンパイルされたバイナリはいつでも公開ページから入手できます。

以上がSvelte、Redis、およびRustを使用したクロスプラットフォームデスクトップアプリケーションの構築方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート