¡Compártelo!

Node js 25 y Strapi 5: lo que funciona de verdad (y cómo lo montaría yo) 

Si estás montando o migrando un headless CMS hoy, la combinación típica es Strapi 5 como backend y un frontend tipo Next.js, Nuxt o Astro. Pero luego llega la típica duda que te hace perder una tarde: “¿Qué versión de Node pongo para no pelearme con compatibilidades, y qué gano realmente si salto a lo último?”.

Este artículo va justo de eso. Nada de humo: qué versiones encajan en febrero de 2026, qué cambios de Node afectan de verdad a un CMS, qué cambia en Strapi 5 a nivel de API y un ejemplo práctico con código para que no se quede en teoría.

Qué versiones de Node 25 y Strapi 5 usar (febrero 2026) y por qué 

Node sigue un ciclo bastante estable: las versiones pares acaban entrando en LTS y son las que quieres para producción; las impares son Current, útiles para probar lo nuevo, pero no para montar un negocio encima sin una buena razón.

A febrero de 2026, el panorama real es:

  • Node 24 (Krypton) está en Active LTS.
  • Node 22 está en Maintenance LTS (sigue siendo muy válido, pero ya no es “lo último”).
  • Node 25 es Current.

¿Y Strapi 5 qué? Aquí hay un matiz importante.

En las docs oficiales de instalación y despliegue, Strapi sigue diciendo “actualmente v20 y v22” como soportadas.

Pero a nivel de producto, Strapi añadió soporte para Node 24 a partir de Strapi 5.31 (aparece en las release notes).

Mi recomendación práctica, sin postureo:

  • Si estás empezando un proyecto nuevo y vas con Strapi 5.31 o superior, Node 24 es la opción “moderna y sensata”.
  • Si tu proyecto depende de muchos plugins de la comunidad o integraciones raras, Node 22 suele ser la ruta con menos sorpresas. 
  • Node 25 lo dejaría para staging y pruebas, salvo que tengas un motivo concreto y lo tengas validado.

Un apunte realista: aunque el core soporte Node 24, el ecosistema a veces va tarde (CLI, engines en plugins, etc.). Si te salta el típico “Strapi requires Node <= 22” al crear un proyecto, la solución suele ser crear con Node 22 y luego mover el runtime a Node 24 cuando ya estás en una versión de Strapi que lo soporte bien. Esto ha pasado y está reportado en issues.

Qué trae Node 25 que de verdad te afecta en un CMS 

Rendimiento: JSON.stringifiy y V8

Para un headless CMS, la vida es JSON. Mucho JSON. Node 25 sube V8 a 14.1 y menciona mejoras grandes en JSON.stringifiy. En APIs con respuestas pesadas se nota, aunque obviamente depende de tu carga real.

TypeScript “nativo”: Node ejecuta TypeScript eliminando tipos (no hace type checking) y esto es estable desde Node 25.2.0. En Node 22.18.0 se habilita por defiecto.

Traducción práctica: te puede simplificar scripts, tooling y cosas internas, pero no significa que mágicamente desaparezcan los builds en proyectos grandes. Y si usas sintaxis no “erasable” (enum, parameter properties, etc.) necesitas el flag de transformación o seguir compilando como siempre.

--env-file: menos dotenv en local

Node soporta cargar variables desde un .env al arrancar. Para local y staging es comodísimo. Para producción, lo normal sigue siendo secrets de plataforma, pero para quitar fricción en dev va genial.

Permission model: útil como cinturón, no como bunker 

El permission model te sirve para restringir capacidades del proceso (por ejemplo, acceso al sistema de archivos) cuando lo arrancas con --permission. En Node 25 se amplía para poder controlar también el acceso a red con --allow-net. No es un “sandbox” perfecto, pero como cinturón de seguridad está muy bien, sobre todo si ejecutas scripts o tooling con dependencias que no controlas del todo.

Strapi 5: los cambios que sí importan 

documentId y el Document Service

Strapi 5 cambia la mentalidad: el identificador estable de cara a API es documentId, no el id numérico. El motivo es simple: el id puede cambiar en duplicados, imports/exports, seeds, etc. documentId es el que Strapi quiere que uses “hacia fuera».

Además, el Document Service API (strapi.documents) es la capa recomendada para trabajar desde backend y plugins.

La respuesta aplanada y el modo compatibilidad 

En Strapi 4 vivías con data.attributes. En Strapi 5 se aplanan campos y desaparece attributes por defecto.

Si estás migrando y quieres respirar, puedes pedir temporalmente respuesta estilo v4 con el header Strapi-Response-Format:v4. Es literalmente el “puente” para migrar backend primero y frontend después.

Draft & Publish y Content History 

Draft & Publish sigue existiendo. Content History existe, pero es de pago: planes Growth o Enterprise (con retención distinta según plan). Si estás en Community, no cuentes con eso integrado.

Implementación rápida, sin convertir esto en un manual.

Ejemplo real: endpoint por slug + contador de vistas

Archivo: 
src/api/article/controllers/article.ts 
import { factories } from '@strapi/strapi'; 
export default factories.createCoreController('api::article.article', ({ 
strapi 
}) => ({ 
async findBySlug(ctx) { 
const { slug } = ctx.params; 

const document = await 
strapi.documents('api::article.article').findFirst({ 
filters: { slug }, 
populate: ['cover'], 
status: 'published', 
}); 

if (!document) { 
return ctx.notFound('Artículo no encontrado'); 
} 

const updated = await 
strapi.documents('api::article.article').update({ 
documentId: document.documentId, 
data: { views: (document.views ?? 0) + 1 }, 
status: 'published', 
}); 

const sanitized = await this.sanitizeOutput(updated, ctx); 
return this.transformResponse(sanitized); 
}, 
})); 

Nota rápida de mundo real: si esto fuese altísimo tráfico, el “views + 1” puede tener condiciones de carrera. Para blogs normales suele dar igual. Si algún día lo necesitas serio, lo ideal es un incremento atómico a nivel DB o cola.

Test rápido con node:test

Esto está perfecto para un smoke test. Node trae node:test y para integración simple es muy cómodo.

import { describe, it } from 'node:test'; 
import assert from 'node:assert/strict'; 

const BASE_URL = 'http://localhost:1337/api'; 

describe('Strapi Articles API', () => { 
it('Devuelve estructura aplanada (sin attributes)', async () 
=> { 
const res = await fetch(${BASE_URL}/articles); 
assert.equal(res.status, 200); 

const json = await res.json(); 
assert.ok(Array.isArray(json.data)); 

const first = json.data[0]; 
if (first) { 
assert.equal(first.attributes, undefined); 
assert.ok(first.documentId); 
} 
}); 
}); 

Con Strapi 5, “data va aplanado”, pero en relaciones y media merece la pena que revises el shape exacto de tu API. Si estás migrando y activaste Strapi-Response-Format:v4, entonces sí volverás a ver attributes.

Un patrón que no falla es: primero decides si estás en formato v5 o v4 y luego parseas en consecuencia.

Migración de Strapi 4 a 5: lo mínimo que de verdad duele

El upgrade tool oficial existe (npx @strapi/upgrade major) y la estrategia típica es: habilitas compatibilidad v4 en REST con el header, actualizas consumidores poco a poco, y luego lo quitas

Y recuerda: Strapi 4 sigue soportado hasta abril de 2026, así que no es “salto ya o muero”, puedes planificarlo.

¿Quieres seguir aprendiendo sobre más tecnologías? ¡Síguenos en nuestras redes sociales y canal de YouTube!

Artículos ​ relacionados