Block Serialization در وردپرس فرآیندی است که طی آن ساختار یک بلاک به یک رشته متنی قابل ذخیره در پایگاه داده تبدیل می‌شود و در زمان بارگذاری، همین رشته دوباره به ساختار بلاک بازگردانده می‌شود؛ این رفت‌و‌برگشت (Round-Trip) پایه ذخیره‌سازی محتوای گوتنبرگ است.

Block Serialization در وردپرس فرآیند تبدیل ساختار بلاک به یک رشته HTML سریالایز‌شده و ذخیره آن در پایگاه داده است.

این مکانیزم بر پایه کامنت‌های مخصوصی بنا شده که نام بلاک و ویژگی‌های آن را در دل HTML نگه می‌دارند.

در زمان بارگذاری، یک parser (تحلیل‌گر) همان رشته را می‌خواند و ساختار بلاک‌ها را بازسازی می‌کند.

بدون Block Serialization، ویرایشگر بلوک نمی‌توانست محتوای ذخیره‌شده را به‌درستی بازخوانی کند و هر بار ویرایش، ساختار را از دست می‌داد.

در این مقاله معماری سریالایز، ساختار کامنت‌ها، فرآیند round-trip، الگوهای عملی، اشتباهات رایج و نکات پیشرفته را با مثال‌های واقعی بررسی می‌کنیم.

نخستین بار که محتوای یک پست را در ویرایشگر کد باز کردم و دیدم HTML با کامنت‌هایی شبیه <!-- wp:paragraph --> پر شده، متوجه شدم که گوتنبرگ به‌جای ذخیره ساختار درختی بلاک‌ها در پایگاه داده، آن را به یک رشته HTML تبدیل کرده و کامنت‌های مخصوص را به‌عنوان لنگر (Anchor) نگه می‌دارد. آن تجربه نقطه شروعی شد برای بررسی دقیق Block Serialization و نقش آن در ذخیره‌سازی محتوای گوتنبرگ. آنچه در ادامه می‌خوانید حاصل کار عملی با این مکانیزم در پروژه‌های واقعی و بررسی کد منبع گوتنبرگ است.

Block Serialization چیست و چه نیازی را برطرف می‌کند؟

Block Serialization در وردپرس فرآیندی است که طی آن ساختار یک بلاک گوتنبرگ به یک رشته HTML قابل ذخیره تبدیل می‌شود. این رشته شامل دو بخش اصلی است: کامنت‌های مخصوصی که نام بلاک و ویژگی‌های آن را نگه می‌دارند، و HTML واقعی که نمایش بلاک را توصیف می‌کند. در زمان بارگذاری، همین رشته توسط یک parser خوانده می‌شود و ساختار اصلی بلاک‌ها بازسازی می‌گردد. این رفت‌و‌برگشت که به آن Round-Trip گفته می‌شود، پایه اصلی ذخیره‌سازی محتوای گوتنبرگ است. برای آشنایی با تاریخچه گوتنبرگ، مقاله Gutenberg چیست و چگونه ویرایش محتوای وردپرس را متحول کرد؟ را مطالعه کنید.

نیازی که Block Serialization برطرف می‌کند، ماهیت ذخیره‌سازی محتوا در وردپرس است. پایگاه داده وردپرس برای محتوای پست‌ها، فیلد متنی ساده دارد و امکان ذخیره ساختار درختی را فراهم نمی‌کند. از سوی دیگر، ویرایشگر بلوک به یک ساختار درختی از بلاک‌ها نیاز دارد تا بتواند آن‌ها را مدیریت، جابه‌جا و ویرایش کند. سریالایز کردن، پل میان این دو دنیا است: ساختار درختی بلاک‌ها به یک رشته متنی تبدیل می‌شود که در فیلد متنی ذخیره می‌گردد و در زمان بارگذاری دوباره به ساختار درختی بازمی‌گردد. برای مطالعه بیشتر درباره مبانی HTML، مقاله چرا HTML API در وردپرس امن‌ترین راه پردازش HTML است؟ را ببینید.

Block Serialization یک تصمیم معماری است: به‌جای تغییر اسکیمای پایگاه داده، ساختار درختی به یک رشته متنی تبدیل می‌شود و در همان فیلد سنتی ذخیره می‌گردد.

یکی از پیامدهای مهم این تصمیم، سازگاری با محتوای قدیمی است. وردپرس از نسخه‌های پیش از گوتنبرگ، محتوای پست‌ها را به‌صورت HTML خام ذخیره می‌کرد. اگر ساختار بلاک‌ها به‌صورت مستقیم در پایگاه داده ذخیره می‌شد، همه محتوای قدیمی نیاز به مهاجرت داشتند. اما با سریالایز، محتوای قدیمی به‌عنوان یک بلاک Classic یا بلاک‌های گوتنبرگ با کامنت‌های سبک، بدون نیاز به مهاجرت گسترده قابل خواندن و نمایش است. برای مطالعه بیشتر درباره این سازگاری، مقاله ویرایشگر Classic یا Gutenberg؛ کدام برای WordPress بهتر است؟ را ببینید.

سریالایز کردن همچنین امکان نگهداری تاریخچه تغییرات را فراهم می‌کند. هر نسخه از محتوای پست که در revision‌ها ذخیره می‌شود، شامل رشته سریالایز‌شده است. این رویکرد امکان بازگردانی محتوا به نسخه‌های قبلی را بدون پیچیدگی ساختاری فراهم می‌سازد. برای مطالعه بیشتر درباره مدیریت نسخه‌ها، مقاله بهینه‌سازی دیتابیس وردپرس: چه چیزی واقعاً سرعت را بالا می‌برد؟ را ببینید.

چرا سریالایز کردن بلاک‌ها ضروری است؟

سریالایز کردن بلاک‌ها از چند منظر ضروری است. اولین دلیل، سازگاری با ساختار پایگاه داده وردپرس است. فیلد post_content یک فیلد متنی بلند است و امکان ذخیره ساختار درختی را ندارد. اگر گوتنبرگ می‌خواست ساختار بلاک‌ها را به‌صورت دقیق ذخیره کند، باید یک جدول جدید در پایگاه داده ایجاد می‌کرد و این امر پیچیدگی قابل‌توجهی به همراه داشت.

