Desarrollo de bloques personalizados de Gutenberg sin dependencias externas

Crear bloques de Gutenberg sin usar herramientas externas (npm, webpack, React desde paquetes, etc.) es una opción práctica cuando se busca simplicidad, menores requisitos de infraestructura y tiempos de despliegue rápidos. En esta guía profesional veremos cómo diseñar, registrar y optimizar bloques usando solo PHP y JavaScript vanilla, manteniendo buenas prácticas de seguridad, rendimiento y compatibilidad con WordPress.

Por qué crear bloques sin dependencias externas

Las ventajas de prescindir de dependencias y de procesos de build son claras en proyectos pequeños o en entornos con restricciones de servidor:

  • Despliegue más sencillo: basta subir archivos PHP/JS/CSS al servidor.
  • Menor superficie de fallo: menos herramientas, menos incompatibilidades.
  • Mayor control sobre el rendimiento y la carga de recursos.
  • Evitas problemas con pipelines CI/CD complejos en servidores de hosting compartido.

Eso sí, hay que asumir límites: para bloques muy complejos o aplicaciones SPA, las herramientas modernas pueden ser más eficientes. Esta guía se enfoca en bloques útiles, sencillos y mantenibles sin bundlers.

Preparación del entorno

Requisitos mínimos:

  • WordPress 5.0+ con editor Gutenberg activo.
  • Acceso para editar/añadir archivos del tema o plugin (recomendado: plugin propio para bloques).
  • Conocimientos básicos de PHP y JavaScript (ES5/ES6 según tu servidor).

Recomendaciones técnicas:

  • Usa PHP 7.4+ por rendimiento y seguridad; consulta la documentación oficial en PHP.net.
  • Escribe JavaScript que funcione en la mayoría de navegadores o añade polyfills puntuales. Consulta MDN Web Docs para compatibilidad y buenas prácticas.

Estructura básica de un bloque sin dependencias

Organiza tu plugin con una estructura simple:

  • my-block-plugin/
    • my-block-plugin.php
    • build/ (opcional)
    • js/block-editor.js
    • css/editor.css
    • css/style.css

Registro en PHP

Registra el bloque y encola los scripts usando las APIs nativas. Ejemplo mínimo en el archivo principal del plugin:

<?php
/**
 * Plugin Name: My Simple Block
 */

function msb_register_block() {
    wp_register_script(
        'msb-block-editor',
        plugins_url( 'js/block-editor.js', __FILE__ ),
        array( 'wp-blocks', 'wp-element', 'wp-editor' ),
        filemtime( plugin_dir_path( __FILE__ ) . 'js/block-editor.js' )
    );

    wp_register_style(
        'msb-editor-style',
        plugins_url( 'css/editor.css', __FILE__ ),
        array(),
        filemtime( plugin_dir_path( __FILE__ ) . 'css/editor.css' )
    );

    register_block_type( 'msb/simple', array(
        'editor_script' => 'msb-block-editor',
        'editor_style'  => 'msb-editor-style',
        'style'         => 'msb-style',
    ) );
}
add_action( 'init', 'msb_register_block' );
?>

Observaciones:

  • Usamos las dependencias globales de WordPress (wp-blocks, wp-element) que ya están presentes en el editor; no añadimos paquetes externos.
  • filemtime() ayuda a bustear caché en desarrollo. En producción usa versiones semánticas cuando sea posible.
  • register_block_type es una función PHP nativa documentada en PHP.net y en la documentación de WordPress.

JavaScript del bloque (sin build)

Puedes escribir el JavaScript en ES5 o ES6 (evita features no soportadas si no añades polyfills). Ejemplo simple usando la API global wp:

( function( wp ) {
    var el = wp.element.createElement;
    var registerBlockType = wp.blocks.registerBlockType;

    registerBlockType( 'msb/simple', {
        title: 'Mi Bloque Simple',
        category: 'common',
        attributes: {
            content: { type: 'string' }
        },
        edit: function( props ) {
            function onChangeContent( event ) {
                props.setAttributes( { content: event.target.value } );
            }
            return el( 'div', { className: props.className },
                el( 'textarea', {
                    value: props.attributes.content || '',
                    onChange: onChangeContent,
                    placeholder: 'Escribe algo...'
                } )
            );
        },
        save: function( props ) {
            return el( 'div', null, wp.htmlEntities ? wp.htmlEntities(props.attributes.content) : props.attributes.content );
        }
    } );
} )( window.wp );

