نقطة
  • الرئيسية
  • الخدمات
  • من نحن
  • الكتابات
  • تسجيل الدخول
الكتابات/tutorial/2026/07
● Tutorial13 يوليو 2026·24 دقيقة

وضع Vapor في Vue 3.6: بناء تطبيق أسرع بدون DOM افتراضي

تعلّم كيفية استخدام وضع Vapor في Vue 3.6 لترجمة المكوّنات مباشرة إلى عمليات DOM دون المرور بالـ DOM الافتراضي. يغطي هذا الدرس العملي إعداد Vite، ومكوّنات vapor، ونظام التفاعلية الجديد، وعرض القوائم الضخمة، والتوافق مع المكوّنات التقليدية، وقياس المكاسب الحقيقية في الأداء.

AI Bot
AI Bot
Author
·EN · FR · AR

على مدى عقد كامل، كان الـ DOM الافتراضي (Virtual DOM) هو الثمن الذي ندفعه مقابل واجهات تصريحية. تكتب قالبًا، فيبني إطار العمل شجرة من كائنات JavaScript تصف الـ DOM، ثم يقارنها بالشجرة السابقة، ثم يطبّق الفروقات. الطريقة تعمل — لكنها تعني أن كل تحديث يخصّص كائنات جديدة، ويجتاز شجرة كاملة، ويقوم بعمل يتناسب مع حجم المكوّن لا مع حجم التغيير الفعلي.

يأتي وضع Vapor في Vue 3.6 باستراتيجية ترجمة بديلة تزيل هذه الطبقة الوسيطة. يُترجم مكوّن vapor إلى شيفرة JavaScript عادية تُنشئ عُقد الـ DOM مرة واحدة، ثم تحدّث فقط العُقد النصية والسمات ومعالجات الأحداث التي تعتمد على الحالة التفاعلية التي تغيّرت. لا شجرة افتراضية، ولا مقارنة، ولا إعادة تصيير على مستوى المكوّن.

والأجمل من ذلك: الوضع اختياري لكل مكوّن على حدة. لن تعيد كتابة تطبيقك. تضع العلامة على المكوّنات الموجودة في المسارات الساخنة — الجدول الضخم، وقائمة المؤشرات الحية، والقائمة الافتراضية — وتترك ما عداها كما هو.

في هذا الدرس ستبني "لوحة عمليات" حيّة تعرض آلاف الصفوف وتحدّثها عبر مؤقّت، أولًا بالوضع التقليدي ثم بوضع vapor، لترى الفرق بنفسك في أداة قياس الأداء.

المتطلبات المسبقة

قبل البدء، تأكد من توفر:

  • Node.js 20+ (أدوات Vue 3.6 تفترض بيئة تشغيل حديثة)
  • معرفة أساسية بـ Vue 3 — واجهة التركيب Composition API وref وcomputed وv-for
  • إلمام بـ Vite وسطر الأوامر
  • محرر شيفرة مع إضافة Vue - Official (Volar)

لست بحاجة إلى أي خبرة سابقة بالإشارات (signals) أو المترجمات أو بنية Vue الداخلية.

ما الذي ستبنيه

لوحة معلومات من صفحة واحدة تعرض جدولًا يضم 5000 نسخة خدمة، لكل منها حالة وقيمة زمن استجابة وشريط حِمل. يقوم مؤقّت بتعديل شريحة عشوائية من الصفوف كل 200 مللي ثانية. ستقوم بـ:

  1. تجهيز مشروع Vue 3.6 مع Vite وتفعيل مترجم vapor
  2. كتابة أول مكوّن vapor وفحص الشيفرة المُولّدة
  3. بناء جدول اللوحة وإخضاعه لضغط 5000 صف
  4. مزج مكوّنات vapor مع المكوّنات التقليدية عبر إضافة التوافق
  5. قياس كلفة التحديث في أدوات مطوّري Chrome وتفسير الأرقام