دومین دلیل، قابلیت خواندن محتوا در خارج از ویرایشگر بلوک است. اگر محتوای پست به‌صورت رشته سریالایز‌شده ذخیره شود، هر ابزاری که HTML را می‌فهمد (مانند مرورگر، خزنده گوگل یا ابزارهای تحلیل محتوا) می‌تواند آن را بخواند. کامنت‌های مخصوص بلاک در HTML به‌عنوان کامنت معمولی دیده می‌شوند و بر نمایش تأثیری ندارند. برای مطالعه بیشتر درباره سئو، مقاله Data API در وردپرس چیست و چطور state بلاک‌ها را مدیریت می‌کند؟ را ببینید.

سومین دلیل، امکان مهاجرت و Deprecation است. سریالایز کردن ساختاری و قابل پیش‌بینی، امکان تشخیص نسخه قدیمی بلاک و مهاجرت به نسخه جدید را فراهم می‌کند. اگر ساختار بلاک به‌صورت مستقیم در پایگاه داده ذخیره می‌شد، تغییر ساختار نیازمند مهاجرت گسترده بود. برای مطالعه بیشتر درباره این مکانیزم، مقاله Block Deprecation در وردپرس چیست و چرا نسخه‌های قدیمی بلاک را می‌شکند؟ را ببینید.

چهارمین دلیل، سادگی انتقال محتوا است. فایل‌های XML خروجی وردپرس، محتوای پست‌ها را به‌صورت رشته سریالایز‌شده ذخیره می‌کنند و انتقال آن به سایت دیگر، بدون نیاز به تبدیل ساختار انجام می‌شود. برای مطالعه بیشتر درباره مهاجرت، مقاله ساختار استاندارد افزونه وردپرس چیست و چطور یک پلاگین حرفه‌ای بسازیم؟ را ببینید.

پنجمین دلیل، امکان دستکاری برنامه‌نویسی محتوا است. با استفاده از توابع سریالایز و unserialize گوتنبرگ، می‌توان محتوا را به‌صورت برنامه‌نویسی تحلیل، تغییر و بازسازی کرد. این قابلیت در ساخت افزونه‌هایی که محتوای بلاک‌ها را دستکاری می‌کنند، حیاتی است. برای مطالعه بیشتر درباره توابع بلاک، مقاله چرا بدون React نمی‌توان بلاک حرفه‌ای در وردپرس ساخت؟ را ببینید.

کامنت‌های مخصوص: قالب سریالایز گوتنبرگ

قلب Block Serialization، کامنت‌های مخصوص گوتنبرگ است. این کامنت‌ها در واقع لنگرهایی هستند که ساختار بلاک‌ها را در HTML مشخص می‌کنند. سه نوع کامنت اصلی در سریالایز بلاک‌ها وجود دارد که در ادامه به بررسی آن‌ها می‌پردازیم.

کامنت بازکننده بلاک

کامنت بازکننده بلاک، آغاز یک بلاک را مشخص می‌کند و نام بلاک و ویژگی‌های آن را در خود دارد. ساختار آن به این صورت است:

<!-- wp:block-name {"attribute1":"value1","attribute2":"value2"} -->

در این ساختار، wp: یک پیشوند ثابت است که نشان می‌دهد این کامنت مربوط به یک بلاک گوتنبرگ است. سپس نام بلاک با فرمت namespace/block-name می‌آید (برای بلاک‌های هسته، فقط نام بلاک کافی است). در انتها، ویژگی‌های بلاک به‌صورت JSON در آکولاد قرار می‌گیرند. اگر بلاک هیچ ویژگی سفارشی نداشته باشد، بخش JSON حذف می‌شود.

کامنت بسته بلاک

کامنت بسته بلاک، پایان یک بلاک را مشخص می‌کند. ساختار آن مشابه کامنت بازکننده است اما با یک اسلش پیش از نام بلاک:

<!-- /wp:block-name -->

این کامنت پایان محدوده بلاک را مشخص می‌کند و parser با دیدن آن، بلاک فعلی را می‌بندد.

کامنت بلاک خودبسته

برای بلاک‌هایی که محتوای درونی ندارند (مانند بلاک تصویر یا بلاک سفارشی)، از یک کامنت خودبسته استفاده می‌شود:

<!-- wp:image {"id":123,"sizeSlug":"large"} /-->

در این حالت، تنها یک کامنت بازکننده وجود دارد که با اسلش در انتها بسته می‌شود. این ساختار مشابه تگ‌های خودبسته در HTML است.

نمونه کامل سریالایز یک بلاک

برای درک بهتر، بیایید یک بلاک پاراگراف ساده را سریالایز کنیم:

<!-- wp:paragraph {"align":"center"} -->
<p class="has-text-align-center">این یک پاراگراف نمونه است.</p>
<!-- /wp:paragraph -->

در این ساختار، کامنت بازکننده نام بلاک (paragraph) و ویژگی (align: center) را مشخص می‌کند. سپس HTML واقعی بلاک قرار می‌گیرد و در نهایت کامنت بسته بلاک. توجه کنید که ویژگی align در HTML به‌صورت کلاس CSS has-text-align-center منعکس شده است. این هماهنگی میان ویژگی و خروجی HTML، یکی از اصول سریالایز گوتنبرگ است.

ویژگی‌ها و نقش JSON در سریالایز

ویژگی‌های بلاک (Attributes) در سریالایز گوتنبرگ نقشی کلیدی دارند. این ویژگی‌ها به‌صورت JSON در کامنت بازکننده ذخیره می‌شوند و در زمان بارگذاری، parser آن‌ها را می‌خواند و به ساختار بلاک اعمال می‌کند. در ادامه به بررسی نکات مهم درباره سریالایز ویژگی‌ها می‌پردازیم.

JSON به‌عنوان قالب استاندارد

