Next.js: Sin servidor Siguiente: crea una dependencia solo para desarrolladores de `next`, introduce` next-server` para compilaciones más pequeñas y un arranque más rápido

Creado en 29 may. 2018  ·  52Comentarios  ·  Fuente: vercel/next.js

El problema: al optimizar para una compilación de producción, invocar next start o usar require('next') dentro de un server.js implica traer todo el conjunto de dependencias next , incluida la los relacionados exclusivamente con el desarrollo, como webpack .

Esto no solo es problemático desde el punto de vista de la imagen de compilación y el rendimiento del tiempo de descarga al generar compilaciones de producción, sino que también es probable que perjudique el tiempo de arranque. _Nota: Esto se ve disminuido por el hecho de que cargamos con cuidado y de manera perezosa dependencias pesadas como webpack en modo dev._

Para los que se preocupan por el rendimiento y los que son sensibles a los _ tiempos de inicio fríos_ (ver por ejemplo: https://twitter.com/rauchg/status/990667331205447680), podemos introducir un paquete next-server .

Tendría las mismas capacidades que require('next') menos todas las configuraciones de tiempo de desarrollo , más una CLI muy pequeña de next-server que puede abrir un puerto y realizar un cierre ordenado.

Para qué queremos optimizar:

  • El conjunto de dependencia total de next-server tiene que ser lo más pequeño posible
  • Debemos optimizar en gran medida para que el tiempo de arranque comience lo más rápido posible

Además, deberíamos proporcionar un ejemplo en examples/ de cómo usar next-server en combinación con pkg para exportar su aplicación Next.js como un binario ELF autónomo .

p1 feature request

Comentario más útil

Los tiempos de inicio en frío que vemos en Now 2.0 para nuestra interfaz son 1.5s, para un tamaño de imagen de 80mb IIRC

2018-05-29 16 50 37

Debería ser posible acercarlo mucho más a 1s sin ningún cambio en Node o V8 o cualquiera de las dependencias cuya evaluación fría toma una buena cantidad de tiempo (como react y react-dom )

Todos 52 comentarios

Los tiempos de inicio en frío que vemos en Now 2.0 para nuestra interfaz son 1.5s, para un tamaño de imagen de 80mb IIRC

2018-05-29 16 50 37

Debería ser posible acercarlo mucho más a 1s sin ningún cambio en Node o V8 o cualquiera de las dependencias cuya evaluación fría toma una buena cantidad de tiempo (como react y react-dom )

wou, esto es asombroso !! : o

Wow eso es genial.

algunas preguntas por next-server .

  1. ¿Será un servidor ligero express?
  2. sí, ¿será configurable con rutas express y next-routes ?

@ Nishchit14 No agregarías express si estuvieras tratando de mantener el tamaño de compilación bajo.

Estoy seguro de que next-routes seguirá funcionando bien.

Entonces, de lo que estamos hablando aquí es de extraer el servidor existente en su propio paquete. Por lo tanto, funcionará de la misma manera que antes, pero en lugar de importar el siguiente, importa el siguiente servidor.

¡Esto es asombroso! Yo y otras personas que conozco hemos estado ejecutando Next.js sobre AWS Lambda usando scandium ( usando esta guía ) y algunos de los principales problemas han sido:

1) Tamaño del paquete. Lambda le ofrece un límite estricto de 50 MB al que puede acercarse fácilmente con todas las herramientas de desarrollo que se incluyen.

2) Arranque en frío. Tener un arranque rápido es muy importante ya que Lambda puede decidir poner en marcha más servidores en cualquier momento. Los servidores existentes también viven un máximo de ~ 4 horas, por lo que el arranque en frío será importante durante todo el ciclo de vida de la aplicación.

¡Muy contento de ver esta iniciativa y feliz de ayudar!

Esta es una gran idea, tenemos lo mismo con Nuxt.js, lo llamamos nuxt-start ya que es el comando que necesita para ejecutar nuxt start -> nuxt-start

