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

چرا بلوک سفارشی، وقتی افزونه‌های آماده زیاد است؟

در نگاه اول، ساخت بلوک سفارشی گوتنبرگ (Gutenberg، ویرایشگر بلوک پیش‌فرض وردپرس) شبیه اختراع دوباره چرخ به نظر می‌رسد. افزونه‌هایی مثل مجموعه‌های بزرگ بلوک در مخزن وردپرس وجود دارند که ده‌ها بلوک آماده ارائه می‌دهند. اما در پروژه‌های واقعی، سه دلیل قاطع وجود دارد که چرا بلوک سفارشی از افزونه‌های آماده جلو می‌زند.

وزن و سرعت

هر افزونه بلوک، ده‌ها بلوک را با خودش می‌آورد که شما از پنج یا شش تای‌شان استفاده می‌کنید. باقی بلوک‌ها، فایل‌های CSS و JS‌شان در بسته نصب می‌ماند و در برخی موارد حتی روی صفحه‌هایی که استفاده نمی‌شوند، لود می‌شوند. در پروژه‌ای که برای یک فروشگاه اینترنتی انجام دادم، حذف سه افزونه بلوک و جایگزینی‌شان با پنج بلوک سفارشی، حجم اولیه CSS و JS را حدود چهل درصد کاهش داد. این عدد در Core Web Vitals (شاخص‌های اصلی وب) و امتیاز PageSpeed مستقیماً اثر گذاشت.

تناسب دقیق با نیاز پروژه

هر پروژه‌ای که در آن چند ماه کار می‌کنید، در نهایت نیازها و الگوهای خاص خودش را پیدا می‌کند که در افزونه‌های عمومی وجود ندارد. مثلاً یک سایت خبری ممکن است به بلوکی برای نمایش «جفت خبر مرتبط» با منطق خاصی نیاز داشته باشد که در هیچ افزونه‌ای آماده نیست. یا یک فروشگاه آنلاین به بلوکی نیاز دارد که محصولات یک دسته را با فیلتر خاصی نشان دهد. در این موارد، ساخت بلوک سفارشی، تنها راه تمیز و سبک است.

کنترل روی نگهداری بلندمدت

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

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

مدل ذهنی گوتنبرگ: بلوک دقیقاً چیست؟

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

در ساده‌ترین تعریف، بلوک یک واحد محتوای قابل استفاده مجدد است که سه مؤلفه اصلی دارد:

مؤلفهنقشنمونه در کد
Editنمایش بلوک در ویرایشگر و تعامل با کاربرتابع Edit() در edit.js
Saveتولید HTML نهایی برای ذخیره در دیتابیستابع save() در save.js
Attributesمدیریت وضعیت داده بلوکشیء attributes در block.json

وقتی کاربر بلوکی را در ویرایشگر ویرایش می‌کند، React (کتابخانه جاوااسکریپت سمت رابط کاربری) مسئول رندر بخش ویرایشگر است. وقتی کاربر ذخیره می‌کند، تابع save اجرا می‌شود و خروجی HTML در جدول wp_posts ذخیره می‌شود. در بازدید بعدی، همان HTML از دیتابیس خوانده می‌شود بدون اینکه React دخالتی داشته باشد. این جداسازی، هسته معماری گوتنبرگ است.

نکته‌ای که در تجربه‌ام بسیار مهم بوده: خروجی save باید در تمام نسخه‌های بعدی بلوک، سازگار باقی بماند. اگر ساختار HTML خروجی عوض شود، وردپرس هشدار «Block validation failed» می‌دهد و بلوک‌های قدیمی از کار می‌افتند. این یکی از پرتکرارترین دام‌هایی است که توسعه‌دهندگان تازه‌کار در آن می‌افتند.

