मुख्य सामग्री पर जाएँ

डेस्कटॉप ऐप

यह पृष्ठ अंग्रेज़ी से अनुवादित है। अंग्रेज़ी पृष्ठ पढ़ें

Zeyn ऐप एक डेस्कटॉप एक्ज़ीक्यूटेबल के रूप में भेजा जा सकता है। zeyn-desktop crate प्रक्रिया के भीतर ऐप का अपना सर्वर शुरू करता है और उसे सिस्टम WebView के ज़रिए नेटिव विंडो में दिखाता है:

प्लेटफ़ॉर्मWebViewस्थिति
Windows 10 और 11WebView2 (Edge)बना और हाथ से जाँचा गया
macOSWKWebViewwry से कंपाइल होता है, हाथ से जाँचा नहीं गया
LinuxWebKitGTK 4.1libwebkit2gtk-4.1-dev और libgtk-3-dev इंस्टॉल होने पर wry से कंपाइल होता है, हाथ से जाँचा नहीं गया

कुछ भी मशीन से बाहर नहीं जाता। ऐप ऑफ़लाइन काम करता है जब तक वह खुद दूरस्थ सेवाओं को कॉल नहीं करता।

इस्तेमाल करें

crate को feature के पीछे जोड़ें, ताकि सामान्य सर्वर बिल्ड WebView कंपाइल न करे:

[features]
desktop = ["dep:zeyn-desktop"]

[dependencies]
zeyn-desktop = { version = "0.0.2", optional = true }

App::serve की जगह विंडो शुरू करें:

#[cfg(feature = "desktop")]
fn main() -> std::io::Result<()> {
    zeyn_desktop::Desktop::new(app()?)
        .id("my-app")
        .title("My App")
        .size(1280, 800)
        .run()
}
  • id प्रति उपयोगकर्ता डेटा फ़ोल्डर को नाम देता है और प्रति id एक इंस्टेंस रखता है। डिफ़ॉल्ट रूप से यह एक्ज़ीक्यूटेबल का नाम है।
  • title तब तक दिखता है जब तक पृष्ठ document.title सेट न करे; उसके बाद विंडो का शीर्षक पृष्ठ का पालन करता है।
  • size लॉजिकल पिक्सेल में पहला आकार है। बाद के लॉन्च आखिरी आकार और स्थिति दोबारा इस्तेमाल करते हैं।

run विंडो बंद होने तक रुकता है, सर्वर रोकता है और प्रक्रिया खत्म करता है। ZEYN_DESCRIBE=1 के साथ यह ऐप का विवरण छापता है और लौट आता है, इसलिए zeyn check और zeyn routes काम करते रहते हैं।

Windows पर रिलीज़ बिल्ड की कंसोल विंडो छिपाने के लिए main.rs के शीर्ष पर यह रखें:

#![cfg_attr(all(feature = "desktop", not(debug_assertions)), windows_subsystem = "windows")]

examples/adisyon पूरा उदाहरण है, एक पॉइंट ऑफ़ सेल ऐप:

cargo run -p zeyn-example-adisyon --features desktop

एक्ज़ीक्यूटेबल बनाएँ

cd my-app
zeyn build-desktop                    # same as --features desktop
zeyn build-desktop --package my-app --features desktop,postgres

यह लिंक टाइम ऑप्टिमाइज़ेशन, एक codegen यूनिट और स्ट्रिप किए सिंबल के साथ cargo build --release चलाता है, फिर हर एक्ज़ीक्यूटेबल का पथ और आकार छापता है। गति opt-level = 3 पर रहती है।

आइकन, संस्करण जानकारी और मैनिफ़ेस्ट (Windows)

Windows ये exe के भीतर के संसाधनों से पढ़ता है। एक बिल्ड स्क्रिप्ट जोड़ें जो इन्हें केवल डेस्कटॉप बिल्ड के लिए एम्बेड करे:

[features]
desktop = ["dep:zeyn-desktop", "dep:winresource"]

[build-dependencies]
winresource = { version = "0.1", optional = true, default-features = false }

build.rs:

