قائمة فحص لاختيار التصفية على الخادم أو على العميل بناءً على حجم البيانات، الكمون، الأذونات، والتخزين المؤقت، مع تجنّب تسريبات واجهة المستخدم أو البطء.

التصفية في واجهة المستخدم أكثر من مجرد صندوق بحث واحد. عادةً تشمل عدة إجراءات مرتبطة تغير ما يراه المستخدم: بحث نصي (الاسم، البريد الإلكتروني، رقم الطلب)، الواجهات المساندة (الحالة، المالك، نطاق التاريخ، العلامات)، والترتيب (الأحدث، الأعلى قيمة، آخر نشاط).
السؤال الأساسي ليس أي تقنية "أفضل". بل أين توجد مجموعة البيانات الكاملة، ومن المسموح له الوصول إليها. إذا استقبل المتصفح سجلات لا ينبغي للمستخدم رؤيتها، يمكن للواجهة أن تكشف بيانات حساسة حتى لو أخفيت بصريًا.
معظم النقاشات حول التصفية على الخادم مقابل العميل هي في الحقيقة ردود فعل على فشلين يلاحظهما المستخدم فورًا:
يوجد قضية ثالثة تسبب تقارير أخطاء لا تنتهي: النتائج غير المتسقة. إذا شغلت بعض الفلاتر على العميل وأخرى على الخادم، يرى المستخدمون أعدادًا وصفحات وإجماليات لا تتطابق. هذا يكسر الثقة بسرعة، خصوصًا في القوائم ذات التقسيم.
قاعدة عملية بسيطة: إن لم يكن مسموحًا للمستخدم الوصول إلى مجموعة البيانات الكاملة، فصفِّ على الخادم. إذا كان مسموحًا وكان حجم البيانات صغيرًا بما يكفي للتحميل بسرعة، يمكن أن تكون التصفية على العميل مقبولة.
التصفية هي فقط "أرني العناصر التي تطابق". السؤال هو أين يحدث المطابقة: في متصفح المستخدم (العميل) أم على الخادم.
التصفية على العميل تعمل في المتصفح. التطبيق يحمل مجموعة سجلات (غالبًا JSON)، ثم يطبق الفلاتر محليًا. قد تبدو فورية بعد تحميل البيانات، لكنها تنجح فقط عندما تكون مجموعة البيانات صغيرة بما يكفي للشحن وآمنة بما يكفي للعرض.
التصفية على الخادم تعمل على الواجهة الخلفية. يرسل المتصفح مدخلات الفلترة (مثل status=open, owner=me, createdAfter=Jan 1)، ويعيد الخادم النتائج المطابقة فقط. عمليًا، هذا عادةً واجهة برمجية تقبل الفلاتر، تبني استعلامًا لقاعدة البيانات، وتعيد قائمة مقسمة بالإضافة إلى الإجماليات.
نموذج ذهني بسيط:
التركيبات الهجينة شائعة. نمط جيد هو تطبيق الفلاتر "الكبيرة" على الخادم (الأذونات، الملكية، نطاق التاريخ، البحث)، ثم استخدام تبديلات صغيرة خاصة بالواجهة محليًا (إخفاء المؤرشف، شرائح العلامات السريعة، رؤية الأعمدة) دون طلب إضافي.
عادةً الانتماء للترتيب، التقسيم، والبحث يتشارك نفس القرار. فهي تؤثر على حجم الحمولة، شعور المستخدم، ونوع البيانات التي تكشفها.
ابدأ بالسؤال الأكثر واقعية: كم بيانات سترسل إلى المتصفح إذا صفّيت على العميل؟ إذا كانت الإجابة الصريحة "أكثر من بضعة شاشات" فستدفع ثمنه في وقت التحميل، واستخدام الذاكرة، وتباطؤ التفاعلات.
لا تحتاج تقديرات دقيقة. احصل فقط على رتبة الحجم: كم صفًا قد يرى المستخدم، وما هو الحجم المتوسط لكل صف؟ قائمة من 500 عنصر بحقول قصيرة مختلفة تمامًا عن 50,000 عنصر حيث كل صف يتضمن ملاحظات طويلة، نصًا غنياً، أو كائنات متداخلة.
السجلات العريضة هي قاتل الحمولة الصامت. يمكن أن تبدو الطاولة صغيرة بعدد الصفوف لكنها ثقيلة إذا احتوى كل صف على حقول كثيرة، سلاسل طويلة، أو بيانات منضمّة (جهة اتصال + شركة + آخر نشاط + عنوان كامل + علامات). حتى لو عرضت ثلاثة أعمدة فقط، الفرق غالبًا ما يُرسَل "لكل الاحتمالات" فتتضخم الحمولة.
فكر أيضًا في النمو. مجموعة بيانات مناسبة اليوم قد تصبح مؤلمة بعد بضعة أشهر. إن نمت البيانات بسرعة، اعتبر التصفية على العميل اختصارًا قصير الأجل وليس الخيار الافتراضي.
إرشادات سريعة:
النقطة الأخيرة مهمة لأكثر من الأداء. "هل يمكننا شحن مجموعة البيانات الكاملة إلى المتصفح؟" هو سؤال أمني أيضًا. إذا لم تكن الإجابة بنعم واثق، لا ترسلها.
غالبًا ما تفشل اختيارات التصفية على مستوى الشعور وليس الصواب. المستخدمون لا يقيسون بالمللي ثانية. يلاحظون التوقفات، الوميض، والنتائج التي تتغير أثناء الكتابة.
يمكن أن يختفي الوقت في أماكن مختلفة:
حدّد ما يعنيه "سريع بما فيه الكفاية" لهذه الشاشة. قد تحتاج قائمة عرض إلى كتابة سريعة وتصفح سلس، بينما صفحة تقرير يمكنها تحمل انتظار قصير طالما أن النتيجة الأولى تظهر بسرعة.
لا تحكم بناءً على واي فاي المكتب فقط. على الاتصالات البطيئة، قد تبدو التصفية على العميل رائعة بعد التحميل الأول، لكن ذلك التحميل الأول قد يكون الجزء البطيء. التصفية على الخادم تبقي الحمولة صغيرة، لكنها قد تشعر بالبطء إذا أطلقت طلبًا على كل ضغطة مفتاح.
صمم حول الإدخال البشري. استعمل debounce لطلبات الكتابة. للمجموعات الكبيرة، استخدم التحميل التقدمي حتى تظهر الصفحة شيئًا بسرعة وتظل سلسة أثناء التمرير.
يجب أن تقرر الأذونات نهج التصفية أكثر من السرعة. إذا استقبل المتصفح بيانات لا يُسمح للمستخدم رؤيتها، فلديك مشكلة بالفعل، حتى لو أخفيتها خلف زر معطّل أو عمود مطوي.
ابدأ بتسمية ما هو حساس في هذه الشاشة. بعض الحقول واضحة (البريد الإلكتروني، أرقام الهواتف، العناوين). أخرى سهلة التغافل عنها: الملاحظات الداخلية، التكلفة أو الهامش، قواعد التسعير الخاصة، درجات المخاطر، علامات المراجعة.
الفخ الكبير هو "نقوم بالتصفية على العميل لكن نظهر فقط الصفوف المسموح بها." هذا يعني أن مجموعة البيانات الكاملة قد تم تنزيلها. أي شخص يمكنه فحص استجابة الشبكة، فتح أدوات المطور، أو حفظ الحمولة. إخفاء الأعمدة في الواجهة ليس تحكمًا في الوصول.
التصفية على الخادم هي الافتراضي الأكثر أمانًا عندما تختلف التفويضات باختلاف المستخدم، خاصة عندما يمكن لمستخدمين مختلفين رؤية صفوف أو حقول مختلفة.
فحص سريع:
إذا كانت أي إجابة نعم، فاجعل التصفية واختيار الحقول على الخادم. أرسِل فقط ما يسمح للمستخدم برؤيته، وطبق نفس القواعد على البحث والفرز والتقسيم والتصدير.
مثال: في قائمة جهات اتصال CRM، يمكن للمندوبين رؤية حساباتهم فقط بينما يراها المديرون جميعها. إذا حمّل المتصفح كل جهات الاتصال وصفّى محليًا، لا يزال بإمكان المندوب استعادة الحسابات المخفية من الاستجابة. تمنع التصفية على الخادم ذلك بعدم إرسال تلك الصفوف أصلًا.
يمكن للتخزين المؤقت أن يجعل الشاشة تبدو فورية. يمكنه أيضًا أن يعرض الحقيقة الخاطئة. المفتاح هو تحديد ما يُسمح بإعادة استخدامه، ولماذا مدة، وما الأحداث التي يجب أن تمسحه.
ابدأ باختيار وحدة التخزين المؤقت. تخزين القائمة كاملة سهل لكن عادة ما يهدر العرض ويصبح قديمًا بسرعة. تخزين الصفحات يعمل جيدًا للتمرير اللا نهائي. تخزين نتائج الاستعلام (فلتر + فرز + بحث) دقيق، لكنه يمكن أن ينمو بسرعة إن جرب المستخدمون تركيبات كثيرة.
الحداثة مهمة في بعض المجالات أكثر من غيرها. إذا تغيرت البيانات بسرعة (مستويات المخزون، الأرصدة، حالة التوصيل)، حتى تخزين لمدة 30 ثانية قد يربك المستخدمين. إذا تغيرت البيانات ببطء (سجلات مؤرشفة، بيانات مرجعية)، فالمدة الأطول عادةً مقبولة.
خطط لإبطال التخزين قبل أن تبرمج. بجانب مرور الزمن، قرر ما الذي يجب أن يجبر على التحديث: الإنشاء/التحرير/الحذف، تغيّر الأذونات، الاستيراد أو الدمج بالجملة، انتقالات الحالة، تراجعات/تراجع، والمهام الخلفية التي تحدّث حقولًا يعتمد عليها الفلتر.
حدد أيضًا أين يعيش التخزين المؤقت. ذاكرة المتصفح تجعل التنقل للخلف/الأمام سريعًا، لكنها قد تسرّب بيانات عبر الحسابات إذا لم تُفهرس حسب المستخدم والمنظمة. التخزين المؤقت على الخادم أكثر أمانًا للأذونات والاتساق، لكنه يجب أن يشمل توقيع الفلتر الكامل وهوية المستدعي حتى لا تُخلط النتائج.
اعتبر الهدف غير قابل للتفاوض: يجب أن تبدو الشاشة سريعة دون تسريب بيانات.
معظم الفرق يتعرضون لنفس الأنماط: واجهة تبدو رائعة في العرض التوضيحي، ثم تكشف البيانات الحقيقية والأذونات وسرعات الشبكة العيوب.
الفشل الأكثر خطورة هو التعامل مع التصفية كمجرد عرض. إذا استقبل المتصفح سجلات لا ينبغي له الحصول عليها، فقد خسرت بالفعل.
سببان شائعان:
مثال: يجب أن يرى المتدربون فقط العملاء المحتملين في منطقتهم. إن أعاد API كل المناطق وكان القوائم تُصفى في React، يمكن للمتدربين استخراج القائمة الكاملة.
غالبًا ما يأتي البطء من افتراضات:
مشكلة دقيقة ومؤلمة هي عدم تطابق القواعد. إذا تعامل الخادم مع "البداية بـ" بشكل مختلف عن الواجهة، يرى المستخدمون أعدادًا لا تتطابق أو عناصر تختفي بعد التحديث.
قم بجولة نهائية بعقليتين: مستخدم فضولي ويوم شبكة سيئ.
اختبار بسيط: أنشئ سجلًا مقيدًا وتأكد أنه لا يظهر أبدًا في الحمولة أو الإجماليات أو التخزين المؤقت، حتى عند تصفية واسعة أو مسح الفلاتر.
تخيل CRM به 200,000 جهة اتصال. يمكن لمندوبي المبيعات رؤية حساباتهم فقط، المديرون يرون فريقهم، والمدراء الإداريون يرون كل شيء. الشاشة تحتوي بحثًا، فلاتر (حالة، مالك، آخر نشاط)، وفرزًا.
تفشل التصفية على العميل بسرعة هنا. الحمولة ثقيلة، التحميل الأول يصبح بطيئًا، وخطر تسريب البيانات مرتفع. حتى لو أخفت الواجهة الصفوف، المتصفح تلقى البيانات. كما تضع ضغطًا على الجهاز: مصفوفات كبيرة، فرز ثقيل، تكرار عمليات التصفية، استخدام ذاكرة عالي، وانهيارات على الهواتف القديمة.
نهج أكثر أمانًا هو التصفية على الخادم مع التقسيم. يرسل العميل خيارات الفلترة ونص البحث، ويعيد الخادم فقط الصفوف المصرح بها، مُفلترة ومرتبة بالفعل.
نمط عملي:
استثناء صغير حيث تكون التصفية على العميل مناسبة: بيانات صغيرة وثابتة. قائمة من 8 قيم لحقل "حالة جهة الاتصال" يمكن تحميلها مرة واحدة والتصفية محليًا بلا مخاطرة أو تكلفة كبيرة.
الفرق لا يُحرق عادةً لاختيار خاطئ مرة واحدة. يحترق عندما تختار خيارًا مختلفًا لكل شاشة، ثم تحاول إصلاح التسريبات والصفحات البطيئة تحت الضغط.
اكتب ملاحظة قرار قصيرة لكل شاشة مع الفلاتر: حجم مجموعة البيانات، تكلفة الإرسال، ما هو "السريع بما فيه الكفاية"، الحقول الحساسة، وكيف يجب أن تُخزن النتائج مؤقتًا (أو لا). أبقِ الخادم والواجهة متوافقين حتى لا تنتهي بـ"حقيقتين" للتصفية.
إذا كنت تبني الشاشات بسرعة في Koder.ai (koder.ai)، فالأفضل أن تقرر مسبقًا أي الفلاتر يجب فرضها على الواجهة الخلفية (الأذونات والوصول على مستوى الصف) وأي تبديلات صغيرة خاصة بالواجهة يمكن أن تبقى في طبقة React. هذا القرار عادةً يمنع أكثر عمليات إعادة الكتابة تكلفة لاحقًا.
افتراضيًا اختَر التصفية على الخادم عندما تختلف أذونات المستخدمين، أو تكون قاعدة البيانات كبيرة، أو تهمك اتساق الصفحات والإجماليات. استخدم التصفية على العميل فقط عندما تكون كامل البيانات صغيرة، آمنة للعرض، وسريعة للتحميل.
لأن كل ما يصل المتصفح يمكن تفقده. حتى لو أخفيت الصفوف في واجهة المستخدم، يمكن للمستخدمين رؤية البيانات في استجابات الشبكة أو في ذاكرة التطبيق أو التخزين المؤقت.
عادةً يحدث ذلك عندما ترسل كمية كبيرة من البيانات ثم تقوم بفرز/تصفية مصفوفات كبيرة على كل ضغطة مفتاح، أو عندما ترسل طلبًا على كل ضغطة دون تأخير (debounce). حافظ على أحجام الاستجابات صغيرة وتجنب العمل الثقيل عند كل تغيير إدخال.
احتفظ بمصدر واحد للحقيقة للفلترات “الحقيقية”: الأذونات، البحث، الفرز، والتقسيم يجب تطبيقها مجتمعة على الخادم. حدّد منطق الواجهة العميلية لتبديلات صغيرة فقط التي لا تغيّر مجموعة البيانات الأساسية.
يمكن أن يعرض التخزين المؤقت على العميل بيانات قديمة أو يسرّب بيانات عبر الحسابات إن لم يكن مفتاح التخزين مرتبطًا بهوية المستخدم. التخزين المؤقت على الخادم أكثر أمانًا للأذونات، لكن يجب أن يتضمن التوقيع الكامل للفِلتر وهوية المستدعي حتى لا تخلط النتائج.
اسأل سؤالين: كم صفًا قد يرى المستخدم عمليًا، وما حجم كل صف بالبايت؟ إذا لم تكن مرتاحًا لتحميله عبر اتصال جوال نموذجي أو على جهاز قديم، فحوّل التصفية إلى الخادم واستخدم التقسيم (pagination).
الخادم. عندما تغيّر الأدوار أو الفرق أو المناطق ما يمكن رؤيته، يجب أن يفرض الخادم وصول الصفوف والحقول. يجب أن يتلقى العميل فقط السجلات والحقول المسموح للمستخدم رؤيتها.
عرّف عقد الفِلاتر والفرز أولًا: الحقول المقبولة، الفرز الافتراضي، قواعد التقسيم، وكيف يتطابق البحث (حساسية لحالة الحروف، العلامات، التطابق الجزئي). ثم نفّذ نفس المنطق بثبات على الخادم واختبر تطابق الإجماليات والصفحات.
استخدم التأخير (debounce) لمنع طلبات على كل ضغطة، وأبقِ النتائج القديمة مرئية حتى وصول النتائج الجديدة لتقليل الوميض. اعتمد التقسيم أو التحميل التدريجي حتى يرى المستخدم شيئًا بسرعة دون انتظار استجابة ضخمة.
طبّق الأذونات أولًا، ثم الفلاتر والفرز، وأعد صفحة واحدة فقط مع عدّ إجمالي. تجنّب إرسال "حقول إضافية تحسبًا"، وتأكّد أن مفاتيح التخزين المؤقت تشمل user/org/role حتى لا يتلقى مندوب بيانات مخصصة لمدير.