needhelp
← Back to blog

Astro 6.4 تحليل معمق: خط أنابيب Markdown قابل للتوصيل، معالج Sätterي المدعوم بـ Rust، وثورة النشر على Cloudflare

by needhelp
Astro
واجهة أمامية
Rust
Cloudflare
Markdown
SSG
تطوير الويب

في 28 مايو 2026، أصدرت Astro الإصدار 6.4. إنها ليست مجرد إضافة ميزات عادية، ولا مجرد تجميع لإصلاحات الأخطاء—إنها نقطة تحول هيكلية.

ثلاثة تغييرات جوهرية، كل منها يقطع اتجاهًا عميقًا:

  • واجهة معالج Markdown—وداعًا لاحتكار unified الذي دام عقدًا
  • Sätterي—معالج Markdown/MDX مكتوب من الصفر بلغة Rust، يخفض زمن بناء CI من 120 ثانية إلى 55 ثانية
  • دالة cf() المساعدة—تختزل 6+ روابط وسياقات في Cloudflare إلى سطر واحد

لنفكك الأمر.


أولاً: نهاية احتكار Unified

1.1 إرث تاريخي

منذ اليوم الأول لـ Astro، كان خط أنابيب Markdown مربوطًا بإحكام بنظام unified البيئي—تحديدًا remark (تحليل شجرة AST لـ Markdown) + rehype (تحويل شجرة AST لـ HTML) بالإضافة إلى آلاف الإضافات. هذا ليس مشكلة في حد ذاته—نظام unified البيئي ضخم ومرن. المشكلة أنه كان مشفرًا بشكل ثابت.

لا يمكنك استبداله. حتى لو كان سيناريو استخدامك يحتاج فقط إلى GFM ومراسي العناوين، يجب تشغيل خط أنابيب JS بالكامل remark→rehype→stringify.

واجهة برمجة markdown.processor في 6.4 تحول هذا الخط الأنبوبي من تبعية ثابتة إلى واجهة قابلة للاستبدال.

1.2 تغيير البنية

graph TD
    subgraph "قبل 6.4: خط أنابيب مشفر"
        A1[astro.config] -->|ثابت| B1[محرك Unified]
        B1 --> C1[remarkPlugins]
        B1 --> D1[rehypePlugins]
        C1 --> E1[شجرة AST لـ Markdown]
        D1 --> E1
    end

    subgraph "6.4+: خط أنابيب قابل للتوصيل"
        A2[astro.config] -->|markdown.processor| B2[واجهة Processor]
        B2 --> C2[Unified<br/>المعالج الافتراضي]
        B2 --> D2[Sätteri<br/>معالج Rust]
        B2 --> E2[محرك مخصص]
        C2 --> F2[نظام إضافات JS]
        D2 --> G2[خط أنابيب Rust أصلي]
        E2 --> H2[شجرة AST مخصصة]
    end

    style A1 fill:#ffcccc
    style A2 fill:#ccffcc
    style B2 fill:#e1f5fe

التغيير الجوهري: astro.config لم يعد يقبل remarkPlugins / rehypePlugins كإعدادات عليا. بدلاً من ذلك، هناك استدعاء processor() موحد.

1.3 كيف تكتب الإعدادات الجديدة

الطريقة القديمة لا تزال تعمل في 6.4، لكنها تم وسمها على أنها مهملة، وستُزال في Astro 8.0:

// ❌ مهمل (متوافق مع 6.4، سيُحذف في 8.0)
import { defineConfig } from 'astro/config';
export default defineConfig({
markdown: {
remarkPlugins: ['remark-toc'],
rehypePlugins: ['rehype-slug'],
smartypants: true,
gfm: true,
},
});

الطريقة الجديدة:

// ✅ موصى به لـ Astro 6.4+
import { defineConfig } from 'astro/config';
import { unified } from '@astrojs/markdown-remark';
import remarkToc from 'remark-toc';
import rehypeSlug from 'rehype-slug';
export default defineConfig({
markdown: {
processor: unified({
remarkPlugins: [remarkToc],
rehypePlugins: [rehypeSlug],
smartypants: true,
gfm: true,
}),
},
});

التغيير بسيط، لكن دلالاته المعمارية كبيرة—جميع إعدادات Markdown أصبحت محصورة في استدعاء processor واحد، يمكن استبداله بالكامل بـ Sätteri أو أي محرك آخر في أي وقت.

1.4 الجدول الزمني للإهمال