گوتنبرگ از JSON به‌عنوان قالب استاندارد برای سریالایز ویژگی‌ها استفاده می‌کند. JSON یک قالب سبک، خوانا و قابل پارس کردن در تمام زبان‌های برنامه‌نویسی است. ساختار آن برای مقادیر مختلف به این صورت است:

  • رشته‌ها: "value"
  • اعداد: 123 یا 123.45
  • بولین: true یا false
  • آرایه: ["a", "b", "c"]
  • شیء: {"key": "value"}
  • null: null

حذف ویژگی‌های پیش‌فرض

یکی از بهینه‌سازی‌های مهم در سریالایز، حذف ویژگی‌هایی است که مقدارشان با مقدار پیش‌فرض یکسان است. اگر ویژگی align مقدار پیش‌فرض "" داشته باشد و در بلاک تنظیم نشده باشد، در JSON قرار نمی‌گیرد. این رویکرد حجم محتوای سریالایز‌شده را کاهش می‌دهد و کارایی پایگاه داده را بهبود می‌بخشد. برای مطالعه بیشتر درباره بهینه‌سازی، مقاله چرا InnerBlocks در وردپرس کلید ساخت بلاک‌های حرفه‌ای است؟ را ببینید.

ترتیب ویژگی‌ها

ترتیب ویژگی‌ها در JSON سریالایز‌شده تصادفی نیست. گوتنبرگ ویژگی‌ها را بر اساس ترتیب تعریف در block.json ذخیره می‌کند. این رویکرد باعث می‌شود که سریالایز یک بلاک در دو بار مختلف، دقیقاً یکسان باشد و اعتبارسنجی به‌درستی انجام شود. برای مطالعه بیشتر درباره ساختار فایل بلاک، مقاله ساختار فایل‌های یک افزونه استاندارد وردپرس را ببینید.

ذخیره ویژگی‌های پیچیده

ویژگی‌ها می‌توانند مقادیر پیچیده‌تری مانند آرایه یا شیء نیز داشته باشند. برای مثال، بلاک گالری ممکن است ویژگی ids داشته باشد که آرایه‌ای از شناسه‌های تصویر است. این ساختار به‌صورت زیر سریالایز می‌شود:

<!-- wp:gallery {"ids":[10,20,30]} -->

در این حالت، parser JSON را پارس کرده و آرایه را به‌عنوان مقدار ویژگی تنظیم می‌کند. این قابلیت برای بلاک‌های پیچیده ضروری است.

فرآیند Round-Trip: از ذخیره تا بارگذاری

فرآیند Round-Trip در Block Serialization شامل دو مرحله اصلی است: سریالایز در زمان ذخیره و دسریالایز در زمان بارگذاری. درک این فرآیند برای کار حرفه‌ای با گوتنبرگ ضروری است.

مرحله سریالایز (ذخیره)

در زمان ذخیره پست، ویرایشگر ساختار درختی بلاک‌ها را به یک رشته سریالایز‌شده تبدیل می‌کند. این فرآیند به‌صورت بازگشتی (Recursive) روی تمام بلاک‌ها اجرا می‌شود. برای هر بلاک، مراحل زیر انجام می‌گیرد:

  1. تولید کامنت بازکننده با نام بلاک و ویژگی‌های آن
  2. فراخوانی تابع save بلاک برای تولید HTML واقعی
  3. سریالایز بلاک‌های فرزند (در صورت وجود InnerBlocks)
  4. تولید کامنت بسته بلاک

در نهایت، تمام بلاک‌های سریالایز‌شده به‌ترتیب در کنار یکدیگر قرار می‌گیرند و رشته نهایی در فیلد post_content ذخیره می‌شود. برای مطالعه بیشتر درباره InnerBlocks، مقاله Synced Patterns در وردپرس چطور محتوا را در چند صفحه هماهنگ می‌کند؟ را ببینید.

مرحله دسریالایز (بارگذاری)

در زمان بارگذاری پست در ویرایشگر، فرآیند معکوس انجام می‌شود. parser گوتنبرگ رشته سریالایز‌شده را از پایگاه داده می‌خواند و آن را به ساختار درختی بلاک‌ها تبدیل می‌کند. مراحل این فرآیند عبارتند از:

  1. خواندن رشته از فیلد post_content
  2. تحلیل کامنت‌های مخصوص و تشخیص بلاک‌ها
  3. پارس کردن JSON ویژگی‌ها
  4. اعتبارسنجی HTML تولیدی با خروجی تابع save
  5. ساخت ساختار درختی بلاک‌ها

این فرآیند در هر بار بارگذاری ویرایشگر انجام می‌شود و به همین دلیل، عملکرد parser نقش کلیدی در سرعت ویرایشگر دارد. برای مطالعه بیشتر درباره عملکرد، مقاله useSelect و useDispatch در توسعه بلاک وردپرس چطور کار می‌کنند؟ را ببینید.

Round-Trip یک قرارداد است: هر چیزی که در زمان ذخیره سریالایز شود، باید در زمان بارگذاری به همان شکل بازگردانده شود؛ در غیر این صورت، بلاک نامعتبر می‌شود.

Parser گوتنبرگ و نحوه تحلیل

Parser گوتنبرگ یک کامپوننت اختصاصی است که رشته سریالایز‌شده را تحلیل کرده و ساختار بلاک‌ها را بازسازی می‌کند. این parser در پکیج @wordpress/blocks قرار دارد و از چندین مرحله تشکیل شده است.

تحلیل کامنت‌ها

اولین مرحله، تحلیل کامنت‌های مخصوص بلاک است. parser با استفاده از عبارات منظم، کامنت‌های <!-- wp: --> را در HTML پیدا می‌کند. برای هر کامنت، نام بلاک و ویژگی‌ها استخراج می‌شوند. این فرآیند باید دقیق باشد زیرا هر خطای جزئی می‌تواند به عدم تطبیق و بلاک نامعتبر منجر شود.

پارس کردن JSON

دومین مرحله، پارس کردن JSON ویژگی‌هاست. parser از یک تابع امن برای پارس JSON استفاده می‌کند که در صورت خطا، پیام مناسبی تولید می‌کند. این مرحله به‌ویژه در مورد ویژگی‌هایی که با کاراکترهای ویژه سریالایز شده‌اند، حساس است.