پیش‌نیازهای فنی و ساختار پروژه

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

  • JavaScript مدرن: آشنایی با ES6 (نسخه ششم استاندارد جاوااسکریپت)، توابع arrow، destructuring و module imports
  • React در سطح مقدماتی: ساخت کامپوننت، props و useState. اگر تازه‌کارید، مقاله React از صفر: ساخت رابط‌های کاربری تعاملی نقطه شروع خوبی است
  • Node.js و npm: برای نصب وابستگی‌ها و اجرای ابزار build
  • PHP در سطح پایه: برای ثبت بلوک در سمت سرور
  • آشنایی با هوک‌های وردپرس: به‌خصوص init و enqueue_block_editor_assets. مفهوم کامل هوک‌ها در هوک‌های وردپرس چیستند و چگونه کار می‌کنند توضیح داده شده است

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

ساختار پوشه بلوک

ساختار پروژه‌ای که در پروژه‌های خودم استاندارد کرده‌ام، به این شکل است:

wp-content/plugins/my-custom-blocks/
├── my-custom-blocks.php     ← فایل ثبت افزونه
├── package.json              ← وابستگی‌ها و اسکریپت‌ها
├── webpack.config.js         ← تنظیمات build
├── build/                    ← خروجی build (نصب نمی‌شود، تولید خودکار)
└── src/
    └── blocks/
        └── notice-box/
            ├── block.json
            ├── index.js
            ├── edit.js
            ├── save.js
            ├── editor.scss
            └── style.scss

این ساختار با ابزار @wordpress/scripts که خود وردپرس ارائه می‌دهد، هم‌خوانی کامل دارد. اگر با ساختار استاندارد افزونه‌ها آشنا نیستید، ساختار فایل‌های یک افزونه استاندارد وردپرس را ببینید؛ اصول یکی است.

block.json: شناسنامه بلوک مدرن

تا چند سال پیش، ثبت بلوک با یک فراخوانی registerBlockType در جاوااسکریپت انجام می‌شد. اما از وردپرس نسخه ۵.۸ به بعد، روش توصیه‌شده استفاده از فایل block.json است. این فایل، تنها منبع حقیقت درباره بلوک شماست و هم سمت جاوااسکریپت و هم سمت PHP از آن می‌خوانند.

نمونه فایل block.json برای یک بلوک ساده:

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "my-plugin/notice-box",
  "version": "1.0.0",
  "title": "جعبه اطلاع‌رسانی",
  "category": "widgets",
  "icon": "info-outline",
  "description": "یک جعبه برای نمایش پیام‌های اطلاع‌رسانی",
  "keywords": [ "notice", "alert", "پیام" ],
  "textdomain": "my-plugin",
  "attributes": {
    "content": {
      "type": "string",
      "source": "html",
      "selector": "p"
    },
    "variant": {
      "type": "string",
      "default": "info"
    }
  },
  "supports": {
    "align": true,
    "html": false
  },
  "editorScript": "file:./index.js",
  "editorStyle": "file:./editor.scss",
  "style": "file:./style.scss"
}

سه نکته مهم در این فایل که تجربه‌ام می‌گوید هر توسعه‌دهنده‌ای یک بار در آن‌ها گیر می‌کند:

  • apiVersion: 3: نسخه سه، ساختار توصیه‌شده امروز است. نسخه‌های پایین‌تر بعضی از قابلیت‌های جدید را پشتیبانی نمی‌کنند.
  • textdomain: حتماً با نام افزونه یکسان باشد. یکسان نبودن، باعث می‌شود رشته‌های ترجمه‌پذیر درست بارگذاری نشوند.
  • file:./ prefix: در بخش script و style، وقتی با file: شروع می‌کنید، وردپرس خودش مسیر و وابستگی‌ها را مدیریت می‌کند. اشتباه رایج، نوشتن مسیر absolute است که در build به مشکل می‌خورد.

برای ثبت بلوک در سمت PHP، کافی است در فایل اصلی افزونه این خط را اجرا کنید:

add_action( 'init', function() {
    register_block_type( __DIR__ . '/build/blocks/notice-box' );
} );

همین یک فراخوانی، هم جاوااسکریپت و هم استایل بلوک را بارگذاری می‌کند. تمام تنظیمات اضافی در block.json خوانده می‌شود. این سادگی، نتیجه معماری مدرن گوتنبرگ است.

ساخت اولین بلوک ساده در چند فایل

حالا یک بلوک واقعی بسازیم: یک جعبه اطلاع‌رسانی با سه حالت نمایش (info، warning، success). فایل index.js نقش نقطه ورود را دارد:

import { registerBlockType } from '@wordpress/blocks';
import Edit from './edit';
import save from './save';
import metadata from './block.json';

registerBlockType( metadata.name, {
  edit: Edit,
  save,
} );

فایل edit.js رابط ویرایشگر را می‌سازد:

import { useBlockProps, RichText, InspectorControls } from '@wordpress/block-editor';
import { PanelBody, SelectControl } from '@wordpress/components';
import './editor.scss';

export default function Edit( { attributes, setAttributes } ) {
  const { content, variant } = attributes;
  const blockProps = useBlockProps( { className: `notice-box notice-${variant}` } );

  return (
    <>
      <InspectorControls>
        <PanelBody title="تنظیمات">
          <SelectControl
            label="نوع پیام"
            value={ variant }
            options={ [
              { label: 'اطلاع‌رسانی', value: 'info' },
              { label: 'هشدار', value: 'warning' },
              { label: 'موفق', value: 'success' },
            ] }
            onChange={ ( val ) => setAttributes( { variant: val } ) }
          />
        </PanelBody>
      </InspectorControls>
      <div { ...blockProps }>
        <RichText
          tagName="p"
          value={ content }
          onChange={ ( val ) => setAttributes( { content: val } ) }
          placeholder="متن پیام را وارد کنید..."
        />
      </div>
    </>
  );
}

فایل save.js خروجی HTML نهایی را می‌سازد:

import { useBlockProps, RichText } from '@wordpress/block-editor';

export default function save( { attributes } ) {
  const { content, variant } = attributes;
  const blockProps = useBlockProps.save( { className: `notice-box notice-${variant}` } );

  return (
    <div { ...blockProps }>
      <RichText.Content tagName="p" value={ content } />
    </div>
  );
}

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

ساخت بلوک سفارشی، در ۹۰ درصد پروژه‌ها به چند فایل کوچک خلاصه می‌شود؛ پیچیدگی‌ای که در نگاه اول به‌نظر می‌رسد، واقعی نیست.

Attribute‌ها و مدیریت وضعیت داده در بلوک

Attribute‌ها، ستون فقرات بلوک شما هستند. هر چیزی که کاربر تغییر می‌دهد — متن، رنگ، اندازه، انتخاب‌ها — باید به‌عنوان یک attribute ذخیره شود. تفاوت مهمی که در تجربه‌ام بسیار حیاتی بوده: نوع داده attribute تعیین می‌کند که داده از کجا خوانده می‌شود.

نوع ذخیرهکاربردنمونه
source: html, selector: pاستخراج داده از HTML خروجیمحتوای متن
source: attribute, selector: img, attribute: srcخواندن از یک attribute مشخصآدرس تصویر
بدون sourceذخیره در comment delimiterشماره، بولی، آرایه
type: objectساختار پیچیدهتنظیمات چندگانه

اشتباه رایجی که در پروژه‌های مختلف دیده‌ام: توسعه‌دهنده یک attribute ساده با type string تعریف می‌کند، اما نمی‌داند که بدون source، مقدار آن در comment delimiter بلوک ذخیره می‌شود نه در HTML. این یعنی اگر کسی HTML را به‌صورت دستی تغییر دهد، مقدار attribute با واقعیت هم‌خوانی نخواهد داشت. برای درک بهتر ساختار کامنت‌های ذخیره‌سازی در وردپرس، ساختار فایل‌های یک قالب استاندارد وردپرس و نحوه ذخیره محتوای بلوکی را بررسی کنید.

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

در بعضی سناریوها، خروجی بلوک باید در هر بار نمایش بازسازی شود. مثلاً بلوکی که آخرین نوشته‌های یک دسته را نمایش می‌دهد، نمی‌تواند HTML ثابت داشته باشد چون محتوایش مرتب تغییر می‌کند. در این حالت، به‌جای تابع save، از render_callback در PHP استفاده می‌کنیم:

register_block_type( 'my-plugin/latest-posts', [
    'render_callback' => function( $attributes ) {
        $posts = get_posts( [
            'numberposts' => $attributes['count'] ?? 3,
            'category'    => $attributes['categoryId'] ?? 0,
        ] );
        ob_start();
        ?>
        <div class="latest-posts">
          <?php foreach ( $posts as $post ) : ?>
            <a href="<?php echo esc_url( get_permalink( $post ) ); ?>">
              <?php echo esc_html( get_the_title( $post ) ); ?>
            </a>
          <?php endforeach; ?>
        </div>
        <?php
        return ob_get_clean();
    },
] );

نکته حیاتی در بلوک‌های dynamic: چون خروجی در دیتابیس ذخیره نمی‌شود (فقط attribute‌ها در کامنت ذخیره می‌شوند)، می‌توانید هر زمان ساختار HTML را عوض کنید بدون نگرانی از خطای اعتبارسنجی بلوک. این انعطاف در بلوک‌های dynamic، یکی از بزرگ‌ترین مزیت‌های آن‌ها است. در مقابل، هزینه پردازشی هر نمایش صفحه بیشتر می‌شود چون هر بار کوئری اجرا می‌شود؛ پس اگر می‌توانید نتیجه را cache کنید، این کار را جدی بگیرید.

استایل‌دهی: تفاوت style و editor.css

یکی از ابهامات رایج برای تازه‌کارها، تفاوت بین style.scss و editor.scss است. این دو فایل، دو محیط متفاوت را هدف می‌گیرند:

  • style.scss: در سایت اصلی (frontend) بارگذاری می‌شود. استایل‌های نهایی که کاربر می‌بیند.
  • editor.scss: فقط در ویرایشگر بارگذاری می‌شود. برای استایل‌های اختصاصی که فقط در حالت ویرایش لازم است، مثل حاشیه دش‌دش برای بلوک‌های selected.

یک الگوی مفید که در پروژه‌هایم استفاده می‌کنم: استایل‌های مشترک را در style.scss بنویسید و بعد در editor.scss از آن import کنید. این کار باعث می‌شود در ویرایشگر و در سایت، بلوک یکسان دیده شود و کاربر غافلگیر نشود. همچنین برای جلوگیری از تعارض استایل با قالب‌های قدیمی، از پیشوند اختصاصی مثل my-plugin- استفاده کنید. اهمیت این رویکرد را در مقالات مربوط به استانداردهای کدنویسی وردپرس مفصل توضیح داده‌ام که یکی از بهترین مراجع‌شان استانداردهای کدنویسی وردپرس چیست است.

نکته دوم که در تجربه‌ام بسیار مؤثر بوده: تا می‌توانید استایل‌ها را کوچک و متمرکز نگه دارید. اگر بلوک شما فقط یک جعبه است، نیازی به یک فایل CSS صد خطی ندارد. CSS سبک، هم PageSpeed را بهتر می‌کند و هم نگهداری بلندمدت را آسان‌تر.

Block Patterns و Block Variations

پس از ساخت بلوک، قدم بعدی معمولاً ساخت الگوهای آماده (Block Patterns) و تنوع‌ها (Block Variations) است. این دو مفهوم، کار کاربر را بسیار راحت‌تر می‌کنند و در پروژه‌های حرفه‌ای، تفاوت جدی ایجاد می‌کنند.

Block Patterns

Pattern یک ترکیب آماده از چند بلوک است که کاربر می‌تواند با یک کلیک آن را به محتوا اضافه کند. مثلاً یک الگوی «بخش خدمات با سه ستون و آیکون» که از سه بلوک ستون و چند بلوک تصویر و متن ساخته شده. ثبت pattern ساده است:

register_block_pattern(
    'my-plugin/services-section',
    [
        'title'      => 'بخش خدمات',
        'categories' => [ 'services' ],
        'content'    => '...html of blocks...',
    ]
);

در پروژه‌های مشتری، pattern‌ها ابزار بسیار مؤثری برای آموزش کاربران به استفاده از بلوک‌ها هستند. کاربر لازم نیست بداند چطور سه بلوک را ترکیب کند؛ یک pattern می‌زند و ساختار آماده است.

Block Variations

