Next.js: Serverless Next : créer une dépendance « next » réservée aux développeurs, introduire « next-server » pour des versions plus petites et un démarrage plus rapide

Créé le 29 mai 2018  ·  52Commentaires  ·  Source: vercel/next.js

Le problème : lors de l'optimisation pour une version de production, l'invocation de next start ou l'utilisation de require('next') dans un server.js implique d'apporter l'ensemble des dépendances next , y compris le celles liées exclusivement au développement, telles que webpack .

Non seulement cela pose problème du point de vue de l'image de build et des performances de temps de téléchargement lors de la génération de builds de production, mais cela nuit également probablement au temps de démarrage. _Remarque : Ceci est atténué par le fait que nous chargeons prudemment paresseusement des dépendances lourdes telles que webpack en mode dev._

Pour les utilisateurs soucieux de la performance et sensibles aux _heures de démarrage à froid_ (voir par exemple : https://twitter.com/rauchg/status/990667331205447680), nous pouvons introduire un package next-server .

Il aurait les mêmes capacités que require('next') moins tous les paramètres de développement , plus une très petite next-server CLI qui peut ouvrir un port et effectuer un arrêt en douceur.

Ce que nous voulons optimiser pour :

  • L'ensemble de dépendances total de next-server doit être aussi petit que possible
  • Nous devons fortement optimiser pour que le temps de démarrage démarre le plus rapidement possible

De plus, nous devrions fournir un exemple dans examples/ de la façon d'utiliser next-server en combinaison avec pkg pour exporter votre application Next.js en tant que binaire ELF autonome .

p1 feature request

Commentaire le plus utile

Les temps de démarrage à froid que nous voyons sur Now 2.0 pour notre frontend sont de 1,5 s, pour une taille d'image de 80 Mo IIRC

2018-05-29 16 50 37

Il devrait être possible de le rendre beaucoup plus proche de 1s sans aucune modification de Node ou V8 ou de l'une des dépendances dont l'évaluation à froid prend une bonne partie du temps (comme react et react-dom )

Tous les 52 commentaires

Les temps de démarrage à froid que nous voyons sur Now 2.0 pour notre frontend sont de 1,5 s, pour une taille d'image de 80 Mo IIRC

2018-05-29 16 50 37

Il devrait être possible de le rendre beaucoup plus proche de 1s sans aucune modification de Node ou V8 ou de l'une des dépendances dont l'évaluation à froid prend une bonne partie du temps (comme react et react-dom )

wou, c'est génial !! :o

Wow c'est génial.

quelques questions pour next-server .

  1. sera-ce un serveur express léger ?
  2. oui, sera-t-il configurable avec des itinéraires express et next-routes ?

@ Nishchit14 Vous n'ajouteriez pas express si vous essayiez de réduire la taille de construction.

Je suis sûr que next-routes fonctionnera toujours très bien.

Donc, ce dont nous parlons ici, c'est d'extraire le serveur existant dans son propre package. Cela fonctionnera donc de la même manière qu'avant, mais au lieu d'importer next, vous importez next-server.

C'est génial! Moi et d'autres personnes que je connais avons exécuté Next.js sur AWS Lambda à l'aide de scandium (à l' aide de ce guide ) et certains des principaux problèmes ont été :

1) Taille de l'emballage. Lambda vous donne une limite stricte de 50 Mo qui peut être facilement approchée avec tous les outils de développement inclus.

2) Démarrage à froid. Avoir un démarrage rapide est très important car Lambda peut décider de faire tourner plus de serveurs à tout moment. Les serveurs existants ont également une durée de vie maximale d'environ 4 heures, le démarrage à froid sera donc important tout au long du cycle de vie de l'application.

Très heureux de voir cette initiative et heureux d'aider!

C'est une excellente idée, nous avons la même chose avec Nuxt.js, nous l'avons appelé nuxt-start car c'est la commande dont vous avez besoin pour exécuter nuxt start -> nuxt-start