اعتبارسنجی HTML

سومین مرحله، اعتبارسنجی HTML تولیدی با خروجی تابع save است. parser ابتدا خروجی تابع save بلاک را با ویژگی‌های فعلی تولید می‌کند و سپس آن را با HTML واقعی موجود در رشته سریالایز‌شده مقایسه می‌نماید. اگر این دو یکسان نباشند، بلاک نامعتبر علامت‌گذاری می‌شود و به مکانیزم Deprecation مراجعه می‌گردد. برای مطالعه بیشتر درباره HTML، مقاله Static یا Dynamic Blocks در وردپرس؛ کدام انتخاب درست است؟ را ببینید.

بازسازی ساختار درختی

چهارمین مرحله، بازسازی ساختار درختی بلاک‌هاست. parser کامنت‌های بازکننده و بسته را جفت کرده و بلاک‌های تودرتو را به‌درستی در ساختار درختی قرار می‌دهد. این مرحله به‌ویژه در مورد بلاک‌های InnerBlocks پیچیده است زیرا باید سطوح تودرتویی به‌درستی مدیریت شوند. برای مطالعه بیشتر درباره معماری، مقاله Dynamic Blocks در وردپرس چیست و چرا رندر سرور مهم است؟ را ببینید.

سریالایز بلاک‌های تودرتو و InnerBlocks

سریالایز بلاک‌های تودرتو یکی از پیچیده‌ترین جنبه‌های Block Serialization است. بلاک‌هایی مانند Columns، Group و Cover می‌توانند بلاک‌های فرزند درون خود داشته باشند و این ساختار باید به‌درستی سریالایز شود.

ساختار سریالایز تودرتو

در بلاک‌های تودرتو، هر بلاک فرزند به‌صورت مستقل سریالایز می‌شود و درون بلاک والد قرار می‌گیرد. برای مثال، یک بلاک Columns با دو ستون که هر کدام یک پاراگراف دارند، به این صورت سریالایز می‌شود:

<!-- wp:columns -->
<div class="wp-block-columns">
<!-- wp:column -->
<div class="wp-block-column">
<!-- wp:paragraph -->
<p>ستون اول</p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:column -->
<!-- wp:column -->
<div class="wp-block-column">
<!-- wp:paragraph -->
<p>ستون دوم</p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:column -->
</div>
<!-- /wp:columns -->

در این ساختار، هر بلاک فرزند با کامنت‌های مخصوص خود مشخص شده است. parser با تحلیل این ساختار، درخت بلاک‌ها را بازسازی می‌کند. برای مطالعه بیشتر درباره InnerBlocks، مقاله آیا WordPress Interactivity API جایگزین React در وردپرس می‌شود؟ را ببینید.

چالش‌های سریالایز تودرتو

سریالایز تودرتو چند چالش دارد. اولین چالش، ترتیب کامنت‌ها است. parser باید بتواند کامنت بازکننده و بسته هر بلاک را به‌درستی جفت کند و این امر در ساختارهای عمیقاً تودرتو پیچیده می‌شود. دومین چالش، حفظ سازگاری در زمان ویرایش است. اگر کاربر یک بلاک فرزند را از یک سطح به سطح دیگر جابه‌جا کند، سریالایز باید به‌درستی ساختار جدید را منعکس کند. سومین چالش، عملکرد parser است که با افزایش عمق تودرتویی، کاهش می‌یابد.

بلاک‌های خودبسته در ساختار تودرتو

بلاک‌هایی که محتوای درونی ندارند (مانند بلاک تصویر) در ساختار تودرتو به‌صورت خودبسته سریالایز می‌شوند. این بلاک‌ها تنها یک کامنت دارند و parser با دیدن اسلش در انتها، آن‌ها را به‌عنوان بلاک خودبسته شناسایی می‌کند.

سریالایز در Dynamic Blocks

سریالایز در Dynamic Blocks تفاوت‌های مهمی با Static Blocks دارد. در Dynamic Blocks، تابع save مقدار null یا یک رشته خالی بازمی‌گرداند و به همین دلیل، HTML واقعی در سریالایز ذخیره نمی‌شود. در عوض، تنها کامنت بازکننده با ویژگی‌ها ذخیره می‌شود.

ساختار سریالایز Dynamic Block

یک Dynamic Block به این صورت سریالایز می‌شود:

<!-- wp:my-plugin/latest-posts {"numberOfPosts":5} /-->

توجه کنید که این بلاک خودبسته است و هیچ HTML واقعی درون آن وجود ندارد. در زمان بارگذاری، parser این کامنت را می‌خواند و ویژگی‌ها را استخراج می‌کند. سپس در فرانت‌اند، تابع render_callback با استفاده از این ویژگی‌ها، خروجی HTML را در زمان نمایش تولید می‌کند.

مزایای این رویکرد

این رویکرد چند مزیت دارد. اول، حجم محتوای ذخیره‌شده کاهش می‌یابد زیرا HTML واقعی ذخیره نمی‌شود. دوم، تغییر ساختار HTML در نسخه‌های بعدی نیازی به مهاجرت محتوا ندارد. سوم، امکان تولید خروجی پویا بر اساس context فراهم می‌شود.

محدودیت‌ها

در مقابل، Dynamic Blocks محدودیت‌هایی نیز دارند. مهم‌ترین محدودیت، عدم امکان ذخیره HTML واقعی برای اعتبارسنجی است. همچنین، در ویرایشگر برای نمایش پیش‌نمایش، باید از ServerSideRender استفاده شود که نیازمند درخواست HTTP است.

مثال عملی: دنبال کردن یک بلاک از ویرایشگر تا پایگاه داده

برای درک عملی Block Serialization، بیایید یک بلاک ساده را از لحظه ساخت در ویرایشگر تا ذخیره در پایگاه داده دنبال کنیم. این مثال به شما نشان می‌دهد که در هر مرحله چه اتفاقی می‌افتد.

مرحله اول: تعریف بلاک

