إذا كنت تبني أداة داخلية، أو عميلًا لقاعدة بيانات، أو عارضًا للسجلات، أو أي تطبيق سطح مكتب صغير أو متوسط، فابنه باستخدام Wails بدلًا من Electron. يجمع Wails بين واجهة خلفية (backend) مكتوبة بلغة Go وبين الـ webview الذي يأتي مع نظام التشغيل أصلًا، لذلك يخرج التطبيق الفارغ بحجم يقارب 8 إلى 11 MB بدلًا من 295 إلى 384 MB (مقارنة Elanis، 2026). تحتفظ بواجهتك الأمامية المبنية بتقنيات الويب وتستبدل Node بلغة Go. ويتحول اتصال IPC المكتوب يدويًا إلى روابط (bindings) مولّدة تلقائيًا، ولا تحتاج إلى تضمين Chromium لأن نظام التشغيل يوفر الـ webview. مع ذلك لا يفوز Wails في كل اختبار أداء، وفي بعض التطبيقات يبقى Electron الخيار الأفضل.
الخلاصة
- الحجم هو المكسب الواضح. في اختبار أداء على CI لتطبيقات فارغة، جاءت بنيات Wails أصغر من بنيات Electron بما بين 30 و40 مرة على Windows وmacOS وLinux (مقارنة Elanis، 2026).
- الذاكرة وسرعة الإقلاع ليستا انتصارًا كاملًا. استهلك Wails ذاكرة أقل على macOS وLinux، لكنه استهلك أكثر على Windows. وفي الاختبار نفسه أقلع Electron أسرع على أنظمة التشغيل الثلاثة.
- المكاسب الأكبر بنيوية. تشحن ملفًا تنفيذيًا واحدًا بلغة Go، وتكتب الواجهة الخلفية بالمكتبة القياسية لـ Go وبالـ goroutines، وتستدعيها عبر روابط مولّدة ذات أنواع محددة، ولا يعمل Node داخل الصفحة.
- تتوقف عن ملاحقة الإصدارات الرئيسية من Electron. يصدر Electron إصدارًا رئيسيًا جديدًا كل 8 أسابيع ولا يدعم إلا أحدث ثلاثة منها (Electron، 2026). مع Wails، يُرقَّع الـ webview خارج تطبيقك: عبر أداة تحديث Evergreen WebView2 على Windows (Microsoft Learn، 2026)، وعبر تحديثات macOS، وعبر حزم توزيعة Linux التي تستخدمها.
- يبقى Electron الخيار الصحيح عندما تحتاج إلى عرض Chromium متطابق في كل مكان، أو تعتمد على وحدات Node الأصلية (native modules)، أو لديك أصلًا قاعدة كود Electron كبيرة.
ماذا يشحن Electron مع كل تطبيق؟
كل تطبيق Electron يشحن متصفحه الخاص وبيئة تشغيل JavaScript خاصة به. يقول توثيق Electron: «من خلال تضمين Chromium وNode.js في ملفه التنفيذي، يتيح لك Electron الحفاظ على قاعدة كود JavaScript واحدة» عبر المنصات (توثيق Electron، 2026). كانت هذه المقايضة منطقية حين كان البديل ثلاث قواعد كود أصلية. لكنها تعني أيضًا أن كل تطبيق تثبّته يحمل نسخة كاملة من Chromium.
نموذج العمليات مأخوذ من Chromium أيضًا. هناك عملية رئيسية واحدة تشغّل Node.js، إضافة إلى «عملية عرض (renderer) منفصلة لكل BrowserWindow مفتوحة (ولكل محتوى ويب مضمّن)» (نموذج العمليات في Electron، 2026). يعيش منطق الواجهة الخلفية في العملية الرئيسية، وتعيش واجهة المستخدم في عمليات العرض، وتربط بينهما برسائل IPC تكتبها بيدك.
ويبقى جدول الإصدارات. «الفاصل بين الإصدارات الرئيسية في Electron هو 8 أسابيع»، ولا يُدعم إلا أحدث ثلاثة إصدارات رئيسية مستقرة (الجداول الزمنية لـ Electron، 2026). صدر Electron 44.0.0 بنسخته المستقرة في 25 أغسطس 2026، مع Chromium M152 وNode v24.18.1. ومن المقرر صدور Electron 45 في 20 أكتوبر 2026 (إصدارات Electron، 2026). ولكي تصل إصلاحات Chromium الأمنية إلى مستخدميك، عليك أن تواصل شحن بنيات جديدة وفق هذا الجدول.
كيف يعمل Wails؟
يصف Wails نفسه بأنه «بديل خفيف وسريع لـ Electron مخصص لـ Go» (توثيق Wails، 2026). وبدلًا من تضمين متصفح، فإنه «يعيد استخدام محرك العرض الأصلي للمنصة». ويقول ملف README: «يستخدم محركات عرض أصلية، بلا متصفح مضمّن!» (Wails على GitHub، 2026). ويختلف المحرك حسب نظام التشغيل:
- Windows يعرض واجهتك عبر Microsoft WebView2.
- macOS يعرضها عبر WebKit.
- Linux يعرضها عبر WebKitGTK.
تطبيق Wails هو «تطبيق Go عادي، مع واجهة أمامية مبنية على webkit» (كيف يعمل Wails، 2026). تُضمَّن واجهتك الأمامية (React أو Svelte أو Vue أو HTML عادي) داخل الملف التنفيذي لـ Go باستخدام //go:embed، فيُشحن التطبيق كله كملف تنفيذي واحد.
الجسر بين النصفين هو الخيار Bind، الذي «يحدد أيّ توابع الـ struct تُعرض للواجهة الأمامية». عندما تشغّل wails dev، يقرأ Wails هذه التوابع ويولّد أغلفة JavaScript مع تصريحات TypeScript. تستدعي واجهتك الأمامية توابع Go كما لو كانت دوال غير متزامنة (async). ولدفع البيانات في الاتجاه المعاكس، تُطلق Go أحداث وقت التشغيل وتستمع إليها JavaScript.
الإصدار v2 من Wails هو الخط المستقر، وقد صدر v2.14.0 في 10 أغسطس 2026 (إصدارات Wails، 2026). المشروع مرخص برخصة MIT ولديه نحو 36.3k نجمة على GitHub. ومن التطبيقات المبنية عليه Tiny RDM، وهي واجهة رسومية لـ Redis لديها نحو 13k نجمة (Tiny RDM، 2026)، وعميل gRPC المسمى Wombat (معرض Wails، 2026).
Wails مقابل Electron: كم يصغر حجم التطبيق وكم يخف؟
يصغر كثيرًا، لكنه لا يخف دائمًا. أفضل الأرقام المنشورة تأتي من مقارنة Elanis لأطر تحويل الويب إلى سطح المكتب، والتي تبني تطبيقًا فارغًا بكل إطار في وضع الإصدار على GitHub CI، وتقيس الحجم والذاكرة وزمن الإقلاع. وقد حُدّثت في 4 سبتمبر 2026 (مقارنة Elanis، 2026).