Variation نسخه‌های از پیش تنظیم‌شده یک بلوک موجود است. مثلاً بلوک core/columns سه variation دارد: دو ستون، سه ستون و چهار ستون. شما می‌توانید برای بلوک‌های خودتان هم variation بسازید که attribute‌های خاصی را از پیش پر کنند. برای بلوکی مثل جعبه اطلاع‌رسانی که ساختیم، می‌توانید سه variation بسازید: «جعبه اطلاع‌رسانی»، «جعبه هشدار» و «جعبه موفقیت» که هر کدام variant پیش‌فرض متفاوتی دارند. برای آشنایی بیشتر با الگوهای ساختاری بلوک، ساخت ویجت اختصاصی با کدنویسی وردپرس دیدگاه مکمل خوبی ارائه می‌دهد.

دیباگ و تست بلوک سفارشی

اشکال‌زدایی بلوک‌های سفارشی می‌تواند سخت باشد، چون بخش عمده کد در سمت جاوااسکریپت اجرا می‌شود و خطاها همیشه واضح نیستند. در تجربه‌ام، سه ابزار و رویکرد اصلی در این مسیر کمک می‌کنند:

  1. کنسول مرورگر: همیشه باز باشد. اگر جاوااسکریپت خطا بدهد، بلوک شما بارگذاری نمی‌شود و ویرایشگر می‌تواند کاملاً بی‌واکنش شود. در بسیاری از موارد پیچیده، پیام خطای کنسول تنها سرنخ است. راهنمای کامل این ابزار در چگونه خطاهای جاوااسکریپت را در کنسول مرورگر پیدا کنیم آمده است.
  2. wp-scripts start: ابزار @wordpress/scripts اگر با start اجرا شود، حالت watch فعال می‌کند و در هر تغییر فایل، خودکار build می‌کند. این باعث می‌شود چرخه دیباگ سریع شود.
  3. WP_DEBUG در wp-config: در سمت PHP، خطاها را در debug.log ثبت می‌کند. اگر ثبت بلوک با خطای PHP شکست بخورد، این لاگ همه چیز را نشان می‌دهد.

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

اشتباهات رایج که پروژه را نابود می‌کند

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

تغییر ساختار save بدون migration

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

استفاده نکردن از useBlockProps

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

نادیده گرفتن ESC و sanitization

هر داده‌ای که از کاربر می‌گیرید و در سمت سرور نمایش می‌دهید، باید به‌درستی sanitize و escape شود. در بلوک‌های dynamic، این موضوع حیاتی است. تابع‌هایی مثل esc_html، esc_attr و esc_url را در پروژه‌های خودم به‌عنوان یک قاعده تغییرناپذیر در نظر می‌گیرم. اهمیت این موضوع را در مقالات مربوط به امنیت پروژه‌های وردپرسی مفصل توضیح داده‌ام و یکی از بهترین منابع فارسی آن چگونه توسعه وردپرس را برای امنیت آماده کنیم است.

بارگذاری بدون build و بدون استانداردها

بلوک سفارشی باید از یک ابزار build استاندارد مثل @wordpress/scripts استفاده کند. نوشتن بلوک به‌صورت دستی با فایل‌های ES5، در پروژه‌های امروز کاملاً غیرحرفه‌ای است. علاوه بر این، رعایت استانداردهای کدنویسی وردپرس، از روز اول پروژه را برای نگهداری آماده می‌کند. مرور استانداردهای کدنویسی از طریق استفاده از WordPress Coding Standards در پروژه‌ها مسیر کاربردی این کار است.

کوچک در نظر گرفتن حجم داده attribute

هر چیزی که در attribute ذخیره می‌شود، به‌عنوان یک کامنت در HTML ذخیره می‌شود. اگر داده سنگینی مثل آرایه بزرگی از داده‌ها را در attribute بریزید، حجم صفحه و پست به‌سرعت بالا می‌رود و در حجم زیاد، کارایی پایین می‌آید. برای داده‌های بزرگ، بهتر است از dynamic block با ذخیره در متادیتا یا جداول اختصاصی استفاده کنید.

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

آیا ساخت بلوک سفارشی برای یک توسعه‌دهنده تازه‌کار مناسب است؟

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