registerBlockType( 'my-plugin/alert', {
  title: 'Alert',
  icon: 'warning',
  category: 'widgets',
  attributes: {
    message: { type: 'string', default: '' },
    type: { type: 'string', default: 'info' },
  },
  edit: ( { attributes, setAttributes } ) => {
    const blockProps = useBlockProps();
    return (
      <div { ...blockProps }>
        <RichText
          tagName="p"
          value={ attributes.message }
          onChange={ ( message ) => setAttributes( { message } ) }
        />
      </div>
    );
  },
  save: ( { attributes } ) => {
    const blockProps = useBlockProps.save( {
      className: `alert alert-${ attributes.type }`,
    } );
    return (
      <div { ...blockProps }>
        <p>{ attributes.message }</p>
      </div>
    );
  },
} );

مرحله دوم: سریالایز در ویرایشگر

هنگامی که کاربر محتوای بلاک را وارد می‌کند و پست را ذخیره می‌نماید، گوتنبرگ ساختار زیر را تولید می‌کند:

<!-- wp:my-plugin/alert {"message":"هشدار مهم","type":"warning"} -->
<div class="wp-block-my-plugin-alert alert alert-warning">
<p>هشدار مهم</p>
</div>
<!-- /wp:my-plugin/alert -->

مرحله سوم: ذخیره در پایگاه داده

این رشته در فیلد post_content جدول wp_posts ذخیره می‌شود. در اینجا، محتوا به‌صورت یک رشته HTML با کامنت‌های مخصوص گوتنبرگ قرار دارد. هیچ ساختار درختی در پایگاه داده ذخیره نمی‌شود.

مرحله چهارم: بارگذاری در ویرایشگر

زمانی که کاربر پست را دوباره در ویرایشگر باز می‌کند، parser گوتنبرگ این رشته را می‌خواند و مراحل زیر را انجام می‌دهد:

  1. کامنت بازکننده را پیدا می‌کند و نام بلاک (my-plugin/alert) و ویژگی‌ها ({"message":"هشدار مهم","type":"warning"}) را استخراج می‌کند.
  2. JSON ویژگی‌ها را پارس می‌کند و مقادیر را تنظیم می‌نماید.
  3. تابع save بلاک را با ویژگی‌های استخراج‌شده فراخوانی می‌کند تا HTML مرجع تولید شود.
  4. HTML مرجع را با HTML واقعی موجود در رشته مقایسه می‌کند.
  5. در صورت تطبیق، بلاک را معتبر می‌شناسد و آن را در ساختار درختی قرار می‌دهد.

این فرآیند در هر بار بارگذاری ویرایشگر انجام می‌شود و به همین دلیل، عملکرد parser اهمیت بالایی دارد.

هر بار که پست را در ویرایشگر باز می‌کنید، parser هزاران کامنت و تگ را تحلیل می‌کند تا ساختار بلاک‌ها را بازسازی کند؛ این فرآیندی است که در پس‌زمینه و بدون آنکه کاربر متوجه شود، اجرا می‌شود.

اعتبارسنجی و ارتباط با Deprecation

اعتبارسنجی، فرآیندی است که در زمان بارگذاری بلاک انجام می‌شود و صحت سریالایز را بررسی می‌کند. این فرآیند ارتباط تنگاتنگی با مکانیزم Deprecation دارد و درک آن برای کار حرفه‌ای با گوتنبرگ ضروری است.

الگوریتم اعتبارسنجی

الگوریتم اعتبارسنجی در گوتنبرگ به این صورت است: ابتدا خروجی تابع save نسخه فعلی با ویژگی‌های استخراج‌شده تولید می‌شود. سپس این خروجی با HTML واقعی موجود در رشته سریالایز‌شده مقایسه می‌گردد. مقایسه شامل ساختار تگ‌ها، کلاس‌ها، ویژگی‌ها و ترتیب عناصر است. اگر این دو یکسان باشند، بلاک معتبر است.

حساسیت به تغییرات جزئی

اعتبارسنجی به تغییرات جزئی بسیار حساس است. حتی تغییر یک فضای خالی، ترتیب کلاس‌ها یا نحوه سریالایز ویژگی‌ها می‌تواند باعث عدم تطبیق شود. برای مثال، اگر کلاس alert-warning در تابع save به warning-alert تغییر کند، بلاک نامعتبر می‌شود. برای مطالعه بیشتر درباره اصول کدنویسی تمیز، مقاله ساختار فایل‌های یک قالب استاندارد وردپرس را ببینید.

نقش Deprecation

زمانی که اعتبارسنجی شکست می‌خورد، گوتنبرگ به آرایه deprecated مراجعه می‌کند. هر نسخه deprecated شامل تابع save مخصوص خود است که HTML نسخه قدیمی را تولید می‌کند. اگر خروجی این تابع با HTML ذخیره‌شده مطابقت داشته باشد، بلاک به‌عنوان نسخه قدیمی شناسایی می‌شود و به نسخه فعلی مهاجرت می‌کند.

Impact بر توسعه‌دهنده

این مکانیزم پیامدهای مهمی برای توسعه‌دهنده دارد. هر تغییری در تابع save باید با تعریف یک نسخه deprecated همراه باشد. در غیر این صورت، محتوای ذخیره‌شده کاربران با خطای بلاک نامعتبر مواجه می‌شود.

دستکاری مستقیم محتوای سریالایز

در برخی پروژه‌ها، نیاز به دستکاری مستقیم محتوای سریالایز‌شده وجود دارد. برای مثال، یک افزونه ممکن است بخواهد به‌صورت برنامه‌نویسی یک بلاک را به محتوا اضافه کند یا ویژگی‌های یک بلاک را تغییر دهد. گوتنبرگ توابع متعددی برای این کار فراهم می‌کند.

توابع سریالایز و دسریالایز

پکیج @wordpress/blocks توابع serialize و parse را ارائه می‌دهد که به‌ترتیب برای تبدیل ساختار بلاک به رشته و برعکس استفاده می‌شوند.

import { serialize, parse } from '@wordpress/blocks';

// تبدیل ساختار بلاک به رشته
const blockString = serialize( block );