لماذا يكلّفك الـ DOM الافتراضي؟

تخيّل مكوّنًا يعرض صفًا واحدًا. في Vue التقليدي، أي تغيّر في الحالة يستدعي دالة التصيير من جديد. تُعيد هذه الدالة شجرة vnode جديدة: كائنات للصف، ولكل خلية، ولكل عقدة نصية. ثم يجتاز نظام التشغيل الشجرتين القديمة والجديدة بالتوازي، ويقارن الخصائص، ويرقّع الـ DOM الحقيقي حيث تختلف.

الترقيع النهائي في الـ DOM ضئيل جدًا. أما كل ما سبقه فهو عبء إضافي: تخصيص ذاكرة، ومخلفات للـ garbage collector، واجتياز شجرة يتناسب مع حجم قالب المكوّن.

يقلب وضع Vapor هذه المعادلة. المترجم يعرف مسبقًا، في وقت البناء، أي عقدة DOM بالضبط يغذّيها كل تعبير. لذلك يولّد شيفرة تربط ذلك التعبير بتلك العقدة مباشرة عبر تأثير تفاعلي. عندما تتغير row.latency، يُطلق تأثير واحد ويُكتب في عقدة نصية واحدة، ولا يُزار بقية الصف إطلاقًا.

ينتج عن ذلك أمران يفوقان في أهميتهما السرعة الخام:

  • زمن تشغيل أصغر. التطبيق المبني بالكامل على vapor لا يشحن مُصيّر الـ DOM الافتراضي أصلًا، ما يقلّص الحزمة الأساسية بشكل ملموس.
  • كلفة التحديث تتناسب مع التغيير لا مع القالب. صف يحتوي 40 ربطًا يكلّف في التحديث ما يكلّفه صف بثلاثة روابط، إذا كان الربط المتغيّر فعليًا واحدًا.

كما أعاد Vue 3.6 بناء نواة التفاعلية اعتمادًا على خوارزمية alien-signals، ما يخفّض كلفة المحاسبة الداخلية لكل تأثير — سواء كان vapor أم لا. الوضع التقليدي يستفيد أيضًا، لكن vapor هو ما يتيح لك تحصيل المكسب كاملًا.

الخطوة 1: إعداد المشروع

جهّز مشروع Vue جديدًا عبر Vite:

npm create vite@latest vapor-dashboard -- --template vue-ts
cd vapor-dashboard
npm install

تأكد من أنك على Vue 3.6 أو أحدث، وعلى نسخة إضافة تفهم vapor:

npm install vue@^3.6.0
npm install -D @vitejs/plugin-vue@latest vite@latest

تحقق مما حصلت عليه فعليًا — دعم vapor يعتمد على النسخ بدقة:

npm ls vue @vitejs/plugin-vue

الخطوة 2: تفعيل مترجم Vapor

ترجمة vapor هي راية (flag) في المترجم، وليست إضافة منفصلة. فعّلها في vite.config.ts:

// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
 
export default defineConfig({
  plugins: [
    vue({
      features: {
        // [!code highlight]
        vapor: true, // السماح للمكوّنات باختيار ترجمة vapor
      },
    }),
  ],
})

هذه الراية لا تحوّل كل مكوّن إلى vapor. هي فقط تخبر مترجم الـ SFC بأن يقبل علامة vapor على المكوّنات التي تطلبها. أي مكوّن لا تضع عليه العلامة يُترجم تمامًا كما في السابق، ولهذا يمكن التبنّي بشكل تدريجي.

الخطوة 3: أول مكوّن vapor

يختار المكوّن الانضمام بإضافة السمة vapor إلى وسم السكربت. أنشئ src/components/StatusBadge.vue:

<script setup vapor lang="ts">
const props = defineProps<{
  status: 'healthy' | 'degraded' | 'down'
}>()
 
const LABELS = {
  healthy: 'سليم',
  degraded: 'متدهور',
  down: 'متوقف',
} as const
</script>
 
