WordPress 2025 đang thay đổi thế nào – từ Query Loop đến Block Data Layer

WordPress 2025 đã đi qua thời “cài plugin là xong”. Cuộc chơi giờ xoay quanh block-first: Query Loop ngày càng trưởng thành, block data layer giúp đọc ghi dữ liệu mượt như app, và Interactivity API khiến UI phản hồi tức thì mà vẫn giữ SSR/SEO chuẩn chỉnh. Bài này tóm gọn điều quan trọng nhất để bạn cập nhật stack, viết block “sạch” và tăng tốc site thật sự.

WordPress 2025 đang thay đổi thế nào – từ Query Loop đến Block Data Layer

Điểm nhanh những thay đổi đáng chú ý

  • Query Loop trưởng thành: ít “hack” PHP hơn, cấu hình được nhiều biến thể (variations), dễ tái dùng với Patterns.
  • Block Data Layer (dựa trên @wordpress/data): đọc/ghi nội dung, taxonomy, media qua store đồng nhất, cache tốt, dễ test.
  • Interactivity API: thêm hành vi client (state, actions) mà không cần SPA, vẫn SSR, vẫn Progressive Enhancement.
  • Block Bindings: ràng buộc block với meta/option/taxonomy, giảm code “dán keo” trong render.
  • Theme.json + Style Variations: đẩy thiết kế vào cấu hình, đồng bộ design-tokens và giảm CSS thủ công.

1. Query Loop – từ “tiện lợi” đến “chuẩn sản xuất”

Query Loop không chỉ là block lặp bài viết. Ở 2025, bạn nên coi nó là lớp trình bày, để phần dữ liệu chuyển dần sang block attributes + variations + Patterns thay vì viết PHP custom query rải rác.

Thực chiến: tạo biến thể (variation) cho Query Loop

Tạo một biến thể hiển thị truyện/manga nổi bật mà không phải forkhard.

{
  "name": "init/query-loop-featured",
  "title": "Query: Truyện nổi bật",
  "parent": [ "core/query" ],
  "attributes": {
    "query": {
      "perPage": 6,
      "postType": [ "manga" ],
      "order": "desc",
      "orderBy": "date",
      "sticky": "only"
    },
    "displayLayout": { "type": "grid", "columns": 3 }
  },
  "scope": [ "inserter" ]
}

Lợi ích: biên tập viên chỉ việc chèn “Query: Truyện nổi bật”, không đụng tới tham số nâng cao. Bạn quản lý logic truy vấn tập trung.

Khi nào vẫn nên dùng PHP custom (và tối ưu ngay)

<?php
$q = new WP_Query([
  'post_type'              => 'manga',
  'fields'                 => 'ids',           // chỉ lấy ID cho nhẹ
  'posts_per_page'         => 12,
  'no_found_rows'          => true,            // không cần phân trang
  'update_post_meta_cache' => false,
  'update_post_term_cache' => false,
  'meta_query'             => [
    [ 'key' => 'score', 'value' => 7, 'compare' => '>=', 'type' => 'NUMERIC' ]
  ],
  'orderby'                => 'meta_value_num',
  'meta_key'               => 'score'
]);

foreach ( $q->posts as $post_id ) {
  // Render nhẹ: tự lấy đúng meta cần, tránh kéo cả post object to đùng
}

Nguyên tắc vàng: “chỉ lấy thứ mình cần” + “tắt cache phụ khi không dùng” để tránh phình RAM.

2. Block Data Layer – đọc/ghi dữ liệu như ứng dụng

Thay vì tự gọi REST/SQL tùy tiện, dùng @wordpress/data và các store lõi (core, core/editor, v.v.) để đồng bộ state, caching, và tối ưu re-render.

Ví dụ: lấy danh sách bài viết & đếm tổng qua store

import { select, resolveSelect } from '@wordpress/data';

// Đọc đồng bộ từ cache (nếu có)
const posts = select('core').getEntityRecords('postType', 'post', { per_page: 5 });

// Đọc có chờ (tự fetch nếu chưa có)
const fetchPosts = async () => {
  const list = await resolveSelect('core').getEntityRecords('postType', 'post', { per_page: 5 });
  const count = select('core').getEntityRecordsTotalItems? 
    select('core').getEntityRecordsTotalItems('postType', 'post') : list?.length;
  console.log({ list, count });
};

Tip: gói logic vào custom hook (React) để tái sử dụng trong block edit.

3. Interactivity API – UI phản hồi nhanh, vẫn SSR

Thêm trạng thái và hành vi ngay trong HTML via data-wp-* mà không cần SPA. Phù hợp cho filter nhỏ, like button, load-more…

Ví dụ: nút “Load more” cho danh sách

<div
  data-wp-interactive
  data-wp-context='{"page":1,"loading":false}'
  data-wp-watch='callbacks.onMount'
>
  <ul data-wp-bind--innerHTML="state.itemsHTML"></ul>

  <button
    data-wp-on--click="actions.loadMore"
    data-wp-bind--disabled="state.loading"
  >Load more</button>