// تبدیل رشته به ساختار بلاک
const blocks = parse( blockString );

ساخت بلاک برنامه‌نویسی

برای ساخت یک بلاک به‌صورت برنامه‌نویسی، از تابع createBlock استفاده می‌شود:

import { createBlock } from '@wordpress/blocks';

const newBlock = createBlock( 'core/paragraph', {
  content: 'محتوای جدید',
} );

const serialized = serialize( newBlock );

دستکاری ویژگی‌ها

برای تغییر ویژگی‌های یک بلاک، از توابع getBlockAttributes و setBlockAttributes استفاده می‌شود. این توابع به شما امکان می‌دهند که ویژگی‌های یک بلاک را بخوانید، تغییر دهید و دوباره سریالایز کنید.

افزودن بلاک به محتوا

برای افزودن یک بلاک جدید به محتوای موجود، می‌توانید مراحل زیر را انجام دهید:

  1. محتوای موجود را با parse به ساختار بلاک تبدیل کنید.
  2. بلاک جدید را با createBlock بسازید.
  3. بلاک جدید را به آرایه بلاک‌ها اضافه کنید.
  4. محتوای جدید را با serialize به رشته تبدیل کنید.
  5. محتوای جدید را در پایگاه داده ذخیره کنید.
import { parse, serialize, createBlock } from '@wordpress/blocks';

const existingBlocks = parse( postContent );
const newBlock = createBlock( 'core/heading', {
  content: 'عنوان جدید',
  level: 2,
} );
existingBlocks.push( newBlock );
const updatedContent = serialize( existingBlocks );

عملکرد و حجم ذخیره‌سازی

Block Serialization از نظر عملکرد و حجم ذخیره‌سازی تأثیرات قابل‌توجهی دارد که باید در پروژه‌های بزرگ در نظر گرفته شود.

حجم ذخیره‌سازی

سریالایز کردن بلاک‌ها حجم محتوا را افزایش می‌دهد. کامنت‌های مخصوص بلاک، JSON ویژگی‌ها و تگ‌های HTML اضافی می‌توانند حجم محتوا را تا چند برابر افزایش دهند. در سایت‌هایی با محتوای زیاد، این افزایش حجم می‌تواند بر عملکرد پایگاه داده تأثیر بگذارد. برای مطالعه بیشتر درباره بهینه‌سازی پایگاه داده، مقاله Data API در وردپرس چیست و چطور state بلاک‌ها را مدیریت می‌کند؟ را ببینید.

سرعت parser

سرعت parser گوتنبرگ به تعداد و عمق بلاک‌ها بستگی دارد. هر بلاک اضافه، یک کامنت بازکننده و بسته دارد که parser باید تحلیل کند. در پست‌هایی با صدها بلاک، این فرآیند می‌تواند زمان‌بر باشد. بهینه‌سازی parser یکی از اولویت‌های تیم هسته وردپرس است.

بهینه‌سازی‌ها

گوتنبرگ چند بهینه‌سازی برای کاهش حجم و افزایش سرعت ارائه می‌دهد:

  • حذف ویژگی‌های پیش‌فرض از JSON
  • استفاده از کامنت‌های خودبسته برای بلاک‌های بدون محتوا
  • کش کردن نتایج parser در حافظه
  • استفاده از الگوریتم‌های بهینه برای تشخیص کامنت‌ها

تأثیر بر کش

محتوای سریالایز‌شده در کش‌های مختلف (Object Cache، Page Cache) ذخیره می‌شود. حجم بیشتر این محتوا می‌تواند بر کارایی کش تأثیر بگذارد. در پروژه‌های بزرگ، استفاده از کش لایه‌بندی‌شده توصیه می‌شود.

اشتباهات رایج در کار با سریالایز

در کار با Block Serialization، توسعه‌دهندگان اغلب مرتکب اشتباهاتی می‌شوند که منجر به کد شکننده یا از دست رفتن محتوا می‌شود. در ادامه به برخی از این اشتباهات اشاره می‌کنیم.

تغییر تابع save بدون Deprecation

رایج‌ترین اشتباه، تغییر تابع save بدون تعریف نسخه deprecated است. این کار باعث می‌شود که محتوای ذخیره‌شده با خطای بلاک نامعتبر مواجه شود. همیشه پس از تغییر تابع save، یک نسخه deprecated اضافه کنید. برای مطالعه بیشتر، مقاله Block Deprecation در وردپرس چیست و چرا نسخه‌های قدیمی بلاک را می‌شکند؟ را ببینید.

عدم تطابق ویژگی‌ها با HTML

اشتباه دیگر، عدم تطابق میان ویژگی‌های سریالایز‌شده و HTML واقعی است. اگر ویژگی align مقدار center داشته باشد اما کلاس CSS متناظر در HTML نباشد، اعتبارسنجی شکست می‌خورد. همیشه اطمینان حاصل کنید که ویژگی‌ها و HTML با یکدیگر هماهنگ هستند.

دستکاری مستقیم پایگاه داده

برخی توسعه‌دهندگان سعی می‌کنند محتوای سریالایز‌شده را به‌صورت مستقیم در پایگاه داده تغییر دهند. این کار خطرناک است زیرا ممکن است ساختار کامنت‌ها یا JSON را بشکند و بلاک‌ها را نامعتبر کند. همیشه از توابع گوتنبرگ برای دستکاری محتوا استفاده کنید.

نادیده گرفتن کاراکترهای ویژه

در سریالایز JSON، کاراکترهای ویژه مانند نقل قول دوگانه، بک‌اسلش و کاراکترهای کنترلی باید به‌درستی escape شوند. نادیده گرفتن این کاراکترها می‌تواند به خطای پارس JSON و بلاک نامعتبر منجر شود.

استفاده از HTML ناسازگار

در تابع save، باید HTML معتبر و سازگار با استانداردهای گوتنبرگ تولید شود. استفاده از تگ‌های منسوخ یا ویژگی‌های غیراستاندارد می‌تواند به شکست اعتبارسنجی منجر شود.