Siguiendo esto de cerca. Como punto de datos de lo que es posible, www.bustle.com es una aplicación SSR preact en AWS Lambda con <1 s de arranques en frío. El archivo zip de producción implementado completo es de 166 kb. Eso es todo el código de la aplicación y la biblioteca. Webpack se utiliza para empaquetar.

Gracias por compartir @southpolesteve. Eso es súper impresionante. #metas

El caso de usuario se parece mucho a micro y micro-dev .

¿Por qué no utilizar la misma nomenclatura? next y next-dev

Estoy jugando con next.js y sin servidor usando este ejemplo y tengo curiosidad por saber si hay alguna forma de lograr compilaciones más pequeñas ahora. ¿Existe una lista de node_modules que absolutamente no necesitamos en producción y que se pueden excluir con archivos de configuración en un empaquetador como serverless o repack-zip ?

@Enalmada Estoy ejecutando next.js con varios departamentos y material-ui es uno de ellos, tengo una aplicación bastante grande en términos de escala, pero el zip integrado que subo a Lambda es de ~ 45 MB. ¿Qué tallas buscas?

@albinekb Estoy inspirado por la respuesta de southpolesteve bustle.com anterior a 166kb y me pregunto cuánto de mis "45 MB" es inútil y fácil de eliminar si supiera qué poner en un archivo de exclusión dist como un truco hasta que este excelente boleto esté terminado. .

@albinekb Le recomiendo encarecidamente que mire el uso de paquete web, paquete o paquete acumulativo para agrupar su JS para lambda. Ahorrará tamaño, pero también tiempo de arranque, ya que acceder al sistema de archivos a través de un nodo normal es bastante lento.

Si está implementando en ZEIT Now y desea mantener su imagen pequeña para arranques en frío rápidos, puede usar una herramienta como Package Phobia para verificar el tamaño de una dependencia npm antes de instalarla (o simplemente verificar el tamaño de las dependencias actuales para cortar la hinchazón).

El archivo Léame también tiene muchas herramientas similares para ayudarlo a combatir la hinchazón. Compruébalo aquí: https://github.com/styfle/packagephobia