</div>
export default {
  state: {
    page: 1,
    loading: false,
    itemsHTML: ''
  },
  callbacks: {
    onMount( { state, actions } ) {
      actions.loadMore();
    }
  },
  actions: {
    async loadMore( { state, element } ) {
      if (state.loading) return;
      state.loading = true;
      const res = await fetch(`/wp-json/wp/v2/posts?per_page=5&page=${state.page}`);
      const data = await res.json();
      const html = data.map(p => `<li><a href="${p.link}">${p.title.rendered}</a></li>`).join('');
      state.itemsHTML += html;
      state.page += 1;
      state.loading = false;
    }
  }
};

Điểm ăn tiền: markup đầu tiên vẫn SSR nên SEO tốt, JS chỉ “nâng cấp” hành vi.

4. Block Bindings – ràng buộc dữ liệu không cần “bóc” thủ công

Rút ngắn khoảng cách giữa dữ liệu và giao diện: bind trực tiếp post meta/option cho block Text/Paragraph, hạn chế render callback phức tạp.

Ví dụ: bind Paragraph vào post meta summary

{
  "version": 3,
  "name": "init/bound-summary",
  "title": "Bound Summary",
  "parent": [ "core/paragraph" ],
  "usesContext": [ "postId", "postType" ],
  "attributes": {
    "content": {
      "type": "string",
      "__experimentalRole": "content",
      "__experimentalBinding": {
        "source": "core/post-meta",
        "args": { "key": "summary" }
      }
    }
  }
}

Kết quả: Block Paragraph tự hiển thị/ghi nội dung meta summary của bài viết hiện tại.

5. Theme.json & Style Variations – dồn sức cho design-tokens

Đưa màu, font, spacing, radius… vào theme.json để editor và frontend đồng bộ. Dùng Style Variations tạo “skin” khác nhau mà không forktheme.

Mẫu theme.json tinh gọn

{
  "version": 3,
  "settings": {
    "color": {
      "palette": [
        { "slug": "primary", "color": "#5435ff", "name": "Primary" },
        { "slug": "ink", "color": "#1f2328", "name": "Ink" }
      ]
    },
    "spacing": { "units": [ "px", "rem" ], "blockGap": "1rem" },
    "typography": { "fontFamilies": [ { "fontFamily": "Inter, system-ui", "slug": "inter" } ] }
  },
  "styles": {
    "elements": {
      "button": { "border": { "radius": "999px" } }
    }
  }
}

6. Server-rendered block (render_callback) + cache “đúng cách”

Khi cần logic nặng, cứ SSR block nhưng nhớ cache theo attributes để tránh render lại vô ích.

<?php
register_block_type( 'init/featured-manga', [
  'render_callback' => function( $atts, $content, $block ) {
    $key = 'init_fm_' . md5( wp_json_encode( $atts ) );
    $html = get_transient( $key );
    if ( false === $html ) {
      $ids = get_posts([
        'post_type' => 'manga',
        'fields'    => 'ids',
        'numberposts' => 6,
        'meta_key'  => 'score',
        'orderby'   => 'meta_value_num',
        'order'     => 'DESC',
        'suppress_filters' => true
      ]);
      ob_start();
      echo '<ul class="init-featured">';
      foreach ( $ids as $id ) {
        echo '<li><a href="' . esc_url( get_permalink( $id ) ) . '">' . esc_html( get_the_title( $id ) ) . '</a></li>';
      }
      echo '</ul>';
      $html = ob_get_clean();
      set_transient( $key, $html, 15 * MINUTE_IN_SECONDS );
    }
    return $html;
  }
] );

7. Checklist “nâng cấp tư duy 2025”

  • Ưu tiên Query Loop + Variations + Patterns, hạn chế PHP template rời rạc.
  • Đọc/ghi dữ liệu qua Data Layer, tránh viết fetch tự do gây lệch state/caching.
  • Thêm tương tác bằng Interactivity API trước khi nghĩ tới SPA.
  • Ràng buộc dữ liệu bằng Block Bindings để giảm boilerplate.
  • Theme.json làm trung tâm cho tokens và style variations.
  • SSR block & cache theo thuộc tính với transient/object cache.

8. Anti-patterns nên bỏ ngay

  • Nhồi WP_Query trong mọi block nhỏ → hãy gom và cache.
  • Dùng posts_per_page=-1 + load cả post object → chuyển sang fields="ids".
  • Gắn JS rời rạc, không theo Data/Interactivity → khó bảo trì, khó test.
  • CSS rải rác file → đưa vào theme.json và block styles.

Kết

Nếu 2019 là năm của “custom functions + plugin”, thì 2025 là năm của “block-first”. Hãy để Query Loop, Data Layer, Interactivity và Bindings làm nền; còn bạn tập trung vào trải nghiệm, tối ưutính đơn giản. Làm đúng, site nhanh hơn, code sạch hơn, và team biên tập cũng hạnh phúc hơn.

Bình luận


  • Không có bình luận.

Init Toolbox

Nhấn Ctrl + \ trên máy tính, hoặc vuốt sang trái ở bất kỳ đâu trên mobile.

Đăng nhập





Đang tải...