À suivre de près. Comme point de données pour ce qui est possible, www.bustle.com est une application SSR preact sur AWS Lambda avec des démarrages à froid <1s. L'intégralité du fichier zip de production déployé fait 166 Ko. C'est tout le code de l'application et de la bibliothèque. Webpack est utilisé pour le regroupement.

Merci pour le partage @southpolesteve. C'est super impressionnant. #buts

Le cas utilisateur ressemble beaucoup à micro et micro-dev .

Pourquoi ne pas utiliser la même nomenclature ? next et next-dev

Je déconne avec next.js et serverless en utilisant cet exemple et je suis curieux de savoir s'il existe un moyen d'accomplir des versions plus petites maintenant. Existe-t-il une liste de node_modules dont nous n'avons absolument pas besoin en production et qui peuvent être exclus avec des fichiers de configuration dans un packager comme serverless ou repack-zip ?

@Enalmada J'exécute next.js avec plusieurs deps et material-ui étant l'un d'entre eux, j'ai une application assez grande en termes d'échelle mais le zip intégré que je télécharge sur Lambda est d'environ 45 Mo. Quelles tailles recherchez-vous ?

@albinekb Je suis inspiré par la réponse de southpolesteve bustle.com ci-dessus de 166 Ko et je me demande combien de mes "45 Mo" sont inutiles et faciles à supprimer si je savais juste quoi mettre dans un fichier d'exclusion de dist comme hack jusqu'à ce que cet excellent ticket soit terminé .

@albinekb Nous vous recommandons vivement d'utiliser webpack, parcel ou rollup pour regrouper votre JS pour lambda. Vous économiserez sur la taille, mais aussi sur le temps de démarrage car atteindre le système de fichiers via le nœud normal requis est assez lent.

Si vous déployez sur ZEIT Now et que vous souhaitez garder votre image petite pour les démarrages à froid rapides, vous pouvez utiliser un outil comme Package Phobia pour vérifier la taille d'une dépendance npm avant de l'installer (ou simplement vérifier la taille des dépendances actuelles pour couper le ballonnement).

Le fichier readme contient également de nombreux outils similaires pour vous aider à lutter contre les ballonnements. Découvrez-le ici : https://github.com/styfle/packagephobia

Cela n'était-il pas censé être traité dans la version Next 7 ? :(

Si vous déployez sur zeit maintenant et que vous souhaitez garder votre image petite pour des démarrages rapides à froid, vous pouvez utiliser un outil comme Package Phobia

Au diable : https://packagephobia.now.sh/result?p=antd

@Enalmada ce sont probablement les dépendances d'antd qui sont responsables, pas la bibliothèque elle-même. J'ai examiné cela pour https://packagephobia.now.sh/result?p=%40material-ui%2Fcore. La plupart du poids provient d'une ou deux dépendances.

Cela n'était-il pas censé être traité dans la version Next 7 ? :(

Pour être clair à ce sujet, Next.js 7 jette les bases de Serverless Next.js, nous avons supprimé environ 5 routes, ne laissant que 2 vraiment nécessaires pour la production.

Quelqu'un a-t-il déjà fait fonctionner next.js avec le rollup ? J'ai l'impression d'être devenu très proche... l'exécution d'un rollup sur mon fichier dist de 60 m a ramené la taille à 6 m. Malheureusement, le fichier dist ne démarre pas réellement et je pense que cela est dû à une seule dépendance circulaire dans le code next.js qui est un avertissement lors du cumul. Si quelqu'un pouvait peser sur la possibilité de supprimer une dépendance circulaire dans le code next.js, nous pourrions tous être très proches de versions beaucoup plus petites et d'un démarrage plus rapide :
https://github.com/zeit/next.js/issues/5392

À suivre de près. Comme point de données pour ce qui est possible, www.bustle.com est une application SSR preact sur AWS Lambda avec des démarrages à froid <1s. L'intégralité du fichier zip de production déployé fait 166 Ko. C'est tout le code de l'application et de la bibliothèque. Webpack est utilisé pour le regroupement.

@southpolesteve pourriez -vous partager quoi que ce soit autour de votre configuration de bundle webpack ?