بلوک سفارشی چه تفاوتی با شورتکد دارد و کدام بهتر است؟

شورتکد (Shortcode) یک تگ کوتاه است که در متن جایگزین محتوای پیچیده می‌شود. بلوک، جایگزین مدرن و مبتنی بر React است. تفاوت اصلی: بلوک تجربه کاربری بصری می‌دهد و داده‌ها ساختارمند ذخیره می‌شوند؛ شورتکد فقط یک تگ ساده در متن است. در پروژه‌های امروز، بلوک انتخاب بهتری است چون ویرایشگر گوتنبرگ مسیر آینده وردپرس است. اگر هنوز با شورتکد آشنایی ندارید، ساخت شورت‌کد با کدنویسی وردپرس نقطه مقایسه خوبی است.

کد بلوک سفارشی باید در افزونه باشد یا قالب؟

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

آیا استفاده از block.json الزامی است؟

الزامی نیست اما توصیه‌شده است. بلوک‌های قدیمی‌تر بدون block.json هم کار می‌کنند، اما استفاده از این فایل مزایای جدی دارد: کد تمیزتر، بارگذاری هوشمندتر asset‌ها، سازگاری بهتر با ابزارهای توسعه و امکان مدیریت آسان‌تر از یک منبع واحد. در پروژه‌های جدید، همیشه با block.json شروع کنید.

اگر بخواهم بلوک را در پروژه‌ای با Node.js قدیمی بسازم، مشکل می‌خورد؟

بله، احتمالاً. @wordpress/scripts نسخه‌های جدید نیازمند Node.js حداقل نسخه ۱۸ است. اگر پروژه شما روی محیطی با نسخه قدیمی‌تر اجرا می‌شود، یا باید Node.js را به‌روز کنید یا از نسخه‌های قدیمی‌تر ابزار استفاده کنید. توصیه من به‌روزرسانی Node.js است، چون باقی ماندن روی نسخه‌های قدیمی، در آینده دردسرهای بیشتری ایجاد می‌کند.

چطور می‌توانم پیش‌نمایش زنده برای بلوک بسازم؟

برای بلوک‌های استاتیک، ویرایشگر گوتنبرگ خودش پیش‌نمایش زنده است چون edit و save یکسان رندر می‌شوند. برای بلوک‌های dynamic، می‌توانید از ServerSideRender استفاده کنید که در ویرایشگر، خروجی رندر شده از سرور را نمایش می‌دهد. اما حواستان باشد که ServerSideRender هزینه پردازشی دارد و در بلوک‌های پرمصرف، ویرایشگر می‌تواند کند شود.

چطور بلوک را برای ترجمه آماده کنم؟

سه کار کلیدی: یک، استفاده از توابع ترجمه در JavaScript (__() و _e() از پکیج @wordpress/i18n) و در PHP. دو، تعریف textdomain در block.json و مطابقت آن با نام افزونه. سه، تولید فایل .pot با ابزارهایی مثل WP-CLI و ترجمه از طریق Poedit. مسیر کامل در مستندات رسمی وردپرس توضیح داده شده است.

آنچه در نهایت باقی می‌ماند

پس از چند سال کار با گوتنبرگ و ساخت ده‌ها بلوک سفارشی، چیزی که برایم به یک اصل تبدیل شده این است: بلوک سفارشی، یک مهارت است نه یک تکنیک. یعنی با آن، نه‌فقط یک قابلیت به سایت اضافه می‌کنید، بلکه درک شما از معماری وردپرس به‌طور کلی عمیق‌تر می‌شود. مسائل مربوط به state، ذخیره‌سازی داده، مدیریت asset و امنیت در همه بلوک‌ها تکرار می‌شوند و همین تکرار، مهارت شما را تیز می‌کند.

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

اگر تجربه‌ای از ساخت بلوک سفارشی دارید — به‌خصوص اگر با دام‌هایی مثل خطای Block validation یا تعارض با افزونه‌های دیگر مواجه شده‌اید — در دیدگاه‌ها بنویسید. این تجربه‌ها برای خواننده بعدی، از هر مستند رسمی ارزشمندترند. 🧱