¿No se suponía que esto se abordaría en la versión de Next 7? :(

Si está implementando en zeit ahora y desea mantener su imagen pequeña para arranques en frío rápidos, puede usar una herramienta como Package Phobia

Maldito seas antd: https://packagephobia.now.sh/result?p=antd

@Enalmada son probablemente las dependencias de antd las responsables, no la biblioteca en sí. He estado investigando eso para https://packagephobia.now.sh/result?p=%40material-ui%2Fcore. La mayor parte del peso proviene de una o dos dependencias.

¿No se suponía que esto se abordaría en la versión de Next 7? :(

Para ser claros sobre esto, Next.js 7 sienta las bases para Serverless Next.js, hemos eliminado alrededor de 5 rutas, dejando solo 2 realmente necesarias para la producción.

¿Alguien ha conseguido que next.js funcione con rollup? Siento que me acerqué mucho ... al ejecutar el resumen en mi archivo dist de 60 m, el tamaño se redujo a 6 m. Desafortunadamente, el archivo dist no se iniciaría realmente y creo que se debe a una única dependencia circular en el código next.js que es una advertencia durante el resumen. Si alguien pudiera opinar sobre la posibilidad de eliminar una dependencia circular en el código next.js, todos podríamos estar muy cerca de compilaciones mucho más pequeñas y un arranque más rápido:
https://github.com/zeit/next.js/issues/5392

Siguiendo esto de cerca. Como punto de datos de lo que es posible, www.bustle.com es una aplicación SSR preact en AWS Lambda con <1 s de arranques en frío. El archivo zip de producción implementado completo es de 166 kb. Eso es todo el código de la aplicación y la biblioteca. Webpack se utiliza para empaquetar.

@southpolesteve , ¿podría compartir algo sobre la configuración de su paquete webpack?

@shauns Desafortunadamente, ya no estoy en Bustle y ya no tengo el código para mirar: /

@southpolesteve ¡ no te preocupes! Es bueno saber sus posibilidades al menos en el paquete web.

¿Podemos tener noticias sobre el próximo servidor? Vi algunas confirmaciones hace este mes.

Consulta la rama de canario.

¿Cuándo planeas lanzarlo?

No puedo compartir una línea de tiempo en este momento.

Recién aterrizado # 5927

@timneutkens ¿Debo mover next a devDependencies y agregar next-server a mis dependencias o lo estás haciendo automáticamente a través de babel?
https://github.com/zeit/next.js/blob/canary/packages/next/build/babel/plugins/next-to-next-server.ts

@Skaronator si está implementando usando # 5927 no es ninguno, según la especificación, generará un paquete por página, no se necesitan dependencias. Lo que significa que puede tomar .next/serverless/index.js requerirlo ( require('./.next/serverless/index.js') ) y luego llamar al método render :

const page = require('./.next/serverless/index.js')

page.render(req, res)

Esto renderizará la página y finalizará la respuesta.

¡Eso es genial!
Estoy probando esto, pero tengo algunos problemas para hacerlo funcionar en aws lambda. ¿Alguien tiene algún consejo?

Supongo que ya no deberíamos necesitar un servidor expreso personalizado, solo podríamos requerir el archivo sin servidor según la ruta 🤔

editar
Esto parece funcionar, aunque es necesario profundizar más para ver cómo optimizar el paso de compilación:

const serverless = require("serverless-http");
const http = require('http');
const app = require('./.next/serverless/index.js');
const server = new http.Server((req, res) => app.render(req, res))
app.prepare().then(() => {
    const handler = serverless(server, {
        binary: binaryMimeTypes
    });
    return handler(event, context, callback);
});

Parece que estás confundiendo el "servidor personalizado" con "sin servidor", sus API están completamente separadas, no hay .prepare método render .

const serverless = require("serverless-http");
const http = require('http');
const page = require('./.next/serverless/index.js');
const server = new http.Server((req, res) => page.render(req, res))
const handler = serverless(server, {
  binary: binaryMimeTypes
});
handler(event, context, callback);

De hecho, y no tengo idea de por qué funcionó el código anterior (tal vez fue solo el caché), pero ni el mío ni el tuyo funcionó porque serverless-http no parece admitir http.Server y No puedo simplemente devolver page.render(req, res) porque el objeto lambda event no puede reemplazar el render necesario req param ..

Además, no quiero usar express / koa / lo que sea, ya que romperá todo el propósito de esta próxima función nueva ... ( serverless-http tiene dependencias, por lo que está bien usarlo)

No tengo ideas: /

Gracias @timneutkens , agradezco tu ayuda.
Pero tampoco está funcionando en este momento, todavía tengo este error: typeError: Parameter "url" must be a string, not undefined

Dejaré de contaminar este hilo y seguiré investigando y escribiré un ejemplo si alguna vez encuentro una solución 😄

Estoy un poco confuso. Este hilo parece que se aplica a dos escenarios: aplicaciones sin servidor y servidores precompilados que incluyen todos los paquetes npm necesarios del lado del servidor empaquetados juntos.

El gif en el primer comentario de este hilo parece referirse al último escenario, que es el que me interesa. Parece que usa next-server que puede ser o no este paquete npm, no lo hace. no tengo un repositorio adjunto, y no pude encontrar uno a través de la búsqueda de Google o GitHub, aunque una de las etiquetas de versión es 8.0.0-canary.7, una etiqueta de versión de next, así que sospecho que es el paquete correcto.

¿Es exacto lo que he escrito hasta ahora? Si es así, a pesar de que está en canario, ¿hay alguna forma de que pueda obtener acceso temprano?

Mi solución actual (que por razones evidentes, no estoy usando en prod ) es eliminar la función de config.externals en mi next.config.js .

Me encantaría poder producir un servidor prediseñado para no tener que instalar 200 MB de node_modules y luego pasar 2 minutos compilando en mi pobre y pequeña máquina virtual de producción cada vez que presiono una actualización.


* "prod" se usa de manera flexible, ya que este proyecto no es de misión crítica ni es tan profesional

Siguiendo esto de cerca. Como punto de datos de lo que es posible, www.bustle.com es una aplicación SSR preact en AWS Lambda con <1 s de arranques en frío. El archivo zip de producción implementado completo es de 166 kb. Eso es todo el código de la aplicación y la biblioteca. Webpack se utiliza para empaquetar.

Next.js 8 serverless target tiene un tamaño de zip de 42Kb por defecto 😌

¡Eso es genial! ¡Lo espero con ansias!

Tengo exactamente la misma pregunta que @dfoverdx. Quiero hacer una compilación de servidor, que también incluya todos los node_modules necesarios para ejecutar. Estoy usando un servidor personalizado con express, por lo que no espero que esas dependencias se incluyan en el paquete, pero ahora también debe instalar _todas_ las dependencias en su servidor (react, next, axios, ...).

No entiendo cómo esto no es por defecto.
Empaquetar todas las dependencias y poder minimizarlas debería traer mejoras significativas en el rendimiento del servidor o ¿estoy completamente equivocado aquí?

Sobrescribir la sección externals de la configuración del paquete web de la siguiente manera incluye la mayoría de las dependencias

module.exports = {
  webpack: (config, { dev }) => {
    config.externals = [];
    return config;
  })
};

Pero react y react-dom siguen siendo necesarios en el servidor. No puedo averiguar cómo incluirlos también ...

Desafortunadamente, no es posible crear un servidor personalizado con el modo sin servidor actual. Y si usa el modo normal, debe incluir next y todas sus dependencias porque el _app.js generado en .next depende, por ejemplo, de next / enrutador

¿Por qué no podría incluirse el modo sin servidor a continuación?

Desafortunadamente, no es posible crear un servidor personalizado con el modo sin servidor actual. Y si usa el modo normal, debe incluir next y todas sus dependencias porque el _app.js generado en .next depende, por ejemplo, de next / enrutador

Tenga en cuenta que desde el próximo 8, puede requerir 'next-server' en lugar de 'next' en su server.js, y al hacerlo, solo perderá la recarga en caliente durante el desarrollo local. En teoría, le da la capacidad de hacer compilación de CI en un servidor intermedio y no copiar dependencias relacionadas con Webpack a instancias de producción. Pero aún no lo hemos probado en nuestro proyecto.

@ElvenMonky esperando algo como esto desde hace un año, pero no pude encontrar nada al respecto en los documentos o ejemplos.

@timneutkens, ¿ podrías verificar esto?

Si es así, podría experimentar con dicha configuración y enviar un PR para los documentos / ejemplos.

Tenga en cuenta que desde el próximo 8, puede requerir 'next-server' en lugar de 'next' en su server.js, y solo perderá la recarga en caliente durante el desarrollo local al hacer eso

Desafortunadamente, esto no funciona.

Primero, la ejecución de la compilación sin servidor con el destino del servidor se bloquea activamente con el siguiente mensaje: "No se puede iniciar el servidor cuando el destino no es el servidor. Https://err.sh/zeit/next.js/next-start-serverless "

Luego, si decide hacer una compilación normal, los archivos de compilación hacen referencia a cosas del paquete next directamente (como next/router en el archivo _app.js compilado para el lado del servidor). Significa que las cosas next y webpack deben estar en producción de todos modos.

@ElvenMonky

Tenga en cuenta que desde el próximo 8, puede requerir 'next-server' en lugar de 'next' en su server.js, y al hacerlo, solo perderá la recarga en caliente durante el desarrollo local.

Lo siguiente es hacerlo internamente como un complemento de Babel, como puede ver aquí:
https://github.com/zeit/next.js/blob/709850154754278d2fc86b987eebe1b3f0565255/packages/next/build/babel/plugins/commonjs.ts#L5 -L32

@sheerun, como mencioné también en # 7011, puede eliminar la dependencia next/router resuelta al transpilar el módulo next usando el complemento next-transpile-modules .

He bifurcado y ajustado un ejemplo para el servidor expreso personalizado para ilustrar la solución: https://github.com/ElvenMonky/next.js/tree/custom-next-server-express/examples/custom-server-express

PD: Todavía estoy muy entusiasmado con el # 5927, no importa, mi aplicación requiere todo lo que se enumera en TODO, sin mencionar las rutas dinámicas y el servicio de contenido estático.
La buena noticia es que la solución anterior parece funcionar bien con la configuración del servidor personalizado https://www.npmjs.com/package/next-serverless , lo que hace posible la siguiente implementación, por ejemplo, en AWS Lambda sin las limitaciones antes mencionadas.

Tenga en cuenta que desde el próximo 8, puede requerir 'next-server' en lugar de 'next' en su server.js, y al hacerlo, solo perderá la recarga en caliente durante el desarrollo local.

He estado usando este consejo, pero desafortunadamente no puedo usar la configuración en tiempo de ejecución ya que requiere next/config que requiere next .

No sé por qué, pero require('next/config') solía trabajar en producción sin next instalado en node_modules con la próxima versión 8.0.3 pero no funciona con la próxima versión 8.1.0

¿Es posible mover next / config a un paquete diferente, como next-runtime-config ?
O next-runtime-vars (evitando el término configuración para evitar confusiones con next.config.js).

Avísame si es aceptable, crearé un PR.

¡Hola a todos! Este problema se implementó desde Next.js 8, y todavía existe en Next.js 9. Voy a cerrar esto como completado. 😌

Lo siento, me confundí con este problema: https://github.com/zeit/next.js/issues/7011
No he comprobado con el objetivo: "sin servidor"


Ver comentario eliminado

Algunos "next/*" se pueden reemplazar con "next-server/*" , como:

  • siguiente / config -> siguiente-servidor / config
  • siguiente / amp -> siguiente-servidor / amp
  • siguiente / dinámico -> siguiente-servidor / dinámico
  • siguiente / constantes -> siguiente-servidor / constantes
  • siguiente / cabeza -> siguiente-servidor / cabeza

Pero hay algunos para los que no hay soporte para dicha optimización mencionada por OP de este problema.

  • siguiente / enrutador -> siguiente-servidor / dist / lib / enrutador / enrutador (tal vez)? (Debería estar vacío o debería arrojar un error si se usa en el servidor)
  • siguiente / enlace?

No es necesario ya que están integrados incluso en el servidor (AKAIK)

  • siguiente / aplicación
  • siguiente / documento

¡Hola a todos! Este problema se implementó desde Next.js 8, y todavía existe en Next.js 9. Voy a cerrar esto como completado.

Hola @Timer : ¿te refieres al objetivo sin servicio o al reemplazo de 'siguiente' por 'siguiente servidor'?

Si reemplazamos next con next server, eso no cambia el tamaño de la carpeta node_modules a menos que las dependencias de packages.json también se actualicen.

¿Hay algún ejemplo disponible de cualquiera de los dos enfoques? con serverless, mi caso de uso es la implementación en AWS Lambda.

El enfoque descrito en el número inicial evolucionó hasta convertirse en el objetivo serverless , le recomendamos que lo utilice.

@timneutkens serverless target no puede resolver problemas con el servidor personalizado, que utiliza rutas dinámicas. # 5927 No es una solución para muchas aplicaciones comerciales del mundo real como en mi caso, donde tenemos que usar páginas generadas dinámicamente, prefijo de activos, _app, _document y _err personalizados: básicamente todo lo que se indica en la lista TODO.
next-server nos brinda una solución parcial para implementar en producción sin dependencias extrañas solo de desarrollo, como webpack y babel. Sin embargo, esto se puede hacer con algunos trucos y bailes woodoo, que estamos discutiendo aquí.

Tenía la impresión de que comprendía esta diferencia y esperaba ver una solución más sólida algún día al problema inicial, tal como lo describe @rauchg.

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

ghost picture ghost  ·  3Comentarios

sospedra picture sospedra  ·  3Comentarios

wagerfield picture wagerfield  ·  3Comentarios

havefive picture havefive  ·  3Comentarios

swrdfish picture swrdfish  ·  3Comentarios