@shauns Malheureusement, je ne suis plus chez Bustle et je n'ai plus le code à regarder :/

@southpolesteve pas de soucis ! Bon à savoir son poss dans webpack au moins.

Peut-on avoir des news sur next-server ? J'ai vu des commits il y a ce mois.

Vérifiez la branche canari.

Quand comptez-vous le sortir ?

Je ne peux pas partager une chronologie à ce stade.

Je viens d'atterrir #5927

@timneutkens Dois-je déplacer next vers devDependencies et ajouter next-server à mes dépendances ou le faites-vous automatiquement via babel ?
https://github.com/zeit/next.js/blob/canary/packages/next/build/babel/plugins/next-to-next-server.ts

@Skaronator si vous implémentez en utilisant #5927, ce n'est ni l'un ni l'autre, conformément à la spécification, il produira un paquet par page, aucune dépendance n'est nécessaire. Cela signifie que vous pouvez prendre .next/serverless/index.js exiger ( require('./.next/serverless/index.js') ) et ensuite appeler sa méthode render :

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

page.render(req, res)

Cela rendra la page et terminera la réponse

C'est génial!
J'essaie cela mais j'ai du mal à le faire fonctionner sur aws lambda. Quelqu'un a-t-il des astuces ?

Je suppose que nous ne devrions plus avoir besoin d'un serveur express personnalisé, nous pourrions simplement exiger le fichier sans serveur basé sur le chemin 🤔

Éditer
Cela semble fonctionner, mais il faut creuser plus profondément pour voir comment optimiser l'étape de construction :

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);
});

On dirait que vous confondez le "serveur personnalisé" avec "sans serveur", leurs API sont complètement séparées, il n'y a pas .prepare méthode render est appelé.

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);

En effet, et je n'ai aucune idée de pourquoi le code ci-dessus a fonctionné (peut-être que c'était juste le cache) mais ni le mien ni votre morceau de code n'a fonctionné car serverless-http ne semble pas prendre en charge http.Server et Je ne peux pas simplement retourner page.render(req, res) car l'objet lambda event ne peut pas remplacer le paramètre render req nécessaire.

En outre, je ne veux pas utiliser exprès / koa / whatever car il brisera tout le but de cette nouvelle fonctionnalité suivante .. ( serverless-http est gratuit dependencie il était donc autorisé à utiliser)

Je suis à court d'idées :/

Merci @timneutkens , j'apprécie votre aide.
Mais ça ne marche pas non plus pour le moment, j'ai toujours cette erreur : typeError: Parameter "url" must be a string, not undefined

Je vais arrêter de polluer ce fil et continuer à creuser et j'écrirai un exemple si jamais je trouve une solution 😄

Je ne suis pas clair. Ce fil semble s'appliquer à deux scénarios : les applications sans serveur et les serveurs précompilés qui incluent tous les packages npm nécessaires côté serveur regroupés.

Le gif dans le premier commentaire sur ce fil semble concerner ce dernier scénario, qui est celui qui m'intéresse. Il semble qu'il utilise next-server qui peut être ou non ce paquet npm --cela ne Je n'ai pas de référentiel attaché, et je n'ai pas pu en trouver un via la recherche Google ou GitHub, bien que l'une des balises de version soit 8.0.0-canary.7 - une balise de version de next - donc je suppose que c'est le bon paquet.

Ce que j'ai écrit jusqu'à présent est-il exact ? Si c'est le cas, même si c'est dans Canary, y a-t-il un moyen d'y accéder en avant-première ?