<template>
  <span class="badge" :class="`badge--${props.status}`">
    {{ LABELS[props.status] }}
  </span>
</template>
 
<style scoped>
.badge {
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
}
.badge--healthy  { background: #dcfce7; color: #166534; }
.badge--degraded { background: #fef9c3; color: #854d0e; }
.badge--down     { background: #fee2e2; color: #991b1b; }
</style>

هذه هي كامل واجهة الانضمام: كلمة واحدة، vapor، في وسم السكربت. الخصائص وdefineProps والأنماط المعزولة وواجهة التركيب تعمل جميعها بالطريقة التي تعرفها.

هناك قاعدة صارمة يجب استيعابها: مكوّنات vapor تدعم واجهة التركيب حصريًا. واجهة الخيارات (Options API) بـ data() وmethods وmounted() مفهوم ينتمي إلى عصر الـ DOM الافتراضي وغير مدعوم داخل مكوّن vapor. إذا كانت قاعدة شيفرتك ما تزال تستخدمها، فببساطة تبقى تلك المكوّنات تقليدية — ولا مشكلة في ذلك.

فحص ما ولّده المترجم

هذه هي الخطوة التي تتخطاها أغلب الدروس، وهي التي تجعل فكرة vapor تتضح. اطلب من Vite إخراج الوحدة بعد التحويل:

npx vite build --mode development --minify false

ثم ابحث في ملف الإخراج عن مكوّنك. بدلًا من دالة render() تُعيد استدعاءات createElementVNode(...)، ستجد شيفرة إجرائية تُنشئ عنصر span، وتُدرج عقدة نصية، وتسجّل تأثير تصيير يكتب في تلك العقدة النصية تحديدًا عند تغيّر خاصية الحالة. شكل القالب مخبوز في المخرجات؛ ولا يبقى حيًّا سوى الأجزاء الديناميكية.

الخطوة 4: بناء صف اللوحة

الآن المكوّن الذي سيتعرض فعليًا للضغط. أنشئ src/components/InstanceRow.vue:

<script setup vapor lang="ts">
import StatusBadge from './StatusBadge.vue'
import type { Instance } from '../types'
 
const props = defineProps<{ instance: Instance }>()
 
const emit = defineEmits<{
  (e: 'restart', id: string): void
}>()
 
function loadColor(load: number): string {
  if (load > 85) return '#ef4444'
  if (load > 60) return '#f59e0b'
  return '#10b981'
}
</script>
 
<template>
  <tr>
    <td class="mono">{{ props.instance.id }}</td>
    <td>{{ props.instance.region }}</td>
    <td><StatusBadge :status="props.instance.status" /></td>
    <td class="mono">{{ props.instance.latency }} ms</td>
    <td>
      <div class="bar">
        <div
          class="bar__fill"
          :style="{
            width: props.instance.load + '%',
            background: loadColor(props.instance.load),
          }"
        />
      </div>
    </td>
    <td>
      <button @click="emit('restart', props.instance.id)">إعادة التشغيل</button>
    </td>
  </tr>
</template>
 
<style scoped>
.mono { font-family: ui-monospace, monospace; }
.bar {
  width: 120px;
  height: 6px;
  background: #e5e7eb;
  border-radius: 3px;
  overflow: hidden;
}
.bar__fill { height: 100%; transition: width 150ms linear; }
</style>

لاحظ أن StatusBadge — وهو نفسه مكوّن vapor — يُستخدم داخل مكوّن vapor آخر دون أي إجراءات إضافية. التركيب من vapor إلى vapor هو المسار السريع، والأفضل أن تستهدف تحويل أشجار فرعية كاملة بدل التناوب بين الوضعين.

عرّف النوع المشترك في src/types.ts:

export interface Instance {
  id: string
  region: string
  status: 'healthy' | 'degraded' | 'down'
  latency: number
  load: number
}

الخطوة 5: توليد البيانات وتحويرها

أنشئ src/composables/useInstances.ts. هذه واجهة تركيب عادية — لا شيء خاص بـ vapor، لأن نظام التفاعلية مشترك بين الوضعين:

import { shallowRef, onUnmounted } from 'vue'
import type { Instance } from '../types'
 
const REGIONS = ['tunis-1', 'paris-2', 'riyadh-1', 'dubai-3', 'frankfurt-1']
const STATUSES = ['healthy', 'healthy', 'healthy', 'degraded', 'down'] as const
 
function makeInstance(i: number): Instance {
  return {
    id: `svc-${String(i).padStart(5, '0')}`,
    region: REGIONS[i % REGIONS.length],
    status: STATUSES[i % STATUSES.length],
    latency: 20 + Math.floor(Math.random() * 180),
    load: Math.floor(Math.random() * 100),
  }
}
 
export function useInstances(count = 5000, tickMs = 200) {
  // shallowRef: نستبدل مرجع المصفوفة، ولا نتتبّع 5000 كائن بعمق
  const instances = shallowRef<Instance[]>(
    Array.from({ length: count }, (_, i) => makeInstance(i)),
  )
 
  // تحوير نحو 2% من الصفوف عند كل نبضة لمحاكاة تدفق حي
  const timer = setInterval(() => {
    const next = instances.value.slice()
    const churn = Math.max(1, Math.floor(count * 0.02))
 
    for (let n = 0; n < churn; n++) {
      const idx = Math.floor(Math.random() * next.length)
      const row = next[idx]
      next[idx] = {
        ...row,
        latency: 20 + Math.floor(Math.random() * 180),
        load: Math.floor(Math.random() * 100),
        status: STATUSES[Math.floor(Math.random() * STATUSES.length)],
      }
    }
 
    instances.value = next
  }, tickMs)
 
  onUnmounted(() => clearInterval(timer))
 
  return { instances }
}

استخدام shallowRef هنا مقصود. الوكلاء التفاعليون العميقون فوق 5000 كائن يكلّفون ذاكرة ووقت تهيئة في كلا وضعي التصيير؛ أما استبدال كائنات الصفوف بنسخ جديدة غير قابلة للتغيير فيبقي الرسم البياني التفاعلي سطحيًا، ويجعل روابط كل صف تُعاد تقييمها فقط عند تغيّر هوية كائنه.

الخطوة 6: تركيب الجدول

أنشئ src/components/InstanceTable.vue:

<script setup vapor lang="ts">
import { computed } from 'vue'
import InstanceRow from './InstanceRow.vue'
import { useInstances } from '../composables/useInstances'
 
const { instances } = useInstances(5000, 200)
 
const unhealthy = computed(
  () => instances.value.filter((i) => i.status !== 'healthy').length,
)
 
function onRestart(id: string) {
  console.info('restart requested', id)
}
</script>
 
<template>
  <header class="summary">
    <strong>{{ instances.length }}</strong> نسخة ·
    <strong>{{ unhealthy }}</strong> غير سليمة
  </header>
 
  <table>
    <thead>
      <tr>
        <th>المعرّف</th><th>المنطقة</th><th>الحالة</th>
        <th>زمن الاستجابة</th><th>الحِمل</th><th></th>
      </tr>
    </thead>
    <tbody>
      <InstanceRow
        v-for="instance in instances"
        :key="instance.id"
        :instance="instance"
        @restart="onRestart"
      />
    </tbody>
  </table>
</template>

تتصرف v-for و:key وcomputed وإطلاق الأحداث بشكل مطابق تمامًا لما تعرفه. و:key ليست اختيارية هنا — فتوفيق القوائم في vapor يعتمد عليها لإعادة استخدام كتل الـ DOM التي بناها للهويات الثابتة.

الخطوة 7: تركيب تطبيق vapor

للتطبيق الذي يكون جذره وأبناؤه كلهم vapor، ركّبه عبر createVaporApp، وهي دالة لا تستدعي مُصيّر الـ DOM الافتراضي إطلاقًا:

// src/main.ts
import { createVaporApp } from 'vue'
import App from './App.vue'
import './style.css'
 
createVaporApp(App).mount('#app')

عندها يحتاج App.vue إلى علامة vapor خاصة به:

<script setup vapor lang="ts">
import InstanceTable from './components/InstanceTable.vue'
</script>
 
<template>
  <main>
    <h1>لوحة العمليات</h1>
    <InstanceTable />
  </main>
</template>

شغّل التطبيق:

npm run dev

من المفترض أن ترى 5000 صف، مع تذبذب أزمنة الاستجابة وأشرطة الحِمل بينما يقوم المؤقّت بتحويرها.

الخطوة 8: التوافق مع المكوّنات التقليدية

في الواقع العملي لن تحوّل كل شيء. لديك نافذة حوار من نظام التصميم، وغلاف لمكتبة رسوم بيانية، ومكوّن خارجي من npm — وكلها مكوّنات DOM افتراضي تقليدية. يدعم Vue مزج الوضعين، لكن يجب تثبيت الجسر صراحةً.

لعرض مكوّن vapor داخل تطبيق تقليدي، ثبّت إضافة التوافق على createApp العادية:

// src/main.ts — جذر تقليدي وأوراق vapor
import { createApp, vaporInteropPlugin } from 'vue'
import App from './App.vue'
 
const app = createApp(App)
app.use(vaporInteropPlugin) // يتيح الحدود بين VDOM و vapor
app.mount('#app')

مع تثبيت الإضافة، يستطيع الأب التقليدي عرض ابن vapor، ويستطيع أب vapor عرض ابن تقليدي، في الاتجاهين. لاحظ أن createVaporApp وcreateApp مع vaporInteropPlugin استراتيجيتان مختلفتان:

الاستراتيجيةمتى تستخدمهاالمقايضة
createVaporAppتطبيق جديد، كل مكوّناته vaporأصغر زمن تشغيل؛ لا يُسمح بأي مكوّن تقليدي
createApp + vaporInteropPluginتطبيق قائم، تحويل المسارات الساخنةيشحن الوضعين؛ يتيح الترحيل مكوّنًا تلو الآخر

التوجيه العملي بسيط: لكل حدّ توافقي كلفة. العبور من VDOM إلى vapor والعودة في كل صف من صفوف الجدول يمحو المكسب تمامًا. حوّل أشجارًا فرعية متصلة — الجدول وصفوفه وشاراته — واترك الحدّ في الأعلى حيث يُعبر مرة واحدة فقط.

أما المكوّن التقليدي الذي لا يملك ملف SFC (دالة تصيير مثلًا)، فيمكنك كتابته بأسلوب vapor عبر defineVaporComponent، لكن في معظم التطبيقات سيقتصر عملك على إضافة العلامة إلى ملفات SFC.

اختبار التنفيذ

هناك فحصان مهمان، وواحد منهما فقط يتضمن ساعة إيقاف.

الصحة الوظيفية

تأكد أن شيئًا لم ينكسر وظيفيًا. اضغط زر إعادة التشغيل وتحقق من وصول الحدث إلى الطرفية. تأكد أن عدّاد "غير سليمة" يتابع الشارات. تأكد أن الصفوف تتحدّث في مكانها بدل أن يعاد ترتيبها، فذلك يعني أن :key خاطئة.

الأداء

افتح أدوات مطوّري Chrome، وانتقل إلى لوحة Performance، وسجّل نحو 5 ثوانٍ من تشغيل اللوحة. ثم قارن بين بنائين:

  1. احذف vapor من وسوم السكربت في StatusBadge.vue وInstanceRow.vue وInstanceTable.vue، وأعد main.ts إلى createApp، ثم سجّل.
  2. أعد العلامات، وبدّل إلى createVaporApp، ثم سجّل مجددًا.

ابحث عن ثلاثة أمور في مخطط اللهب:

  • زمن السكربت لكل نبضة. في الوضع التقليدي سترى إطارات متكرّرة لدوال التصيير وعمل ترقيع للشجرة الفرعية لكل صف تغيّر. في وضع vapor تختفي هذه الإطارات إلى حد بعيد، ولا يبقى سوى حفنة من استدعاءات التأثيرات الضيّقة.
  • الذاكرة وجامع المهملات. الوضع التقليدي يخصّص شجرة vnode جديدة لكل تحديث. راقب كيف يستوي منحنى الذاكرة المسنّن تحت vapor.
  • التركيب الأولي. تركيب vapor عادةً أسرع أيضًا، لأنه ينفّذ شيفرة بناء DOM مباشرة بدل بناء شجرة ثم اجتيازها.

لا تلاحق مضاعِفًا رقميًا محددًا. حجم المكسب يعتمد كليًا على كثافة الروابط في قوالبك وعلى حجم ما حوّلته من التطبيق. في جدول كهذا، بصفوف كثيرة وروابط قليلة متغيّرة لكل صف، يكون الفارق كبيرًا. أما في مكوّن يعيد رسم كل شيء على أي حال، فيكون ضئيلًا.

واجعل المقارنة نزيهة: ابنِ نسخة إنتاج (npm run build && npm run preview) قبل القياس. فوضع التطوير في Vue يحمل تحذيرات ومحاسبة داخلية تشوّه القياس في الوضعين معًا.

استكشاف الأخطاء وإصلاحها

"سمة vapor مُتجاهَلة / المكوّن ما زال يستخدم الـ DOM الافتراضي." راية features: { vapor: true } مفقودة من خيارات @vitejs/plugin-vue، أو أن نسخة الإضافة أقدم من دعم vapor. أعد التحقق عبر npm ls @vitejs/plugin-vue.

"لا يمكن استخدام Options API داخل مكوّن vapor." تمامًا كما تقول الرسالة. حوّل المكوّن إلى script setup بواجهة التركيب، أو اتركه تقليديًا ودع إضافة التوافق تجسر الفجوة.

مكوّن تقليدي يظهر فارغًا داخل أب vapor. نسيت app.use(vaporInteropPlugin). التوافق ليس ضمنيًا أبدًا.

مكوّن من مكتبة خارجية يرمي خطأً تحت vapor. بعض المكتبات تتعمّق في بنية الـ DOM الافتراضي (دوال تصيير مخصصة، تلاعب بالـ vnode، توجيهات معيّنة). أبقِ تلك المكوّنات تقليدية وضع حدّ التوافق فوقها بدل مصارعتها.

الأداء صار أسوأ بعد التحويل. السبب غالبًا مشكلة في حدود التوافق: حوّلت مكوّنًا ورقيًا يقع داخل قائمة تقليدية، فصار كل عنصر يدفع كلفة عبور حدّ. حوّل صعودًا إلى أن يصبح الحدّ يُعبر مرة واحدة لا N مرة.

ميزة تعتمد عليها غير مدعومة. وضع Vapor جديد ومساحة ميزاته ما تزال تكتمل إصدارًا بعد إصدار. راجع توثيق Vue الحالي قبل افتراض توفّر توجيه أو انتقال أو سلوك دورة حياة معيّن داخل مكوّنات vapor — وأبقِ المكوّن المتأثر تقليديًا في الأثناء.

الخطوات التالية

  • حوّل القائمة إلى قائمة افتراضية (virtualized). vapor يجعل كل تحديث رخيصًا، لكن تصيير 5000 صف DOM يبقى مكلفًا بحد ذاته. اجمع vapor مع مكتبة نوافذ عرض، ويتضاعف المكسبان.
  • ابدأ بأسوأ مكوّن لديك. حلّل أداء تطبيقك الحقيقي، وجد المكوّن الأعلى كلفة سكربت لكل تفاعل، وحوّل تلك الشجرة الفرعية — لا قاعدة شيفرتك كلها.
  • استكشف مخرجات المترجم. قراءة الشيفرة المولّدة لقالب كتبته بنفسك هي أسرع طريقة لبناء حدس حول أي الروابط ديناميكي فعلًا.
  • اقرأ أدلتنا المرتبطة حول التحسين التلقائي مع React Compiler وبناء تطبيقات متكاملة مع Nuxt 4 لترى كيف تهاجم أطر أخرى العبء نفسه من زوايا مختلفة.

الخلاصة

وضع Vapor ليس إطارًا جديدًا ولا نموذجًا ذهنيًا جديدًا ولا إعادة كتابة. إنه نفس Vue الذي تكتبه اليوم — ref وcomputed وv-for وملفات SFC والأنماط المعزولة — مترجَمًا عبر خلفية مختلفة تُخرج عمليات DOM مباشرة بدل شجرة DOM افتراضية.

ما تعلّمته هنا ينتقل مباشرة إلى العمل الإنتاجي: فعّل راية المترجم، وضع علامة vapor على أشجار فرعية متصلة، وأبقِ تلك الأشجار على واجهة التركيب حصريًا، وثبّت vaporInteropPlugin عند الحدّ مع شيفرتك التقليدية، وتحقق من المكسب في بناء إنتاجي بأداة قياس بدل الوثوق بمقياس أجراه شخص آخر.

ابدأ بالمكوّن الذي يشعر به مستخدموك أكثر من غيره. هناك بالضبط كان الـ DOM الافتراضي يكلّفك، وهناك ستظهر ثمرة إزالته.

● الوسوم
#vue#vapor-mode#performance#typescript#vite#intermediate#24 دقيقة قراءة
● مشاركة
● هل لديك سؤال؟

تحدث مع وكيل نقطة بشأن هذا المقال.

AI Bot
AI Bot
Author · noqta
متابعة ↗

● اقرأ التالي

بروتوكول A2A بلغة TypeScript: بناء وكلاء ذكاء اصطناعي متوافقين مع معيار Agent2Agent (2026)
● Tutorial

بروتوكول A2A بلغة TypeScript: بناء وكلاء ذكاء اصطناعي متوافقين مع معيار Agent2Agent (2026)

6 يوليو 2026
بناء وكيل ACP بلغة TypeScript: اربط أي محرّر بوكيل الذكاء الاصطناعي الخاص بك (2026)
● Tutorial

بناء وكيل ACP بلغة TypeScript: اربط أي محرّر بوكيل الذكاء الاصطناعي الخاص بك (2026)

30 يونيو 2026
بروتوكول AG-UI مع Next.js: بث وكلاء الذكاء الاصطناعي إلى واجهتك بأحداث مُنمّطة (2026)
● Tutorial

بروتوكول AG-UI مع Next.js: بث وكلاء الذكاء الاصطناعي إلى واجهتك بأحداث مُنمّطة (2026)

9 يوليو 2026
نقطة
الشروط والأحكام · سياسة الخصوصية
الخدمات
  • أتمتة الذكاء الاصطناعي
  • وكلاء الذكاء الاصطناعي
  • أتمتة تجربة العملاء
  • Vibe Coding
  • إدارة المشاريع
  • ضمان الجودة
  • تطوير الويب
  • تكامل API
  • تطبيقات الأعمال
  • الصيانة
  • Low-Code/No-Code
الروابط
  • معلومات عنا
  • كيف نعمل؟
  • الأخبار
  • الدروس التعليمية
  • المدونة
  • تواصل معنا
  • الأسئلة الشائعة
  • الموارد
المناطق
  • السعودية
  • الإمارات
  • قطر
  • البحرين
  • عُمان
  • ليبيا
  • تونس
  • الجزائر
  • المغرب
الشركة
  • نقطة، تونس، الهاتف +216 24 309 128
© نقطة. جميع الحقوق محفوظة.