Notas técnicas:

  • Usamos window.wp que WordPress inyecta en el editor; no es necesario instalar React o paquetes npm.
  • Para escapar HTML en front-end puedes usar funciones de servidor o utilidades seguras; evita inyectar contenido sin sanitizar.

Buenas prácticas de seguridad y rendimiento

Al no usar bundlers pierdes control automático sobre tree-shaking o minificación. Aplica estas prácticas:

  • Minifica manualmente los archivos JS/CSS para producción. Herramientas online o tareas locales sencillas bastan.
  • Desinfecta atributos y usa funciones de escape en PHP (por ejemplo, esc_html, wp_kses).
  • Evita encolar scripts en el front-end si solo se usan en el editor; usa editor_script en register_block_type.
  • Usa versiones y cache busting para evitar problemas con CDN o proxies.

Para recomendaciones avanzadas de rendimiento, consulta las guías de Google Developers sobre optimización web: Google Developers.

Ejemplo real: bloque de llamada a la acción (CTA)

Un bloque CTA suele necesitar título, texto y botón. Estructura mínima usando solo JavaScript y render en PHP para seguridad:

1) Definición de atributos

  • title (string)
  • text (string)
  • url (string)

2) Render en el servidor (callback render)

Para mayor seguridad y SEO, puedes usar render callback en PHP:

register_block_type( 'msb/cta', array(
    'editor_script' => 'msb-block-editor',
    'render_callback' => 'msb_render_cta'
) );

function msb_render_cta( $attributes ) {
    $title = isset( $attributes['title'] ) ? esc_html( $attributes['title'] ) : '';
    $text  = isset( $attributes['text'] ) ? wp_kses_post( $attributes['text'] ) : '';
    $url   = isset( $attributes['url'] ) ? esc_url( $attributes['url'] ) : '';

    ob_start();
    ?>
    <div class="msb-cta">
        <h3>" class="msb-cta-button">Acción</a>
    </div>
    

Ventajas de este enfoque:

  • El HTML final está sanitizado en servidor.
  • Mejor SEO y control sobre marcado.
  • Compatibilidad con cachés y CDNs.

Compatibilidad y pruebas

Prueba en distintos entornos antes de producción:

  • Edición: editor de bloques en dispositivos móviles y escritorio.
  • Visualización: distintos navegadores y tamaños de pantalla (consulta MDN para compatibilidad CSS/JS).
  • Performance: tiempo de carga del editor y peso de los assets. Revisa recomendaciones de Lighthouse en Google Developers.

Cuando considerar herramientas y bundlers

Evitar dependencias es viable, pero hay escenarios donde las herramientas son recomendables:

  • Bloques con lógica compleja, múltiples dependencias o librerías externas.
  • Necesidad de modularidad, Tree-shaking o compatibilidad con ES Modules moderna.
  • Proyectos con equipos grandes y pipelines CI/CD donde automatizar builds reduce errores.

Si llegas a ese punto, migrar a un flujo con @wordpress/scripts o bundlers como webpack facilita la gestión. Para proyectos ligeros, la estrategia sin dependencias es más rápida y más fácil de mantener en servidores controlados.

Resumen y checklist para producción

Checklist antes del despliegue:

  • Minificar JS y CSS y versionar assets.
  • Escapar y sanitizar todos los datos en PHP.
  • Encolar solo lo necesario en el editor (no en front-end salvo que haga falta).
  • Probar accesibilidad y compatibilidad entre navegadores.
  • Monitorizar rendimiento tras el despliegue y ajustar cachés/CDN.

Conclusión

Desarrollar bloques personalizados de Gutenberg sin dependencias externas es una estrategia práctica, segura y eficiente para proyectos contenidos o cuando la infraestructura limita el uso de herramientas modernas. Con una estructura clara, encolado correcto desde PHP, JavaScript vanilla usando la API global de WordPress y renderizado seguro en servidor, puedes ofrecer bloques útiles y optimizados sin incorporar complejidad innecesaria. Para casos de mayor complejidad, evalúa introducir bundlers y pipelines, pero comienza por una base sólida: código limpio, escapado y versiones controladas.

Si quieres ejemplos adicionales o un plugin de referencia listo para instalar, puedo generar el código completo y las instrucciones paso a paso adaptadas a tu entorno de hosting.