de errores con not-found a fork next-runtime-env / Sudo Null IT News
Recientemente encontré un error interesante en Next.js. si en la pagina not-found
navegar a través de router.push(pathname)
todas las variables de entorno que inicializamos a través de la biblioteca se pierden next-runtime-env
(significado window.__ENV
se convierte undefined
).
En el proyecto utilizamos next-runtime-env
ya que nos adherimos al enfoque Construya una vez, implemente muchas – esto le permite conservar una imagen de Docker, en la que se incluyen las variables de entorno necesarias al inicio. Next.js no admite este comportamiento de fábrica, porque quiere recopilar variables ambientales en la etapa de compilación de la aplicación.
El error apareció en not-found
página donde tenemos un botón que permite crear un elemento con un solo clic si no se encuentra algo. El mismo componente de botón se utiliza en otras páginas y esto es lo interesante: en otras páginas router.push(pathname)
funciona correctamente, pero not-found
– No.
Al principio pensé que el problema estaba en next-runtime-env
. La biblioteca probablemente se anula cuando se actualiza la página, porque el script que establece las variables en window.__ENV
colocado en diseño raíz. También intenté versionar Next.js, asumiendo que el error estaba relacionado con ciertas versiones del marco, pero esto no arrojó ningún resultado. Como resultado, una solución temporal fue utilizar window.location.href
lo que impidió la actualización de la página y ayudó a guardar variables.
Sin embargo, la historia no terminó ahí.
El problema se ha reducido: sólo se perdió la configuración del cliente
Profundicé en el problema, tratando de entender por qué la configuración se perdía sólo en el entorno del cliente. Al principio sospeché router.push(pathname)
– Pensé que estaba provocando una recarga de página completa, borrando window
y sin provocar que el script se ejecute nuevamente desde el diseño raíz. Sin embargo, resultó que este no fue el caso.
Al intentar reproducir el error en entornos sandbox minimalistas, me encontré con el hecho de que el error no aparecía allí. Luego presté atención al middleware. next-intl
que podría influir mágicamente en las variables ambientales durante la navegación. Durante el proceso de depuración, noté que en los sandboxes y en el proyecto en el que me estaba metiendo not-found
de diferentes maneras: a través notFound()
y a través de router.push(/not-existed-pathname)
. Esto me llevó a realizar aún más experimentos.
En los comentarios en mi blog de telegramas A mis intentos de descubrir la causa del problema, se me hizo una pregunta razonable: “¿Qué decide exactamente next-runtime-env
? ” Respondí que normalmente uso bibliotecas de terceros para gestionar la complejidad del proyecto, pero el problema claramente requería profundizar más en las raíces.
Habiendo ahorrado energía para depurar, comencé a probar diferentes hipótesis:
Reemplace el script nativo en línea con un script de
next/script
para jugar con diferentes estrategias de carga.Compruebe si esto se debe a que a partir de la versión 14,
not-found
está preparado de forma predeterminada en el servidor.Comprenda por qué se produce una actualización completa de la página al navegar
router.push
.
No había finales a la vista
Después de numerosos experimentos, incluida la sustitución de scripts nativos por next/script
con diferentes estrategias de carga, todavía no pude obtener la configuración en la página not-found
a través de router.push
. Intenté duplicar scripts en el servidor, jugué con la directiva use client
pero fue en vano.
En algún momento mi entusiasmo se agotó. incluso lo eliminé next-intl
del proyecto para verificar si su middleware lo está afectando, pero esto no resolvió el problema.
Entonces me di cuenta de que en la página not-found
objeto presente window.__next_f
que me recordó a RSC Payload. En él vi mi script con la configuración, pero por alguna razón Next.js no hidrogenó esta parte de la página.
En esta etapa, ya estaba pensando en escribir un analizador de carga útil RSC para extraer la configuración desde allí y extraerla. window
pero algo me distrajo, y entonces decidí buscar lo que escriben sobre esto. __next_f
.
Curiosamente, al renderizar la página not-found
Next.js arroja un determinado error y reacciona a todos los errores de la misma manera: deja de representar la página, incluido el diseño, donde tuvo lugar mi asignación de configuración. Cómo explicado en uno de los hilos, el problema es que Siguiente.js detiene la representación de cualquier página cuando ocurre un error, ya sea NotFoundError
u otro. Como resultado, el servidor deja de mostrar la página, incluidos todos los elementos de diseño. Es importante tener en cuenta que el HTML inicial que devuelve el servidor no contiene elementos de diseño específicos.
No importa si el error se produce a través de notFound()
o a través de regulares new Error()
la representación de la ruta se detiene y el HTML devuelto por el servidor no contiene las etiquetas necesarias para los scripts que trabajan con beforeInteractive
. Cuando se completa la hidratación, el script se agrega al HTML, pero en este punto el principal app-bootstrap
el script ya ha sido ejecutado y su impacto se pierde. Por lo tanto la estrategia de carga beforeInteractive
No funciona en páginas con errores.
Sin embargo, todas las demás estrategias de carga, como afterInteractive
o lazyOnLoad
funciona correctamente. Esto me impulsó a comprobar cómo cargar scripts en next-runtime-env
y resultó que allí también se usa beforeInteractive
. decidí abrir relaciones públicas al repositorio, especialmente porque ya encontré dos problemas en los que los desarrolladores encontraron problemas similares: pérdida de configuración en el cliente.
Menos mal que no soy el único que se ha encontrado con esto. Veamos cómo reacciona el equipo al PR. Me pregunto por qué no agregaron soporte para la estrategia de carga de scripts mediante prop. estrategiay ¿existe alguna limitación conceptual que aún no entiendo? Si no hay limitaciones conceptuales, ¡genial! De lo contrario, tal vez haga mi propia implementación para pasar la configuración al cliente sin pérdidas.
Fork y su destino
Al final, decidí liberar mi bifurcación de la biblioteca. next-runtime-env
. Se puede encontrar en GitHub: impresionante-siguiente-entorno-de-ejecución.
Describí todas las diferencias con el original en relaciones públicas. Que esta bifurcación se desarrolle más dependerá de si cargan mi PR o no.
Así, el historial de búsqueda de una solución, comenzando con la navegación en not-found
página y terminando con una bifurcación de biblioteca, resultó estar llena de giros inesperados.