بیشتر خطاهای بلاک نامعتبر از عدم تطابق میان ویژگی‌ها و HTML ناشی می‌شوند؛ نه از پیچیدگی سریالایز.

عیب‌یابی مشکلات سریالایز

عیب‌یابی مسائل مربوط به Block Serialization نیازمند رویکردی سیستماتیک است. در ادامه به بررسی مراحل عیب‌یابی می‌پردازیم.

مرحله اول: بررسی کنسول مرورگر

اولین گام، بررسی کنسول مرورگر است. گوتنبرگ پیام‌های خطای دقیقی در کنسول نمایش می‌دهد که می‌تواند به شما در یافتن ریشه مشکل کمک کند. به‌دنبال پیام‌هایی مانند «Block validation failed» بگردید و جزئیات خطا را بررسی کنید.

مرحله دوم: مقایسه محتوای ذخیره‌شده با خروجی save

گام دوم، مقایسه محتوای ذخیره‌شده با خروجی تابع save است. می‌توانید از نمای HTML ویرایشگر (Code Editor) برای مشاهده محتوای ذخیره‌شده استفاده کنید. تفاوت‌های جزئی مانند فضای خالی، ترتیب ویژگی‌ها یا نام کلاس‌ها می‌توانند باعث خطا شوند.

مرحله سوم: بررسی ویژگی‌ها

گام سوم، بررسی ویژگی‌های سریالایز‌شده است. مطمئن شوید که JSON ویژگی‌ها معتبر است و مقادیر با انتظارات مطابقت دارند. از یک پارسر JSON آنلاین برای بررسی معتبر بودن JSON استفاده کنید.

مرحله چهارم: تست با محتوای نمونه

گام چهارم، تست با محتوای نمونه است. یک پست نمونه با محتوای سریالایز‌شده بسازید و آن را در ویرایشگر باز کنید. اگر بلاک نامعتبر است، می‌توانید مرحله‌به‌مرحله کد را بررسی کنید و تفاوت‌ها را بیابید.

مرحله پنجم: بررسی Deprecation

گام پنجم، بررسی مکانیزم Deprecation است. مطمئن شوید که نسخه‌های deprecated به‌درستی تعریف شده‌اند و ترتیب آن‌ها صحیح است. اگر نسخه‌ای از قلم افتاده باشد، بلاک نامعتبر باقی می‌ماند.

پرسش‌های پرتکرار درباره Block Serialization

Block Serialization چیست و چه تفاوتی با Serialization عمومی دارد؟

Block Serialization فرآیند تبدیل ساختار بلاک‌های گوتنبرگ به یک رشته HTML سریالایز‌شده است. برخلاف Serialization عمومی که در زبان‌های برنامه‌نویسی برای تبدیل اشیاء به بایت استفاده می‌شود، Block Serialization از HTML و کامنت‌های مخصوص برای نگهداری ساختار استفاده می‌کند.

چرا گوتنبرگ از کامنت HTML برای سریالایز استفاده می‌کند؟

کامنت‌های HTML در مرورگر نمایش داده نمی‌شوند و بر ظاهر صفحه تأثیری ندارند. از سوی دیگر، parserهای HTML به‌راحتی می‌توانند کامنت‌ها را تشخیص دهند. این رویکرد به گوتنبرگ اجازه می‌دهد که محتوای ساختاریافته را در فیلد متنی سنتی وردپرس ذخیره کند.

آیا می‌توانم محتوای سریالایز‌شده را به‌صورت دستی ویرایش کنم؟

توصیه نمی‌شود. ویرایش دستی می‌تواند ساختار کامنت‌ها یا JSON را بشکند و بلاک را نامعتبر کند. در صورت نیاز، از توابع گوتنبرگ برای دستکاری محتوا استفاده کنید.

تفاوت سریالایز در Static و Dynamic Blocks چیست؟

در Static Blocks، هم کامنت مخصوص و هم HTML واقعی سریالایز می‌شوند. در Dynamic Blocks، تابع save مقدار null بازمی‌گرداند و تنها کامنت مخصوص با ویژگی‌ها سریالایز می‌شود.

چه اتفاقی می‌افتد وقتی سریالایز شکست می‌خورد؟

در زمان بارگذاری، parser با شکست در تطبیق HTML، بلاک را نامعتبر علامت‌گذاری می‌کند. کاربر می‌تواند بلاک را به‌عنوان HTML خام تبدیل کند یا آن را نادیده بگیرد. در حالت ایده‌آل، مکانیزم Deprecation باید نسخه قدیمی را شناسایی و مهاجرت کند.

آیا سریالایز بر سرعت سایت تأثیر می‌گذارد؟

سریالایز و دسریالایز تنها در ویرایشگر انجام می‌شوند، نه در فرانت‌اند. بنابراین تأثیر مستقیمی بر سرعت سایت ندارند. اما حجم بیشتر محتوا در پایگاه داده می‌تواند بر عملکرد کوئری‌ها تأثیر بگذارد. برای مطالعه بیشتر، مقاله بهینه‌سازی دیتابیس وردپرس: چه چیزی واقعاً سرعت را بالا می‌برد؟ را ببینید.

چگونه می‌توانم محتوای سریالایز‌شده را در افزونه خود دستکاری کنم؟

از توابع parse، serialize، createBlock و getBlockAttributes در پکیج @wordpress/blocks استفاده کنید. این توابع امکان تحلیل، تغییر و بازسازی محتوا را فراهم می‌کنند.

آیا می‌توانم یک بلاک را از سریالایز حذف کنم؟

بله، با استفاده از parse می‌توانید محتوا را تحلیل کنید و بلاک مورد نظر را از آرایه حذف نمایید. سپس با serialize محتوای جدید را بسازید و ذخیره کنید.

آیا سریالایز از TypeScript پشتیبانی می‌کند؟

بله، پکیج‌های گوتنبرگ دارای type definition هستند و می‌توانید از آن‌ها در پروژه‌های TypeScript استفاده کنید. برای مطالعه بیشتر، مقاله چرا بدون React نمی‌توان بلاک حرفه‌ای در وردپرس ساخت؟ را ببینید.