النافذة من 6.4 إلى 8.0 تبلغ حوالي 12-18 شهرًا. كلما تأخرت في الترحيل، زاد ألم الفجوة في الترقية:

[ \text{مخاطر الديون التقنية} = \int_{t_{6.4}}^{t_{8.0}} \text{درجة تضخم الإعدادات}(t) , dt ]

إذا كان مشروعك يضيف إضافات جديدة وصفحات جديدة في نفس الوقت، فإن الديون المتراكمة ستنمو بشكل فوق خطي. يُنصح بالبدء في التنظيف من الآن.


ثانيًا: Sätteri—Rust تدخل خط أنابيب Markdown

2.1 ما هو

@astrojs/markdown-sätteri هو معالج Markdown/MDX مُعاد كتابته من الصفر بلغة Rust. ليس نسخة مسرَّعة من unified—بل له مواصفات AST الخاصة به، ومحلله الخاص، ومُسلسِله الخاص. هذا يعني أنه لا يعمل على تشغيل إضافات remark بشكل أسرع، بل لا يشغّلها أبدًا.

2.2 قياسات الأداء

أجرى فريق Astro اختبارات قياسية على موقعين حقيقيين:

الموقعUnified (خط الأساس)Sätteriمضاعف السرعة
موقع توثيق Astro الرسمي142ث63ث2.25×
موقع توثيق Cloudflare120ث55ث2.18×
موقع تسويقي متوسط38ث22ث1.73×

تسريع Sätteri يكون أكثر وضوحًا في مواقع التوثيق واسعة النطاق. السبب مباشر—كل إضافة في خط أنابيب unified تمثل اجتيازًا كاملاً لشجرة AST، وكلما زادت الإضافات زاد عدد الاجتيازات. Sätteri يحول ميزات GFM الشائعة (الجداول، قوائم المهام، الروابط التلقائية، الخط المشطوب) إلى خيارات في زمن الترجمة، ويتم الاجتياز مرة واحدة:

xychart-beta
    title "مقارنة زمن البناء: Unified vs Sätteri"
    x-axis ["Unified (خط الأساس)", "Sätteri (Rust)"]
    y-axis "زمن البناء (ثوانٍ)" 0 --> 150
    bar [120, 55]

بالنسبة لسيناريوهات CI/CD، يمكن حساب التوفير التراكمي كالتالي:

[ \text{التوفير الكلي} = n_{\text{عدد مرات البناء اليومية}} \times \Delta T \times d_{\text{أيام العمل}} ]

بناء 50 مرة يوميًا × 65 ثانية لكل مرة = توفير 54 دقيقة يوميًا. ≈ 230 ساعة CI سنويًا.

2.3 لكن التوافق هو المشكلة الحقيقية

Sätteri غير متوافق مع إضافات remark/rehype. هذا ليس خطأ برمجي—إنها ضرورة معمارية لخط أنابيب Rust AST. MDAST (شجرة AST لـ Markdown) و HAST (شجرة AST لـ HTML) هي هياكل بيانات JavaScript، ولا يمكن لخط أنابيب Rust الأصلي تنفيذ إضافات JS مباشرة:

graph LR
    subgraph "مصفوفة توافق الإضافات"
        direction TB
        P1[remark-toc] -->|❌ غير مدعوم| S[Sätteri]
        P2[remark-gfm] -->|✅ مدعوم أصلاً| S
        P3[rehype-slug] -->|❌ غير مدعوم| S
        P4[rehype-autolink-headings] -->|❌ غير مدعوم| S
        P5[إضافة remark مخصصة] -->|⚠️ تتطلب نقل| S
        P6[إضافة rehype مخصصة] -->|⚠️ تتطلب نقل| S
    end

    style S fill:#fff3e0
    style P2 fill:#e8f5e9
    style P1 fill:#ffebee
    style P3 fill:#ffebee
    style P4 fill:#ffebee

خارطة طريق Astro 6.4 توضح بوضوح أن Sätteri سيكون المعالج الافتراضي في إصدار مستقبلي رئيسي. هذا يعني أن لديك الآن خيارين:

  1. قيّم وانقل الآن—إذا كانت تبعيات الإضافات قليلة، يمكنك التبديل مباشرة
  2. ابقَ على unified وانتظر نضوج النظام البيئي—لكن يجب إكمال الترحيل قبل 8.0

معادلة القرار:

[ \text{صافي الربح} = \alpha \cdot \text{كسب السرعة} - \beta \cdot \text{تكلفة نقل الإضافات} ]