Ma solution actuelle (que, pour des raisons évidentes, je n'utilise pas dans prod ) consiste à supprimer la fonction de config.externals dans mon next.config.js .

J'aimerais être en mesure de produire un serveur pré-construit de sorte que je ne ai pas besoin d'installer 200 Mo d'node_modules puis passer 2 minutes sur la compilation mon pauvre, peu de production VM chaque fois que je pousse une mise à jour.


* "prod" est utilisé de manière lâche, car ce projet n'est pas critique pour la mission ou tout ce que professionnel

À suivre de près. Comme point de données pour ce qui est possible, www.bustle.com est une application SSR preact sur AWS Lambda avec des démarrages à froid <1s. L'intégralité du fichier zip de production déployé fait 166 Ko. C'est tout le code de l'application et de la bibliothèque. Webpack est utilisé pour le regroupement.

La cible sans serveur Next.js 8 a une taille de zip de 42 Ko par défaut 😌

C'est génial! J'attends ça avec impatience !

J'ai exactement la même question que @dfoverdx. Je souhaite créer un serveur, qui inclut également tous les node_modules nécessaires à l'exécution. J'utilise un serveur personnalisé avec express donc je ne m'attends pas à ce que ces dépendances soient incluses dans le package, mais maintenant vous devez également installer _toutes_ les dépendances sur votre serveur (react, next, axios, ...).

Je ne comprends pas comment ce n'est pas par défaut ?
L'empaquetage de toutes les dépendances et la possibilité de les minimiser devraient apporter des améliorations significatives des performances côté serveur ou est-ce que je me trompe complètement ?

L'écrasement de la section externals de la configuration webpack comme suit inclut la plupart des dépendances

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

Mais réagir et réagir-dom sont toujours requis sur le serveur. Je n'arrive pas à comprendre comment les inclure aussi...

Malheureusement, il n'est pas possible de créer un serveur personnalisé avec le mode sans serveur actuel. Et si vous utilisez le mode normal, vous devez inclure next et toutes ses dépendances car _app.js généré dans .next dépend par exemple de next/router

Pourquoi le mode non sans serveur ne pourrait-il pas également être intégré ensuite ?

Malheureusement, il n'est pas possible de créer un serveur personnalisé avec le mode sans serveur actuel. Et si vous utilisez le mode normal, vous devez inclure next et toutes ses dépendances car _app.js généré dans .next dépend par exemple de next/router

Notez que depuis le prochain 8, vous pouvez exiger 'next-server' au lieu de 'next' dans votre server.js, et vous ne perdez que le rechargement à chaud pendant le développement local en faisant cela. En théorie, cela vous donne la possibilité de construire CI sur un serveur intermédiaire et de ne pas copier les dépendances liées à Webpack sur des instances de production. Mais nous ne l'avons pas encore essayé dans notre projet.

@ElvenMonky attend quelque chose comme ça depuis un an, mais n'a rien trouvé à ce sujet dans les documents ou les exemples.

@timneutkens pouvez-vous vérifier cela s'il vous plaît ?

Si c'est le cas, je pourrais expérimenter avec une telle configuration et envoyer un PR pour les documents/exemples.

Notez que depuis le prochain 8, vous pouvez exiger 'next-server' au lieu de 'next' dans votre server.js, et vous ne perdez que le rechargement à chaud pendant le développement local en faisant cela

Malheureusement cela ne fonctionne pas.

Tout d'abord, l'exécution de la construction sans serveur avec la cible du serveur est activement bloquée avec le message suivant : "Impossible de démarrer le serveur lorsque la cible n'est pas le serveur. https://err.sh/zeit/next.js/next-start-serverless "

Ensuite, si vous décidez de faire une construction normale, les fichiers de construction font référence directement aux éléments du package next (comme next/router dans le fichier _app.js compilé côté serveur). Cela signifie que les éléments next et webpack doivent être en production de toute façon.

@ElvenMonky

Notez que depuis le prochain 8, vous pouvez exiger 'next-server' au lieu de 'next' dans votre server.js, et vous ne perdez que le rechargement à chaud pendant le développement local en faisant cela.

Ensuite, faites cela en interne en tant que plugin Babel, comme vous pouvez le voir ici :
https://github.com/zeit/next.js/blob/709850154754278d2fc86b987eebe1b3f0565255/packages/next/build/babel/plugins/commonjs.ts#L5 -L32

@sheerun, comme je l'ai mentionné également dans #7011, vous pouvez éliminer la dépendance non résolue de next/router en transpilant le module next aide du plugin next-transpile-modules .

J'ai fourché et ajusté l'exemple du serveur express personnalisé pour illustrer la solution : https://github.com/ElvenMonky/next.js/tree/custom-next-server-express/examples/custom-server-express

PS : Je suis toujours très excité par le #5927, peu importe que mon application nécessite tout ce qui est répertorié dans TODO, sans parler des routes dynamiques et du contenu statique.
La bonne nouvelle est que la solution ci-dessus semble bien fonctionner avec la configuration de serveur personnalisée https://www.npmjs.com/package/next-serverless , ce qui permet de déployer ensuite dans AWS Lambda, par exemple, sans les limitations susmentionnées.

Notez que depuis le prochain 8, vous pouvez exiger 'next-server' au lieu de 'next' dans votre server.js, et vous ne perdez que le rechargement à chaud pendant le développement local en faisant cela.

J'ai utilisé ce conseil, mais je ne peux malheureusement pas utiliser la configuration d'exécution car cela nécessite next/config qui nécessite next .

Je ne sais pas pourquoi mais require('next/config') fonctionnait en production sans next installé dans node_modules avec la prochaine version 8.0.3 mais ne fonctionne pas avec la prochaine version 8.1.0

Est-il possible de déplacer next/config vers un autre package, comme next-runtime-config ?
Ou next-runtime-vars (en évitant le terme config pour éviter toute confusion avec next.config.js).

Faites-moi savoir si cela est acceptable, je vais créer un PR.

Salut tout le monde! Ce problème a été implémenté depuis Next.js 8 et existe toujours dans Next.js 9. Je vais clore ce problème comme terminé. ??

Désolé, je me suis trompé avec ce problème : https://github.com/zeit/next.js/issues/7011
Je n'ai pas vérifié avec la cible : "sans serveur"


Voir le commentaire supprimé

Certains "next/*" peuvent être remplacés par "next-server/*" , comme :

  • suivant/config -> prochain-serveur/config
  • suivant/amp -> suivant-serveur/amp
  • suivant/dynamique -> prochain-serveur/dynamique
  • suivant/constantes -> suivant-serveur/constantes
  • suivant/tête -> prochain-serveur/tête

Mais il y en a quelques-uns pour lesquels il n'y a pas de support pour une telle optimisation mentionnée par OP de ce problème.

  • suivant/routeur -> prochain-serveur/dist/lib/routeur/routeur (peut-être) ? (Doit être vide ou doit générer une erreur s'il est utilisé sur le serveur)
  • suivant/lien ?

Pas nécessaire car ils sont intégrés même dans le serveur (AKAIK)

  • suivant/application
  • suivant/document

Salut tout le monde! Ce problème a été implémenté depuis Next.js 8 et existe toujours dans Next.js 9. Je vais clore ce problème comme terminé.

Salut @Timer - Faites-vous référence à la cible sans serv, ou au remplacement de « next » par « next-server » ?

Si nous remplaçons next par next server, cela ne change pas la taille du dossier node_modules à moins que les dépendances packages.json ne soient également mises à jour.

Existe-t-il un exemple de l'une ou l'autre de ces approches ? avec serverless, mon cas d'utilisation est le déploiement sur AWS Lambda.

L'approche décrite dans le numéro initial a évolué vers la cible serverless , nous vous recommandons de l'utiliser.

@timneutkens serverless target ne résout pas et ne peut pas résoudre les problèmes avec le serveur personnalisé, qui utilise des routes dynamiques. #5927 N'est pas une solution pour beaucoup d'applications commerciales du monde réel comme dans mon cas, où nous devons utiliser des pages générées dynamiquement, des préfixes d'actifs, des _app personnalisées, _document et _err : essentiellement tout ce qui est indiqué dans la liste TODO.
next-server nous donne une solution partielle à déployer en production sans dépendances étranges de développement uniquement, comme webpack et babel. Cela peut être fait cependant avec quelques hacks et danse woodoo, dont nous discutons ici.

J'avais l'impression que vous compreniez cette différence et j'espérais voir un jour une solution plus robuste au problème initial tel qu'il est décrit par @rauchg

Cette page vous a été utile?
0 / 5 - 0 notes