آیا می‌توانم سریالایز را در سمت سرور نیز انجام دهم؟

خیر، توابع parse و serialize بخشی از پکیج‌های JavaScript گوتنبرگ هستند و در PHP معادل مستقیمی ندارند. در سمت سرور، محتوای سریالایز‌شده به‌صورت رشته ذخیره و مدیریت می‌شود.

آیا سریالایز بر سئو تأثیر می‌گذارد؟

کامنت‌های سریالایز در HTML به‌عنوان کامنت دیده می‌شوند و بر ایندکس شدن محتوا تأثیری ندارند. محتوای واقعی بلاک‌ها به‌صورت HTML معتبر در صفحه قرار می‌گیرد و موتورهای جستجو می‌توانند آن را بخوانند. برای مطالعه بیشتر، مقاله چرا HTML API در وردپرس امن‌ترین راه پردازش HTML است؟ را ببینید.

تحلیل معماری در سطح پیشرفته

از منظر معماری نرم‌افزار، Block Serialization یک پیاده‌سازی از الگوی Dual Representation است. در این الگو، یک ساختار داده در دو representation موازی نگهداری می‌شود: ساختار درختی در حافظه و representation سریالایز‌شده در پایگاه داده. این الگو امکان کار با ساختار درختی در سطح کد و ذخیره‌سازی ساده در سطح پایگاه داده را فراهم می‌کند.

یکی از جنبه‌های کمتر شناخته‌شده، نحوه تعامل سریالایز با Block Context است. در بلاک‌های تودرتو، Context به‌صورت مستقیم در سریالایز ذخیره نمی‌شود بلکه در زمان بارگذاری از ساختار درختی استخراج می‌گردد. این رویکرد باعث می‌شود که Context در صورت تغییر ساختار، به‌درستی به‌روزرسانی شود.

از منظر عملکرد، سریالایز یک trade-off میان سادگی ذخیره‌سازی و پیچیدگی تحلیل ایجاد می‌کند. ذخیره‌سازی یک رشته متنی ساده است، اما تحلیل آن در هر بار بارگذاری می‌تواند زمان‌بر باشد. تیم هسته وردپرس برای کاهش این هزینه، از تکنیک‌هایی مانند کش کردن نتایج parser و بهینه‌سازی الگوریتم‌های تشخیص کامنت استفاده می‌کند.

از منظر امنیت، سریالایز نیازمند توجه ویژه‌ای است. کاراکترهای ویژه در JSON و HTML باید به‌درستی escape شوند تا از آسیب‌پذیری‌هایی مانند XSS جلوگیری شود. همچنین، در زمان تحلیل محتوای سریالایز‌شده، باید از توابع امن برای پارس JSON و اعتبارسنجی HTML استفاده کرد. برای مطالعه بیشتر درباره امنیت، مقاله چرا InnerBlocks در وردپرس کلید ساخت بلاک‌های حرفه‌ای است؟ را ببینید.

از منظر قابلیت نگهداری، سریالایز یک سرمایه‌گذاری بلندمدت است. ساختار سریالایز‌شده در طول زمان تکامل می‌یابد و مکانیزم Deprecation امکان سازگاری با نسخه‌های قدیمی را فراهم می‌کند. این رویکرد مشابه مهاجرت اسکیمای پایگاه داده است، اما در سطح محتوا.

از منظر قابلیت آزمون‌پذیری، سریالایز امکان تست round-trip را فراهم می‌کند. می‌توانید یک ساختار بلاک بسازید، آن را سریالایز کنید، دوباره دسریالایز کنید و بررسی کنید که ساختار اصلی بازسازی شده است. این تست به‌ویژه در پروژه‌های بزرگ که چندین توسعه‌دهنده دارند، حیاتی است.

آینده Block Serialization

تیم هسته وردپرس در حال کار بر روی بهبود Block Serialization است. از جمله تحولات مورد انتظار می‌توان به پشتیبانی بهتر از TypeScript، بهبود عملکرد parser و ادغام بهتر با Block Bindings API اشاره کرد. Block Bindings API که در حال توسعه است، امکان اتصال ویژگی‌های بلاک به منابع داده خارجی را فراهم می‌کند و این امر می‌تواند سریالایز را متحول کند.

نکات کلیدی

  • Block Serialization فرآیند تبدیل ساختار بلاک به یک رشته HTML سریالایز‌شده است.
  • کامنت‌های مخصوص گوتنبرگ (<!-- wp: -->) لنگرهای ساختار بلاک هستند.
  • ویژگی‌ها به‌صورت JSON در کامنت بازکننده ذخیره می‌شوند.
  • فرآیند Round-Trip شامل سریالایز در زمان ذخیره و دسریالایز در زمان بارگذاری است.
  • اعتبارسنجی با مقایسه HTML ذخیره‌شده و خروجی تابع save انجام می‌شود.
  • در Dynamic Blocks، تنها کامنت مخصوص سریالایز می‌شود و HTML واقعی ذخیره نمی‌گردد.
  • هر تغییری در تابع save نیازمند تعریف نسخه deprecated است.
  • توابع parse و serialize امکان دستکاری برنامه‌نویسی محتوا را فراهم می‌کنند.
  • حجم محتوای سریالایز‌شده بیشتر از HTML خام است اما مزایای ساختاری آن را جبران می‌کند.
  • سریالایز بر سرعت فرانت‌اند تأثیری ندارد و تنها در ویرایشگر اجرا می‌شود.
  • همیشه از توابع گوتنبرگ برای دستکاری محتوا استفاده کنید، نه ویرایش مستقیم پایگاه داده.

اگر در پروژه‌ای با Block Serialization کار کرده‌اید، برایم جالب است بدانید کدام جنبه آن بیشترین چالش را برای شما ایجاد کرده است؛ به‌ویژه اگر راه‌حل خلاقانه‌ای برای دستکاری برنامه‌نویسی محتوا یا بهینه‌سازی حجم ذخیره‌سازی پیدا کرده‌اید که می‌تواند برای دیگران مفید باشد. تجربه خود را در دیدگاه‌ها بنویسید. 🚀