| المقياس | نظام التشغيل | Electron | Wails | Tauri |
|---|---|---|---|---|
| حجم البنية | Windows x64 | ~384 MB | ~11 MB | ~3 MB |
| حجم البنية | macOS arm64 | ~319 MB | ~8 MB | ~5 MB |
| حجم البنية | Linux x64 | ~295 MB | ~9 MB | ~4 MB |
| الذاكرة | Windows x64 | ~278 MB | ~323 MB | ~317 MB |
| الذاكرة | macOS arm64 | ~369 MB | ~100 MB | ~95 MB |
| الذاكرة | Linux x64 | ~586 MB | ~360 MB | ~94 MB |
| زمن الإقلاع | Windows x64 | ~206 ms | ~559 ms | ~711 ms |
| زمن الإقلاع | macOS arm64 | ~640 ms | ~1,740 ms | ~2,044 ms |
| زمن الإقلاع | Linux x64 | ~204 ms | ~263 ms | ~30,325 ms |
المصدر: Elanis web-to-desktop-framework-comparison، حُدّث في 2026-09-04. تطبيق فارغ، بنية إصدار، على GitHub CI. قارن بين الأطر داخل نظام التشغيل نفسه فقط. لا يذكر ملف README إصدارات الأطر.
في الحجم يفوز Wails بلا منازع. التطبيق الفارغ في Wails أصغر من نظيره في Electron بنحو 35 مرة على Windows، و40 مرة على macOS، و33 مرة على Linux. على اتصال فندقي بطيء، تُحمَّل 11 MB في ثوانٍ بينما تستغرق 384 MB دقائق. ويتراكم الفرق حين تحمل كل أداة على الحاسوب المحمول نسختها الخاصة من Chromium.
أما الذاكرة فتتوقف على نظام التشغيل. على macOS، استهلك Wails ذاكرة أقل من Electron بنحو 3.7 مرات. وعلى Linux استهلك أقل بنحو 1.6 مرة. أما على Windows فاستهلك أكثر، نحو 323 MB مقابل 278 MB لـ Electron. لا يفصّل الاختبار سبب ذلك، لكن WebView2 يستخدم محرك Microsoft Edge المبني على Chromium، ويشغّل عمليات متصفح خاصة به. لذلك يُرجَّح أنك ما زلت تدفع ثمن محرك Chromium في الذاكرة على Windows، حتى وإن لم تشحنه مع تطبيقك.
وفي هذا الاختبار أقلع Electron أسرع على كل الأنظمة. على Windows أقلع في نحو 206 ms مقابل 559 ms لـ Wails. وعلى macOS كانت الفجوة 640 ms مقابل 1,740 ms. وعلى Linux تقارب الاثنان، 204 ms مقابل 263 ms. تطبيق فارغ على جهاز CI مؤشر تقريبي، ولن يطابق ما يراه مستخدموك. ومع ذلك، لا تدعم البيانات الادعاء بأن Wails يقلع أسرع دائمًا.
تحفّظ أخير يخص Windows. تحتاج تطبيقات Wails إلى Microsoft WebView2 Runtime. وهو يأتي مع Windows 11، وتقول Microsoft إن «الغالبية العظمى من أجهزة Windows 10 مثبّت عليها WebView2 Runtime مسبقًا» (Microsoft Learn، 2026). ويغطي تضمين أداة التمهيد (bootstrapper) بقية الأجهزة، ويضيف نحو 150 KB (دليل Wails لـ Windows، 2026). أما إذا احتجت إلى محرك بإصدار مثبّت، فإن Microsoft تحذّر من أن «ملفات Fixed Version يتجاوز حجمها 250 MB، وستزيد حزمة تطبيقك بهذا المقدار». وهذا يمحو معظم ميزة الحجم على Windows.
كيف يبدو كود Wails؟
إليك عارض سجلات صغيرًا قد تبنيه لفريقك: تختار ملف سجل، فيعرض آخر 200 سطر، ثم يبث الأسطر الجديدة فور كتابتها. كما يرسل طلب فحص إلى نقطة الصحة (health endpoint) لخدمة ما. كل ذلك يعمل في Go، والواجهة الأمامية تكتفي بالعرض.
جانب Go عبارة عن struct عادي بتوابع مُصدَّرة. يقرأ TailLog ملفًا باستخدام os وbufio. ويستدعي CheckHealth نقطة HTTP مع مهلة زمنية باستخدام net/http، وهو ما تغطيه دورة HTTP. يُترجم الكود أدناه بنجاح مع Wails v2.14.0:
example.gogo// app.go package main import ( "bufio" "context" "fmt" "net/http" "os" "sync" "time" ) const tailLines = 200 type App struct { ctx context.Context mu sync.Mutex stopFollow context.CancelFunc } func NewApp() *App { return &App{} } // startup is called by Wails once the app is running. Keep the context: // runtime calls like EventsEmit need it. func (a *App) startup(ctx context.Context) { a.ctx = ctx } // TailLog returns the last 200 lines of the log file at path. func (a *App) TailLog(path string) ([]string, error) { f, err := os.Open(path) if err != nil { return nil, fmt.Errorf("open log: %w", err) } defer f.Close() lines := make([]string, 0, tailLines) sc := bufio.NewScanner(f) sc.Buffer(make([]byte, 0, 64*1024), 1024*1024) // allow long JSON log lines for sc.Scan() { if len(lines) == tailLines { lines = lines[1:] } lines = append(lines, sc.Text()) } if err := sc.Err(); err != nil { return nil, fmt.Errorf("read log: %w", err) } return lines, nil } // CheckHealth calls a service's health endpoint and returns the status code. func (a *App) CheckHealth(url string) (int, error) { ctx, cancel := context.WithTimeout(a.ctx, 3*time.Second) defer cancel() req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { return 0, fmt.Errorf("build request: %w", err) } resp, err := http.DefaultClient.Do(req) if err != nil { return 0, fmt.Errorf("health check %s: %w", url, err) } defer resp.Body.Close() return resp.StatusCode, nil }
تضمّن main الواجهة الأمامية المبنية وتسلّم الـ struct إلى Bind. يوجد Wails v2 في المسار github.com/wailsapp/wails/v2:
example.gogo// main.go package main import ( "embed" "log" "github.com/wailsapp/wails/v2" "github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options/assetserver" ) //go:embed all:frontend/dist var assets embed.FS func main() { app := NewApp() err := wails.Run(&options.App{ Title: "Log Viewer", Width: 1100, Height: 720, AssetServer: &assetserver.Options{ Assets: assets, }, OnStartup: app.startup, Bind: []interface{}{app}, }) if err != nil { log.Fatal(err) } }
شغّل wails dev وسيولّد Wails الملفين frontend/wailsjs/go/main/App.js وApp.d.ts. تبدو التصريحات هكذا:
example.tstsexport function TailLog(arg1: string): Promise<Array<string>>; export function CheckHealth(arg1: string): Promise<number>;
كل تابع مربوط يعيد Promise. وإذا أعاد تابع Go قيمة error غير nil، يُرفض الـ Promise بها. لذلك تستخدم الواجهة الأمامية await وtry/catch العاديين:
example.tstsimport { TailLog, CheckHealth } from "../wailsjs/go/main/App"; async function openLog(path: string) { try { const lines = await TailLog(path); renderLines(lines); } catch (err) { showError(`Could not read ${path}: ${err}`); } } async function refreshStatus(url: string) { try { const status = await CheckHealth(url); setStatus(status === 200 ? "healthy" : `HTTP ${status}`); } catch (err) { setStatus(`down: ${err}`); } }
لا تحتاج إلى مزامنة أسماء القنوات بين الطرفين ولا إلى التحقق من شكل الرسائل يدويًا. غيّر توقيع تابع في Go وسيتغير التصريح المُعاد توليده معه، فتكشف بنية الواجهة الأمامية التي تمر بفحص الأنواع الاستدعاءات القديمة.
بث الأسطر الجديدة عبر أحداث وقت التشغيل
متابعة ملف حي هي الموضع الذي يفيد فيه التزامن في Go. ينتقل FollowLog إلى نهاية الملف، ثم تفحص goroutine الملف دوريًا بحثًا عن أسطر جديدة وتدفع كل سطر إلى الواجهة الأمامية عبر runtime.EventsEmit. وفتح ملف آخر يلغي المتابع السابق:
example.gogo// follow.go package main import ( "bufio" "context" "fmt" "io" "os" "strings" "time" "github.com/wailsapp/wails/v2/pkg/runtime" ) // FollowLog streams lines appended to path as "log:line" events. func (a *App) FollowLog(path string) error { f, err := os.Open(path) if err != nil { return fmt.Errorf("open log: %w", err) } if _, err := f.Seek(0, io.SeekEnd); err != nil { f.Close() return fmt.Errorf("seek log: %w", err) } a.mu.Lock() if a.stopFollow != nil { a.stopFollow() } ctx, cancel := context.WithCancel(a.ctx) a.stopFollow = cancel a.mu.Unlock() go a.follow(ctx, f) return nil } func (a *App) follow(ctx context.Context, f *os.File) { defer f.Close() r := bufio.NewReader(f) var partial strings.Builder ticker := time.NewTicker(500 * time.Millisecond) defer ticker.Stop() for { select { case <-ctx.Done(): return case <-ticker.C: for { chunk, err := r.ReadString('\n') partial.WriteString(chunk) if err != nil { break // no complete line yet, try again on the next tick } line := strings.TrimRight(partial.String(), "\r\n") runtime.EventsEmit(a.ctx, "log:line", line) partial.Reset() } } } }
في الواجهة الأمامية، اشترك مرة واحدة عبر EventsOn:
example.tstsimport { FollowLog } from "../wailsjs/go/main/App"; import { EventsOn } from "../wailsjs/runtime/runtime"; EventsOn("log:line", (line: string) => appendLine(line)); await FollowLog("/var/log/payments-api/app.log");
في Electron ستكتب الميزة نفسها باستخدام fs في العملية الرئيسية، وipcMain.handle للقراءة، وwebContents.send لكل سطر جديد، وسكربت preload يعرض الاثنين عبر contextBridge. أما في Wails فهي struct واحد في Go واسم حدث واحد. هذه النسخة لا تتعامل مع تدوير السجلات (log rotation). المتابع الجاهز لبيئة الإنتاج يعيد فتح الملف عندما يتقلص حجمه.
يغيّر Wails v3 الشكل قليلًا. تسجّل الخدمات في application.Options.Services باستخدام application.NewService(&LogService{})، وتستورد الواجهة الأمامية الكود المولّد من مجلد bindings بدلًا من wailsjs (الروابط في Wails v3، 2026). وتبقى توابع أنواع Go هي ما تستدعيه الواجهة الأمامية.
كيف يختلف نموذج الأمان؟
يعتمد أمان Electron على قائمة تحقق، بينما يبدأ Wails بمساحة هجوم أصغر. يطلب منك دليل الأمان الخاص بـ Electron أن تُبقي تكامل Node معطّلًا للمحتوى البعيد (وهو الافتراضي منذ 5.0.0)، وأن تُبقي عزل السياق (context isolation) مفعّلًا (افتراضي منذ 12.0.0)، وأن تُبقي عزل العمليات في صندوق رمل (sandboxing) مفعّلًا (افتراضي منذ 20.0.0)، وأن تتحقق من مُرسل كل رسالة IPC، وأن تضبط سياسة أمان المحتوى (Content Security Policy)، وألا تعرض واجهات برمجية للصفحة إلا عبر contextBridge (الأمان في Electron، 2026).
هذه الإعدادات الافتراضية جيدة الآن، لكن كل واحد منها خيار يستطيع كودك تعطيله. ولأن كل تطبيق يضمّن Chromium، تبقى ثغرة المتصفح في تطبيقك المثبّت إلى أن تشحن تحديثًا مبنيًا على Electron مُرقَّع.
يزيل Wails عدة بنود من هذه القائمة بحكم تصميمه. لا يوجد Node.js في الصفحة، فلا يوجد nodeIntegration يمكن أن يُضبط خطأً. تحصل الصفحة على توابع Go التي ربطتها، إضافة إلى واجهة Wails البرمجية لوقت التشغيل، ولا شيء آخر من النظام المضيف. لا تستطيع قراءة الملفات أو تشغيل العمليات إلا إذا فعل ذلك أحد توابعك. ولأن الـ webview ملك لنظام التشغيل، تصل إصلاحاته الأمنية عبر WebView2 runtime ذاتي التحديث من نوع Evergreen على Windows، أو عبر تحديثات macOS، أو عبر حزم توزيعة Linux لديك، لا عبر خط الإصدار الخاص بك. أما إذا ثبّت إصدارًا من نوع Fixed Version على Windows، فتعود مسؤولية الترقيع إليك.
تبقى بعض المخاطر. كل تابع مربوط هو واجهة برمجية، والصفحة التي تستدعيه قد تعرض محتوى لا تتحكم فيه. في عارض السجلات أعلاه، يقبل TailLog أي مسار. فإذا عرض تطبيقك يومًا HTML غير موثوق، يصبح ذلك أداة جاهزة لقراءة الملفات. تحقّق من المُعاملات في Go بالطريقة نفسها التي تتحقق بها من مُدخلات معالج HTTP: قيّد المسارات بمجلدات مسموح بها، والعناوين بمضيفين معروفين. وتبقى سياسة CSP مهمة أيضًا، لأن الصفحة ما زالت قادرة على إرسال طلبات شبكة مثل أي صفحة في المتصفح.
وللسؤال المرتبط حول ما يمكن لاعتمادية Node أن تفعله وقت التثبيت، اقرأ هل Go أكثر أمانًا من Node.js في مواجهة هجمات سلسلة التوريد؟.
أين يكلّفك Wails؟
يستبدل Wails متصفحًا واحدًا مضمّنًا بثلاثة webviews مختلفة، ولهذا ثمن. تنبّه Microsoft إلى أنه مع Evergreen WebView2 Runtime عليك إعداد اختبارات للتوافق المستقبلي، لأن المحرك يتحدّث تلقائيًا بمعزل عن تطبيقك (Microsoft Learn، 2026). وعلى macOS أنت تستهدف WebKit، المحرك الذي يقف خلف Safari، لذا اختبر هناك أي CSS أو واجهة ويب برمجية لم تتحقق منها إلا في Chrome.
Linux هي المنصة الأكثر خشونة. يسرد دليل Wails لـ Linux مشكلات معروفة: حدث الفيديو ended لا يُطلق بسبب خلل في WebKitGTK، وقد تظهر لك الرسالة "GStreamer element autoaudiosink not found"، كما أن «WebKit يثبّت معالجات إشارات تتعارض مع آلية Go للتعافي من الـ panic» (دليل Wails لـ Linux، 2026). وهناك أيضًا انقسام في الـ ABI. تحتاج Debian 11 وUbuntu 20.04 وRHEL من 8 إلى 9 إلى WebKitGTK 4.0 القديم، فتختار بين وسمي البناء webkit2_41 وwebkit2_40 (دعم التوزيعات في Wails، 2026). وتبلّغ مشكلة في v3 من فبراير 2026 عن نافذة فارغة على X11 مع بطاقات Nvidia، ويُتجاوز الأمر باستخدام WEBKIT_DISABLE_DMABUF_RENDERER=1 (مشكلة Wails رقم 4985، 2026).
تكاليف أخرى ينبغي أن تعرفها:
- الإصدار v2 يدعم نافذة واحدة. يقول دليل الانتقال إلى v3 إن v2 «كان يدعم نافذة واحدة فقط لكل تطبيق»، بينما «يقدّم v3 دعمًا أصليًا لتعدد النوافذ كميزة أساسية» (دليل الانتقال من Wails v2 إلى v3، 2026).
- الإصدار v3 ما زال تجريبيًا. أحدث إصدار هو v3.0.0-beta.25 الصادر في 22 سبتمبر 2026. وتقول ملاحظات الإصدار: «الواجهة البرمجية مستقرة، لكنك قد تواجه مشكلات قبل صدور النسخة النهائية 3.0» (إصدارات Wails، 2026). ويضيف دليل الانتقال أن «v2 يبقى الإصدار المستقر الحالي».
- المنظومة أصغر. الإضافات أقل، وعندما تصادف خللًا غريبًا تقل احتمالية أن يكون أحد قد كتب الحل من قبل.
- توثيق الانتقال شحيح. صفحة «الانتقال من Electron» في توثيق v3 ما زالت حاليًا صفحة فارغة مؤقتة.
ماذا عن Tauri؟
Tauri هو الإطار الرئيسي الآخر المبني على الـ webview. يصف نفسه بأنه «إطار لبناء ملفات تنفيذية صغيرة وسريعة لكل منصات سطح المكتب والهواتف الرئيسية»، ويستخدم «الـ webview المتوفر أصلًا على نظام كل مستخدم»، وواجهته الخلفية مكتوبة بلغة Rust (Tauri، 2026). صدر Tauri 2.0 بنسخته المستقرة في 2 أكتوبر 2024 (مدونة Tauri، 2024).
في مقارنة Elanis، أنتج Tauri أصغر البنيات (نحو 3 إلى 5 MB) واستهلك أقل ذاكرة على Linux. لكنه سجّل أيضًا أبطأ زمن إقلاع على كل نظام تشغيل، بما في ذلك نحو 30 ثانية على جهاز CI العامل بنظام Linux. يتشارك Tauri وWails مقايضات الـ webview نفسها، لذا يعود الاختيار في الغالب إلى لغة الواجهة الخلفية. إذا كان فريقك يكتب Rust، فاستخدم Tauri. وإذا كان فريقك يكتب Go، فاستخدم Wails.
كيف تنقل تطبيق Electron إلى Wails؟
احتفظ بواجهتك الأمامية واستبدل العملية الرئيسية. لا يوجد لدى Wails حتى الآن دليل رسمي للانتقال من Electron، لذا خطّط للعمل بمطابقة كل جزء من Electron مع ما يقابله في Go:
| Electron | Wails (Go) |
|---|---|
ipcMain.handle + ipcRenderer.invoke عبر preload | تابع مُصدَّر على struct مربوط، يُستدعى من الروابط المولّدة |
fs | os، io، bufio، path/filepath |
child_process | os/exec |
fetch / axios في العملية الرئيسية | net/http مع مهلة زمنية عبر context |
webContents.send + ipcRenderer.on | runtime.EventsEmit + EventsOn |
electron-builder | wails build، مع -nsis لمُثبّت Windows |
ترتيب عملي للخطوات:
- انقل الواجهة الأمامية كما هي. وجّه Wails إلى مخرجات بناء Vite أو webpack الموجودة لديك. معظم المكونات لا تحتاج إلى تغيير. وحدها مواضع الاستدعاء التي تتحدث إلى واجهة preload تحتاج إلى ذلك، والخطوة 2 تتكفل بها.
- انقل قناة IPC واحدة في كل مرة. يصبح كل
ipcMain.handleتابعًا في Go. احذف مدخل preload المقابل وحوّل موضع الاستدعاء إلى الاستيراد المولّد. - استبدل الرسائل المدفوعة بالأحداث. كل ما يُرسل عبر
webContents.sendيصبحruntime.EventsEmit. - أعد بناء عملية التحزيم. يترجم
wails build«ملفًا تنفيذيًا جاهزًا لبيئة الإنتاج»، وتغطي خيارات مثل-nsisو-webview2و-platformبرامج التثبيت واستراتيجية WebView2 والبناء لمنصات أخرى (واجهة سطر أوامر Wails، 2026). ويغطي دليل التوقيع توثيق التطبيقات (notarization) على macOS وأداة SignTool على Windows، بما في ذلك GitHub Actions. - اختبر على الـ webviews الثلاثة. هذه الخطوة عمل جديد مقارنة بـ Electron، فخصص لها وقتًا في خطتك.
كود Go الذي تكتبه في الخطوة 2 هو في معظمه كود من المكتبة القياسية. إذا كانت os وnet/http وencoding/json جديدة عليك، فإن دورة HTTP ودورة تنسيقات البيانات تغطيان الأجزاء التي تستخدمها الواجهة الخلفية لتطبيق سطح مكتب.
أين يأتي دور LevelUpGo
يعتمد عارض السجلات أعلاه على أساسيات Go: الدوال، والقيم المُعادة المتعددة، ومعالجة الأخطاء، والمكتبة القياسية. تعلّمك دورة Go Basics على LevelUpGo هذه الأساسيات مع محرر حقيقي بجانب كل درس، ويجب أن يجتاز كودك الاختبارات قبل أن تنتقل إلى ما بعده. أما العمل مع goroutine وcontext في FollowLog فتغطيه دورة Concurrency Fundamentals. وحين تريد مزيدًا من التمرين، يوفر Training Ground تمارين مستقلة.
إذا كنت ما زلت تقرر ما إذا كانت Go تستحق وقتك، فابدأ بمقال هل تستحق Go التعلم في 2026؟. ولمعرفة أين تعمل Go في بيئة الإنتاج اليوم، اقرأ أين تُستخدم Go؟، ولجانب الخوادم اقرأ أفضل لغة برمجة لتطوير الواجهة الخلفية.
الأسئلة الشائعة
هل Wails أفضل من Electron؟
لمعظم تطبيقات سطح المكتب الصغيرة والمتوسطة، نعم. في مقارنة Elanis جاء تطبيق Wails الفارغ أصغر من تطبيق Electron بما بين 30 و40 مرة (مقارنة Elanis، 2026)، وتحصل على واجهة خلفية بلغة Go مع روابط ذات أنواع محددة. ويبقى Electron أفضل عندما تحتاج إلى عرض Chromium متطابق أو إلى وحدات Node الأصلية.
هل يستهلك Wails ذاكرة أقل من Electron؟
يتوقف ذلك على نظام التشغيل. في الاختبار نفسه، استهلك Wails نحو 100 MB مقابل 369 MB لـ Electron على macOS، و360 MB مقابل 586 MB على Linux. أما على Windows فاستهلك أكثر، نحو 323 MB مقابل 278 MB، على الأرجح لأن WebView2 يستخدم محرك Microsoft Edge المبني على Chromium ويشغّل عمليات متصفح خاصة به.
هل Wails جاهز لبيئة الإنتاج؟
الإصدار v2 من Wails هو الإصدار المستقر، وقد صدر v2.14.0 في 10 أغسطس 2026 (إصدارات Wails، 2026). وتعمل عليه تطبيقات مثل Tiny RDM. أما Wails v3 فما زال تجريبيًا. يقول توثيقه إن هناك تطبيقات تعمل به في بيئة الإنتاج، لكنه ينصح بالاختبار الشامل قبل النشر.
هل تعمل تطبيقات Wails على Windows 10؟
نعم، ما دام WebView2 Runtime مثبّتًا. تقول Microsoft إن الغالبية العظمى من أجهزة Windows 10 مثبّت عليها مسبقًا (Microsoft Learn، 2026). وللأجهزة الباقية، يستطيع Wails تضمين أداة تمهيد (bootstrapper) أو تنزيل الـ runtime وقت التثبيت باستخدام خيار البناء -webview2.
هل يمكنني الاحتفاظ بواجهة React الأمامية عند الانتقال إلى Wails؟
نعم. يقدّم Wails أي واجهة أمامية ويب مبنية من ملفات مضمّنة داخل الملف التنفيذي لـ Go، لذا تعمل React وVue وSvelte وHTML العادي كلها. ما يتغير هو طريقة تواصل الواجهة الأمامية مع الواجهة الخلفية. تتحول استدعاءات IPC إلى استيراد دوال مولّدة، وتتحول الرسائل المدفوعة إلى أحداث وقت التشغيل.
المصادر
- Elanis، web-to-desktop-framework-comparison (حُدّث في 2026-09-04)
- Wails، Introduction
- Wails على GitHub
- Wails، How does it work?
- إصدار Wails v2.14.0
- إصدار Wails v3.0.0-beta.25
- Wails v3، Migrating from v2
- Wails v3، Binding methods
- مرجع واجهة سطر أوامر Wails
- دليل التوقيع في Wails
- دليل Wails لـ Windows
- دليل Wails لـ Linux
- دعم توزيعات Linux في Wails
- مشكلة Wails رقم 4985، نافذة فارغة على Linux X11 مع Nvidia
- معرض Wails
- Tiny RDM
- Microsoft Learn، Distribute your app and the WebView2 Runtime
- توثيق Electron
- Electron، Process model
- Electron، Release timelines
- جدول إصدارات Electron
- Electron، Security checklist
- معرض تطبيقات Electron
- Tauri، Start
- إعلان Tauri 2.0 (2024)