fn main() {
    #[cfg(feature = "desktop")]
    if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("windows") {
        let mut res = winresource::WindowsResource::new();
        res.set_icon("assets/app.ico")
            .set("ProductName", "My App")
            .set("FileDescription", "My App")
            .set_manifest_file("assets/app.exe.manifest");
        res.compile().unwrap();
    }
}

आइकन का रिसोर्स आईडी 1 होना चाहिए (set_icon का डिफ़ॉल्ट); विंडो और टास्कबार इसे इस्तेमाल करते हैं। संस्करण package.version से आता है। प्रति मॉनिटर DPI जागरूकता, UTF-8 और common controls 6 वाले मैनिफ़ेस्ट के लिए examples/adisyon/build.rs और examples/adisyon/assets देखें। MSVC टूलचेन rc.exe Windows SDK में खोजता है; GNU टूलचेन windres इस्तेमाल करता है।

WebView2 रनटाइम

Windows 11 और मौजूदा Windows 10 में WebView2 रनटाइम पहले से इंस्टॉल होता है और अपने आप अपडेट होता है (evergreen रनटाइम)। exe उसे बंडल नहीं करता, जो उसे छोटा रखता है।

पुरानी या लॉक की गई मशीनों के लिए:

  • Microsoft का evergreen बूटस्ट्रैपर (MicrosoftEdgeWebview2Setup.exe, लगभग 2 MB) अपने इंस्टॉलर के साथ भेजें और जब रनटाइम छूटा हो तो उसे /silent /install से चलाएँ। यह रनटाइम एक बार डाउनलोड करता है।
  • बिना इंटरनेट वाली मशीनों के लिए evergreen standalone इंस्टॉलर (बड़ा, ऑफ़लाइन) इस्तेमाल करें, या exe के पास रखा fixed version रनटाइम। fixed version अपने आप अपडेट नहीं होता, इसलिए उसके सुरक्षा अपडेट आपकी ज़िम्मेदारी हैं।

रनटाइम के बिना विंडो नहीं खुल सकती और run त्रुटि लौटाता है।

सुरक्षा मॉडल

सर्वर केवल ऐप की अपनी विंडो से पहुँच योग्य है।

  • केवल loopback। श्रोता सिस्टम के चुने पोर्ट पर 127.0.0.1 से बँधता है। यह कभी 0.0.0.0 या LAN पते से नहीं बँधता।
  • लॉन्च टोकन। हर लॉन्च एक यादृच्छिक 256 बिट टोकन बनाता है। विंडो पहले /_desktop/start?t=<token> खोलती है, जो टोकन को HttpOnly, SameSite=Strict कुकी के रूप में सेट करता है और / पर रीडायरेक्ट करता है। हर दूसरे अनुरोध को वह टोकन उस कुकी में या x-zeyn-desktop हेडर में रखना होगा, वरना उसे 403 मिलता है। स्थिर एसेट भी सुरक्षित हैं। टोकन केवल मेमोरी में रहता है और constant time में तुलना होता है।
  • Host और Origin। Host हेडर ठीक 127.0.0.1:<port> होना चाहिए, जो DNS rebinding रोकता है (जिस साइट का नाम 127.0.0.1 पर हल होता है वह होस्ट के रूप में अपना नाम भेजती है)। Origin हेडर, जब मौजूद हो, ठीक http://127.0.0.1:<port> होना चाहिए। दोनों हर पथ पर लागू हैं, start और focus एंडपॉइंट समेत।
  • अन्य स्थानीय प्रोग्राम पोर्ट से जुड़ सकते हैं लेकिन टोकन नहीं जानते। अन्य उपयोगकर्ता खाते प्रति उपयोगकर्ता डेटा फ़ोल्डर की instance फ़ाइल नहीं पढ़ सकते।
  • नेविगेशन। विंडो केवल अपना origin, अपने blob: URL और about:blank दिखाती है। http, https और mailto लिंक सिस्टम के डिफ़ॉल्ट हैंडलर में खुलते हैं; हर अन्य स्कीम (file:, कस्टम प्रोटोकॉल हैंडलर, javascript:) छोड़ दी जाती है। window.open कभी दूसरा WebView नहीं बनाता।
  • Devtools डिबग बिल्ड में चालू और रिलीज़ बिल्ड में बंद हैं।
  • डाउनलोड केवल ऐप के origin से अनुमत हैं और उपयोगकर्ता के Downloads फ़ोल्डर में जाते हैं, कभी फ़ाइल ओवरराइट किए बिना (orders.csv, orders (1).csv, ...)। लगातार कई डाउनलोड बिना प्रॉम्प्ट के अनुमत हैं। अन्य अनुमति अनुरोध (कैमरा, माइक्रोफ़ोन, क्लिपबोर्ड) WebView का सामान्य प्रॉम्प्ट पाते हैं।