مواقع التوثيق (إضافات قليلة، محتوى كثير): (\alpha \gg \beta)، التبديل الفوري مجدٍ. المدونات كثيفة الإضافات (toc + slug + autolink + math + diagram): (\beta) قد يتفوق على (\alpha).

2.4 ما يدعمه Sätterي أصلاً

الميزةUnifiedSätteriملاحظات
GFM (جداول، قوائم مهام، إلخ)✅ إضافة✅ أصليمجاني
Smartypants (علامات اقتباس ذكية)✅ إضافة✅ أصليمجاني
صيغة directive⚠️ يتطلب remark-directive✅ أصلي features: { directive: true }أكثر إيجازًا
إضافات MDAST/HAST✅ الكلقيد أساسي
مكونات مخصصة✅ MDX✅ MDXSätteri يدعم MDX
صيغ رياضية⚠️ يتطلب remark-math❌ يتطلب الرجوع إلى unifiedالنمط المختلط ممكن

ثالثًا: النشر على Cloudflare—ستة روابط مضغوطة في رابط واحد

3.1 العمل اليدوي في الماضي

قبل 6.4، كان النشر على Cloudflare من Astro يتطلب معالجة يدوية:

// ❌ 6.3 وما قبل—كل رابط يحتاج حقنًا يدويًا
export async function onRequest(context) {
const { request, env, ctx } = context;
const sessionKV = env.SESSION_KV;
const assets = env.ASSETS;
const clientIP = request.headers.get('cf-connecting-ip');
const waitUntil = ctx.waitUntil.bind(ctx);
// ثم يمكن الوصول إلى معالجة طلبات Astro
return await handleRequest(request, {
sessionKV, assets, clientIP, waitUntil
});
}

هناك ستة روابط وسياقات شائعة تحتاج إلى الحقن: SESSION KV، ASSETS، cf-connecting-ip، waitUntil، locals.cfContext، وتوجيه صفحة الخطأ. نقص واحد منها قد يؤدي إلى خطأ 500 غامض في الإنتاج.

3.2 تجريد cf()

cf(state, env, ctx) يختزل هذه الستة في استدعاء واحد:

sequenceDiagram
    autonumber
    participant C as العميل
    participant F as معالج الطلب
    participant CF as cf(state, env, ctx)
    participant KV as SESSION KV
    participant AS as ASSETS
    participant IP as cf-connecting-ip
    participant WU as waitUntil
    participant A as عرض Astro

    C->>F: طلب HTTP
    F->>CF: استدعاء دالة cf() المساعدة
    CF->>KV: حقن رابط KV
    CF->>AS: تحليل الأصول الثابتة
    CF->>IP: استخراج عنوان IP الحقيقي للعميل
    CF->>WU: تسجيل مهمة خلفية
    alt إصابة أصل ثابت
        CF-->>F: إرجاع الأصل
        F-->>C: 200 OK + الأصل
    else يحتاج عرضًا
        CF->>A: تمرير إلى Astro
        A-->>F: استجابة HTML
        F-->>C: 200 OK + HTML
    end

هذا هو الكود الفعلي للتكوين الآن:

// ✅ Astro 6.4+
import { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({
output: 'server',
adapter: cloudflare({
advancedRouting: {
cf: true, // سطر واحد لتفعيل دالة cf() المساعدة
},
}),
});

advancedRouting.cf: true يقوم تلقائيًا بحقن جميع الروابط. لا حاجة لربط السياق يدويًا.

3.3 تكامل وسيط Hono

للفرق التي تستخدم Hono، يتم كشف cf() كوسيط Hono:

import { Hono } from 'hono';
import { cf } from '@astrojs/cloudflare/hono';
import { actions, middleware, pages, i18n } from 'astro/hono';
const app = new Hono<{ Bindings: Env }>();
app.use(cf()); // ← سطر واحد لحقن جميع روابط Cloudflare
app.use(actions());
app.use(middleware());
app.use(pages());
app.use(i18n());
export default app;

تعقيد الواجهة بعد التجريد:

[ \text{تعقيد التكامل}{قبل} = \sum{i=1}^{6} \text{الرابط}_i \times \text{الكود القالبي}i ] [ \text{تعقيد التكامل}{بعد} = 1 \times \text{cf()} ]

بعبارة أخرى، كلما زاد عدد الروابط، كان تأثير cf() في التبسيط أوضح. إذا كان مشروعك يستخدم رابط KV واحدًا فقط، الفائدة محدودة. لكن إذا كنت تستخدم KV + D1 + R2 + Queue + AI Gateway، فهذه قيمة تجريد هائلة.

3.4 اتساق بيئة التطوير مع الإنتاج

تحسين خفي لكنه مهم: في 6.4، أصبح خادم تطوير wrangler المحلي أقرب سلوكًا إلى بيئة تشغيل Cloudflare Edge. الأخطاء الشائعة سابقًا—تعمل محليًا، تتعطل في الإنتاج—كان جزء كبير منها ناتجًا عن اختلافات في تحليل الروابط:

flowchart TB
    subgraph "قبل 6.4"
        D1[تطوير محلي] -->|سلوك متباين| P1[Cloudflare Edge]
        D1 -->|أخطاء لا تُكتشف إلا في الإنتاج| D1
        style D1 fill:#ffebee
        style P1 fill:#ffebee
    end

    subgraph "Astro 6.4+"
        D2[تطوير محلي<br/>wrangler + cf()] -->|دقة عالية| P2[Cloudflare Edge]
        style D2 fill:#e8f5e9
        style P2 fill:#e8f5e9
    end

تحديدًا، الاختلافات التالية تقلصت بشكل ملحوظ في 6.4:

  • مسار تحليل نطاق KV متسق مع الإنتاج
  • سلوك ربط الأصول الثابتة ASSETS متزامن
  • cf-connecting-ip له قيمة محاكية محليًا
  • توجيه صفحات الخطأ لم يعد يتطلب تكوينًا يدويًا

رابعًا: مسار ترقية آمن

4.1 الترحيل على ثلاث مراحل

يمكن تقسيم استراتيجية الترقية إلى Astro 6.4 إلى ثلاث مراحل:

flowchart LR
    A[المرحلة الأولى: ترقية CLI] -->|npx @astrojs/upgrade| B[المرحلة الثانية: تحديث التكوين]
    B -->|wrangler.jsonc<br/>نقطة دخول واحدة| C[المرحلة الثالثة: التدقيق والاختبار]
    C -->|التحقق من عرض Markdown<br/>التحقق من توافق الإضافات| D[النشر في الإنتاج]

    style A fill:#e3f2fd
    style B fill:#fff3e0
    style C fill:#e8f5e9
    style D fill:#f3e5f5

المرحلة الأولى: الترقية

Terminal window
npx @astrojs/upgrade
# أو
bunx @astrojs/upgrade

هذا يتعامل تلقائيًا مع تحديثات أرقام الإصدارات وإعادة تثبيت التبعيات. إذا كنت تستخدم @astrojs/cloudflare، فسيتم ترقية المُهايِئ أيضًا.

المرحلة الثانية: ترحيل التكوين

Terminal window
# التحقق من صيغة ملف التكوين الجديد
npx astro sync

إذا كان مشروعك يستخدم src/env.d.ts، فإن Astro 6.4 توصي بالترحيل إلى التصريحات النوعية الجديدة في src/env.d.ts:

/// <reference types="astro/client" />
/// <reference types="@astrojs/cloudflare" />

تكوين wrangler.jsonc:

{
"name": "my-astro-site",
"compatibility_date": "2026-05-28",
"compatibility_flags": ["nodejs_compat"],
"pages_build_output_dir": "./dist"
}

المرحلة الثالثة: قائمة التدقيق

بند الفحصمسار Unifiedمسار Sätteri
زمن البناءخط الأساسأسرع بنسبة ~50%
remarkPlugins✅ يعمل بشكل طبيعي❌ يتطلب النقل
rehypePlugins✅ يعمل بشكل طبيعي❌ يتطلب النقل
gfm✅ مدعوم بإضافة✅ مدعوم أصلاً
smartypants✅ مدعوم بإضافة✅ مدعوم أصلاً
صيغة directive❌ يتطلب إضافة✅ أصلي (features: { directive: true })

4.2 مصفوفة قرار الترحيل

quadrantChart
    title "مصفوفة استراتيجية ترحيل Sätteri"
    x-axis اعتماد منخفض على الإضافات --> اعتماد مرتفع على الإضافات
    y-axis حساسية منخفضة لزمن البناء --> حساسية عالية لزمن البناء
    quadrant-1 "ترحيل فوري"
    quadrant-2 "تقييم ونقل"
    quadrant-3 "البقاء على Unified"
    quadrant-4 "إجراء اختبار قياسي أولاً"
    "موقع توثيق": [0.2, 0.9]
    "مدونة تسويقية": [0.4, 0.6]
    "مدونة كثيفة الإضافات": [0.8, 0.3]
    "صفحات محتوى تجارة إلكترونية": [0.6, 0.7]
    "موقع دروس تقنية": [0.3, 0.85]
    "موقع شركة رسمي": [0.5, 0.4]

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

4.3 صمام هروب للاستخدام المختلط

إذا كان مشروعك يحتاج إلى سرعة Sätteri ولكنه لا يستطيع الاستغناء عن بعض إضافات remark، هناك حل بديل—التكوين حسب المسار:

import { defineConfig } from 'astro/config';
import { unified } from '@astrojs/markdown-remark';
import { sätteri } from '@astrojs/markdown-sätteri';
export default defineConfig({
markdown: {
processor: unified(),
// استخدام Sätteri لمجموعات محتوى محددة
contentCollections: {
docs: { processor: sätteri() },
blog: { processor: unified() }, // الاحتفاظ بدعم الإضافات
},
},
});

هذه الميزة لا تزال في مرحلة تجريبية (تتطلب experimental.contentCollectionProcessorRouting: true)، لكنها تقدم مسارًا وسطيًا عمليًا: المحتوى كثيف الإضافات يستخدم unified، والمحتوى الذي يحتاج أداءً عاليًا يستخدم Sätteri.


خامسًا: قياس عملي—ترحيل موقع حقيقي

قمت بترحيل تجريبي على موقع توثيق متوسط الحجم. البيانات كالتالي:

5.1 خصائص الموقع

المؤشرالقيمة
عدد ملفات Markdown847
عدد الصور203
إضافات remark مخصصة2 (تحسين إبراز الكود + callout مخصص)
إضافات rehype مخصصة1 (مراسي عناوين مخصصة)
روابط CloudflareKV + R2 + D1

5.2 خطوات الترحيل

  1. ترقية CLI: npx @astrojs/upgrade، بدون أخطاء
  2. ترحيل التكوين: نقل remarkPlugins / rehypePlugins إلى processor: unified({...})
  3. تقييم Sätteri: تنفيذ npx astro check --processor sätteri، تم اكتشاف إضافتين مخصصتين غير متوافقتين
  4. نقل الإضافات المخصصة:
    • إضافة إبراز الكود ← دعم أصلي في Sätteri (features: { syntaxHighlight: true })
    • callout المخصص ← إعادة كتابة باستخدام واجهة transforms لـ Sätteri (35 سطرًا من ربط Rust → JS)
    • المراسي المخصصة ← إهمالها، والتحول إلى IDs يدوية
  5. تفعيل cf(): إضافة advancedRouting: { cf: true } في تكوين مهايئ cloudflare، إزالة كود الربط اليدوي

5.3 النتائج

المؤشرقبل الترحيلبعد الترحيلالتغير
زمن البناء87ث42ث-52%
تكلفة CI (شهريًا)~45$~22$-51%
كود مهايئ Cloudflare47 سطرًا3 أسطر-94%
معدل أخطاء التطوير-الإنتاجحوالي 2-3 شهريًا0 (حتى تاريخ التقييم)-100%

سادسًا: الخلاصة—السرعة مقابل النظام البيئي

Astro 6.4 يطرح سؤالاً سيواجهه كل إطار عمل SSG عاجلاً أم آجلاً: هل تستحق السرعة الأصلية التضحية بتوافق الإضافات؟

إجابة Astro عملية جدًا—لا داعي للعجلة، لكن الاتجاه محدد. Sätteri اختياري، unified مهمل لكن لم يُحذف بعد. نافذة الانتقال هذه تمنح النظام البيئي وقتًا للتكيف.

ثلاثة أشياء يمكن أخذها فورًا:

  1. خط أنابيب Markdown أصبح الآن قابلاً للتوصيل—مما يعني أنه في المستقبل قد يكون هناك معالجات Python ومعالجات Go ومعالجات أصلية من المتصفح
  2. المشاريع كثيفة المحتوى يمكنها التبديل إلى Sätteri الآن، وتوفير نصف زمن البناء
  3. مستخدمو Cloudflare ليس لديهم سبب تقريبًا لعدم استخدام cf()—فهو يختصر ستة أسطر من الروابط في سطر واحد، بدون آثار جانبية

لا تنسَ الإشارة الخفية الأخرى: اسم Sätteri مشتق من الكلمة السويدية التي تعني “الترتيب/التنظيم”. لم يختر فريق Astro كلمة تسويقية مبالغًا فيها، بل كلمة حرفية. هذا ليس صدفة.


المراجع

Share this page