जो चीज़ें गार्ड कवर नहीं करता:

  • उसी उपयोगकर्ता के रूप में चलने वाला प्रोग्राम प्रक्रिया की मेमोरी पढ़ सकता है या डिबगर जोड़ सकता है; कोई स्थानीय ऐप इससे अपना बचाव नहीं कर सकता।
  • WebView2 WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS एनवायरनमेंट वेरिएबल का सम्मान करता है, इसलिए जो उपयोगकर्ता के लिए एनवायरनमेंट वेरिएबल सेट कर सकता है वह रिमोट डिबगिंग चालू कर सकता है। वही उपयोगकर्ता, ऊपर वाली ही सीमा।
  • ऐप का अपना प्रमाणीकरण विंडो के भीतर अब भी लागू होता है। डेस्कटॉप बिल्ड में DevAuth मशीन पर बैठे किसी भी व्यक्ति को पूरा एक्सेस देता है।

व्यवहार

  • एकल इंस्टेंस। पहला लॉन्च instance (पोर्ट और एक अलग focus कुंजी) डेटा फ़ोल्डर में लिखता है। दूसरा लॉन्च कुंजी को /_desktop/focus पर पोस्ट करता है; पहली विंडो सामने आती है और दूसरी प्रक्रिया लगभग 150 ms में बाहर निकल जाती है। जब दो लॉन्च एक ही पल शुरू हों, दोनों खुल सकते हैं।
  • विंडो स्थिति। आकार, स्थिति और maximized फ़्लैग बंद करने पर window.json में सहेजे जाते हैं। जो सहेजी स्थिति अब किसी मॉनिटर पर नहीं है उसे अनदेखा किया जाता है।
  • शटडाउन। विंडो बंद करना WebView छोड़ता है, सर्वर को शालीनता से रोकता है (अधिकतम 2 सेकंड) और प्रक्रिया खत्म करता है। WebView प्रक्रियाएँ उसके साथ खत्म होती हैं।
  • डेटा फ़ोल्डर। Windows पर %LOCALAPPDATA%\<id>, macOS पर ~/Library/Application Support/<id>, Linux पर ~/.local/share/<id>। WebView प्रोफ़ाइल (कैश, local storage) उसके भीतर webview में रहती है, इसलिए exe Program Files जैसे केवल पढ़ने योग्य फ़ोल्डर से भी काम करता है।
  • कोई ट्रे आइकन नहीं। बिल्ट इन नहीं है।

आकार और मेमोरी

Windows 11 पर examples/adisyon के साथ मापा गया, रिलीज़ बिल्ड, WebView2 रनटाइम 156:

zeyn build-desktop exe6.72 MB (सादी रिलीज़ प्रोफ़ाइल के साथ 7.25 MB)
ऐप प्रक्रिया, निष्क्रिय4.3 MB निजी, 25.6 MB working set
ऐप प्रक्रिया और WebView2 प्रक्रियाएँ, निष्क्रिय7 प्रक्रियाएँ, लगभग 180 MB निजी, 370 MB working set
--disable-gpu के साथ वहीलगभग 114 MB निजी, 330 MB working set
दूसरा लॉन्च बाहर निकलने तकलगभग 130 ms

WebView हावी रहता है। अकेली उसकी GPU प्रक्रिया लगभग 88 MB रखती है। कम मेमोरी वाली मशीनों पर सरल Screen के लिए, सॉफ़्टवेयर रेंडरिंग की कीमत पर लगभग 65 MB बचाने के लिए exe को WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS=--disable-gpu के साथ शुरू करें (उदाहरण के लिए शॉर्टकट या लॉन्चर स्क्रिप्ट से)।