Next.js: Serverless Next: `next` dev-only Abhängigkeit machen, `next-server` für kleinere Builds und schnelleres Booten einführen

Erstellt am 29. Mai 2018  ·  52Kommentare  ·  Quelle: vercel/next.js

Das Problem: Bei der Optimierung für einen Produktions-Build erfordert das Aufrufen von next start oder die Verwendung von require('next') in einem benutzerdefinierten server.js das Einbringen des gesamten Satzes von next Abhängigkeiten, einschließlich der solche, die sich ausschließlich auf die Entwicklung beziehen, wie webpack .

Dies ist nicht nur aus Sicht des Build-Image und der Download-Zeit beim Generieren von Produktions-Builds problematisch, sondern beeinträchtigt wahrscheinlich auch die Startzeit. _Hinweis: Dies wird dadurch verringert, dass wir schwere Abhängigkeiten wie webpack im Entwicklungsmodus vorsichtig träge laden._

Für Leistungsbewusste und Sensitive für _Kaltstartzeiten_ (siehe zum Beispiel: https://twitter.com/rauchg/status/990667331205447680) können wir ein next-server Paket einführen.

Es hätte die gleichen Fähigkeiten wie require('next') abzüglich aller Entwicklungszeiteinstellungen plus eine sehr kleine next-server CLI, die einen Port öffnen und ein ordnungsgemäßes Herunterfahren durchführen kann.

Worauf wir optimieren wollen:

  • Die gesamte Abhängigkeitsmenge von next-server muss so klein wie möglich sein
  • Wir müssen stark optimieren, damit die Boot-Zeit so schnell wie möglich beginnt

Darüber hinaus sollten wir in examples/ ein Beispiel dafür bereitstellen, wie Sie next-server in Kombination mit pkg , um Ihre Next.js-Anwendung als eigenständige ELF-Binärdatei zu exportieren.

p1 feature request

Hilfreichster Kommentar

Die Kaltstartzeiten, die wir auf Now 2.0 für unser Frontend sehen, sind 1,5s, für eine Bildgröße von 80 MB IIRC

2018-05-29 16 50 37

Es sollte möglich sein, es ohne Änderungen an Node oder V8 oder einer der Abhängigkeiten, deren kalte Auswertung viel Zeit in Anspruch nimmt (wie react und react-dom ) viel näher an 1s zu bringen.

Alle 52 Kommentare

Die Kaltstartzeiten, die wir auf Now 2.0 für unser Frontend sehen, sind 1,5s, für eine Bildgröße von 80 MB IIRC

2018-05-29 16 50 37

Es sollte möglich sein, es ohne Änderungen an Node oder V8 oder einer der Abhängigkeiten, deren kalte Auswertung viel Zeit in Anspruch nimmt (wie react und react-dom ) viel näher an 1s zu bringen.

wou, das ist toll!! :Ö

wow! Das ist toll.

einige Fragen für next-server .

  1. Wird es ein leichter Express-Server sein?
  2. Ja, wird es mit Expressrouten und next-routes konfigurierbar sein?

@Nishchit14 Sie würden express nicht hinzufügen, wenn Sie versuchen würden, die Build-Größe gering zu halten.

Ich bin mir sicher, dass next-routes immer noch gut funktionieren wird.

Wir sprechen hier also davon, den vorhandenen Server in ein eigenes Paket zu extrahieren. Es funktioniert also genauso wie zuvor, aber anstatt als nächstes zu importieren, importieren Sie next-server.

Das ist fantastisch! Ich und andere Leute, die ich kenne, haben Next.js auf AWS Lambda mit Scandium (unter Verwendung dieses Handbuchs ) ausgeführt und einige der Hauptprobleme waren:

1) Paketgröße. Lambda gibt Ihnen ein hartes Limit von 50 MB, das mit allen enthaltenen Entwicklungstools leicht zu erreichen ist.

2) Kaltstart. Ein schnelles Hochfahren ist sehr wichtig, da Lambda jederzeit entscheiden kann, weitere Server hochzufahren. Vorhandene Server leben auch maximal ~4 Stunden, sodass der Kaltstart während des gesamten Lebenszyklus der Anwendung wichtig ist.

Ich freue mich sehr über diese Initiative und helfe gerne weiter!

Das ist eine großartige Idee, wir haben das gleiche mit Nuxt.js, wir haben es nuxt-start da es der Befehl ist, den Sie brauchen, um nuxt start -> nuxt-start auszuführen

Verfolge dies genau. Als Datenpunkt für das, was möglich ist, ist www.bustle.com eine SSR-Preact-App auf AWS Lambda mit Kaltstarts von <1s. Die gesamte bereitgestellte Produktions-ZIP-Datei ist 166 KB groß. Das ist der gesamte Anwendungs- und Bibliothekscode. Webpack wird zum Bündeln verwendet.

Danke für das Teilen von @southpolesteve. Das ist super beeindruckend. #Tore

Der Benutzerfall sieht micro und micro-dev sehr ähnlich.

Warum nicht dieselbe Nomenklatur verwenden? next und next-dev

Ich spiele mit next.js und serverless herum, indem ich dieses Beispiel verwende, und bin gespannt, ob es jetzt eine Möglichkeit gibt, kleinere Builds durchzuführen. Gibt es eine Liste von node_modules, die wir in der Produktion absolut nicht benötigen und die mit Konfigurationsdateien in einem Packager wie serverless oder

@Enalmada Ich führe next.js mit mehreren Deps aus und material-ui ist einer von ihnen. Welche Größen suchen Sie?

@albinekb Ich bin inspiriert von der obigen Antwort von Southpolesteve bustle.com von 166 KB und frage mich, wie viel von meinen "45 MB" nutzlos und leicht zu entfernen ist, wenn ich nur wüsste, was ich als Hack in eine Dist-Exclude-Datei einfügen muss, bis dieses ausgezeichnete Ticket fertig ist .

@albinekb Wir empfehlen Ihnen dringend, Webpack, Paket oder Rollup zu verwenden, um Ihr JS für Lambda zu bündeln. Sie sparen Größe, aber auch Bootzeit, da das Aufrufen des Dateisystems über normale Knotenanforderungen ziemlich langsam ist.

Wenn Sie für ZEIT Now bereitstellen und Ihr Image für schnelle Kaltstarts klein halten möchten, können Sie ein Tool wie Package Phobia verwenden, um die Größe einer npm-Abhängigkeit vor der Installation zu überprüfen (oder einfach die Größe der aktuellen Abhängigkeiten überprüfen) um die Blähungen zu schneiden).

Die Readme enthält auch viele ähnliche Tools, die Ihnen helfen, Blähungen zu bekämpfen. Schau mal hier: https://github.com/styfle/packagephobia

Sollte dies nicht in der Next 7-Version behandelt werden? :(

Wenn Sie jetzt für zeit bereitstellen und Ihr Image für schnelle Kaltstarts klein halten möchten, können Sie ein Tool wie Package Phobia verwenden

Verdammt noch mal: https://packagephobia.now.sh/result?p=antd

@Enalmada Es sind wahrscheinlich die Abhängigkeiten von antd, die dafür verantwortlich sind, nicht die Bibliothek selbst. Ich habe nach https://packagephobia.now.sh/result?p=%40material-ui%2Fcore gesucht

Sollte dies nicht in der Next 7-Version behandelt werden? :(

Um dies klarzustellen, Next.js 7 legt die Grundlage für Serverless Next.js. Wir haben ungefähr 5 Routen entfernt, sodass nur 2 wirklich für die Produktion benötigt werden.

Hat schon mal jemand next.js dazu gebracht, mit Rollup zu arbeiten? Ich habe das Gefühl, dass ich sehr nah dran bin ... das Rollup meiner 60-m-Dist-Datei reduzierte die Größe auf 6 m. Leider würde die dist-Datei nicht wirklich gestartet, und ich denke, dies liegt an einer einzigen zirkulären Abhängigkeit im next.js-Code, die während des Rollups eine Warnung darstellt. Wenn jemand die Möglichkeit abwägen könnte, eine zirkuläre Abhängigkeit im next.js-Code zu entfernen, könnten wir alle sehr nahe an viel kleineren Builds und einem schnelleren Booten sein:
https://github.com/zeit/next.js/issues/5392

Verfolge dies genau. Als Datenpunkt für das, was möglich ist, ist www.bustle.com eine SSR-Preact-App auf AWS Lambda mit Kaltstarts von <1s. Die gesamte bereitgestellte Produktions-ZIP-Datei ist 166 KB groß. Das ist der gesamte Anwendungs- und Bibliothekscode. Webpack wird zum Bündeln verwendet.

@southpolesteve könnten Sie alles rund um Ihre Webpack-Bundle-Konfiguration freigeben?

@shauns Leider bin ich nicht mehr bei Bustle und habe auch keinen Code mehr zum anschauen :/

@southpolesteve keine Sorge! Gut zu wissen, dass es zumindest im Webpack möglich ist.

Können wir Neuigkeiten zum nächsten Server haben? Ich habe vor einem Monat einige Commits gesehen.

Überprüfen Sie die kanarische Niederlassung.

Wann planen Sie, es zu veröffentlichen?

Eine Zeitleiste kann ich derzeit nicht teilen.

Gerade gelandet #5927

@timneutkens Soll ich next in devDependencies verschieben und next-server zu meinen Abhängigkeiten hinzufügen oder machst du das automatisch über Babel?
https://github.com/zeit/next.js/blob/canary/packages/next/build/babel/plugins/next-to-next-server.ts

@Skaronator Wenn Sie #5927 implementieren, ist dies auch nicht der .next/serverless/index.js ( require('./.next/serverless/index.js') ) und dann die Methode render aufrufen:

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

page.render(req, res)

Dadurch wird die Seite gerendert und die Antwort abgeschlossen

Das ist toll!
Ich probiere das aus, aber ich habe einige Probleme damit, dass es auf AWS Lambda funktioniert. Hat jemand Tipps?

Ich denke, wir sollten keinen benutzerdefinierten Express-Server mehr benötigen, wir könnten einfach die serverlose Datei basierend auf dem Pfad benötigen 🤔

bearbeiten
Dies scheint zu funktionieren, Sie müssen jedoch tiefer graben, um zu sehen, wie Sie den Build-Schritt optimieren können:

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

Sieht so aus, als ob Sie den "benutzerdefinierten Server" mit "serverlos" verwechseln, ihre APIs sind völlig getrennt, es gibt keine .prepare Methode in Serverless, da nichts vorbereitet werden muss, wir rendern die Seite sofort in HTML und beenden die Antwort, wenn render aufgerufen wird.

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

In der Tat, und ich habe keine Ahnung, warum der obige Code funktioniert hat (vielleicht war es nur der Cache), aber weder mein Code noch Ihr Code funktionierte, weil serverless-http http.Server nicht zu unterstützen scheint und Ich kann nicht einfach page.render(req, res) weil das Lambda-Objekt event den erforderlichen Render-Parameter req nicht ersetzen kann.

Außerdem möchte ich nicht Express/koa/was auch immer verwenden, da dies den gesamten Zweck dieser nächsten neuen Funktion unterbricht. ( serverless-http ist frei von Abhängigkeiten, daher war die Verwendung in Ordnung)

Ich habe keine Ideen mehr :/

Danke @timneutkens , ich schätze deine Hilfe.
Aber es funktioniert im Moment auch nicht, ich habe immer noch diesen Fehler: typeError: Parameter "url" must be a string, not undefined

Ich werde aufhören, diesen Thread zu verschmutzen und weiter zu wühlen und ich werde ein Beispiel schreiben, wenn ich jemals eine Lösung finde 😄

Ich bin etwas unklar. Dieser Thread scheint auf zwei Szenarien zuzutreffen: serverlose Apps und vorkompilierte Server, die alle erforderlichen serverseitigen npm-Pakete zusammen webpacked enthalten.

Das Gif im ersten Kommentar zu diesem Thread scheint sich auf das letztere Szenario zu beziehen, an dem ich interessiert bin. Es sieht so aus, als ob es next-server das dieses npm-Paket sein kann oder nicht -

Stimmt das, was ich bisher geschrieben habe? Wenn ja, obwohl es auf Kanarienvogel ist, gibt es eine Möglichkeit, einen frühen Zugriff darauf zu erhalten?

Meine aktuelle Lösung (die ich aus offensichtlichen Gründen nicht in prod verwende ) besteht darin, die Funktion aus config.externals in meinem next.config.js zu entfernen.

Ich würde gerne in der Lage sein, einen vorgefertigten Server zu produzieren, damit ich nicht jedes Mal, wenn ich ein Update pushe, 200 MB node_modules installieren und dann 2 Minuten damit verbringen muss, auf meiner armen, kleinen Produktions-VM zu kompilieren.


* "prod" wird lose verwendet, da dieses Projekt nicht geschäftskritisch oder so professionell ist

Verfolge dies genau. Als Datenpunkt für das, was möglich ist, ist www.bustle.com eine SSR-Preact-App auf AWS Lambda mit Kaltstarts von <1s. Die gesamte bereitgestellte Produktions-ZIP-Datei ist 166 KB groß. Das ist der gesamte Anwendungs- und Bibliothekscode. Webpack wird zum Bündeln verwendet.

Das serverlose Ziel von Next.js 8 hat standardmäßig eine ZIP-Größe von 42 KB

Das ist toll! Freue mich darauf!

Ich habe genau die gleiche Frage wie @dfoverdx. Ich möchte einen Server-Build erstellen, der auch alle zum Ausführen erforderlichen node_modules enthält. Ich verwende einen benutzerdefinierten Server mit Express, daher erwarte ich nicht, dass diese Abhängigkeiten im Paket enthalten sind, aber jetzt müssen Sie _alle_ Abhängigkeiten auch auf Ihrem Server installieren (react, next, axios, ...).

Ich verstehe nicht, warum das nicht standardmäßig ist?
Alle Abhängigkeiten zu packen und in der Lage zu sein, sie zu minimieren, sollte erhebliche serverseitige Leistungsverbesserungen bringen oder liege ich hier völlig falsch?

Das Überschreiben des Abschnitts externals der Webpack-Konfiguration wie folgt enthält die meisten Abhängigkeiten

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

Reagieren und reagieren-dom sind jedoch weiterhin auf dem Server erforderlich. Ich kann mir auch nicht vorstellen, wie man diese einfügt...

Leider ist es im aktuellen serverlosen Modus nicht möglich, benutzerdefinierte Server zu erstellen. Und wenn Sie den normalen Modus verwenden, müssen Sie next und alle seine Abhängigkeiten einschließen, da die generierte _app.js in .next beispielsweise von next/router abhängt

Warum könnte nicht auch der nicht-serverlose Modus als nächstes gebündelt werden?

Leider ist es im aktuellen serverlosen Modus nicht möglich, benutzerdefinierte Server zu erstellen. Und wenn Sie den normalen Modus verwenden, müssen Sie next und alle seine Abhängigkeiten einschließen, da die generierte _app.js in .next beispielsweise von next/router abhängt

Beachten Sie, dass Sie seit der nächsten 8 in Ihrer server.js 'next-server' anstelle von 'next' verlangen können und Sie dadurch während der lokalen Entwicklung nur heißes Neuladen verlieren. Theoretisch können Sie CI-Builds auf einem Zwischenserver ausführen und keine Webpack-bezogenen Abhängigkeiten auf Produktionsinstanzen kopieren. Aber wir haben es in unserem Projekt noch nicht ausprobiert.

@ElvenMonky wartet seit einem Jahr auf so etwas, konnte aber in den Dokumenten oder Beispielen nichts dazu finden.

@timneutkens könnten Sie das bitte überprüfen?

Wenn ja, könnte ich mit einem solchen Setup experimentieren und eine PR für die Dokumente/Beispiele senden.

Beachten Sie, dass Sie seit der nächsten 8 in Ihrer server.js 'next-server' anstelle von 'next' verlangen können, und Sie verlieren dadurch während der lokalen Entwicklung nur Hot-Reloading

Leider funktioniert dies nicht.

Zuerst wird die Ausführung eines serverlosen Builds mit Serverziel aktiv mit der folgenden Meldung blockiert: "Server kann nicht gestartet werden, wenn Ziel nicht Server ist. https://err.sh/zeit/next.js/next-start-serverless "

Wenn Sie sich dann für einen normalen Build entscheiden, verweisen Build-Dateien direkt auf Dinge aus dem next Paket (wie next/router in der kompilierten _app.js-Datei für den Server). Es bedeutet, dass next und webpack Sachen sowieso im Produktions-Build sein müssen.

@ElvenMonky

Beachten Sie, dass Sie seit der nächsten 8 in Ihrer server.js 'next-server' anstelle von 'next' verlangen können und Sie dadurch während der lokalen Entwicklung nur heißes Neuladen verlieren.

Als nächstes macht das intern als Babel-Plugin, wie Sie hier sehen können:
https://github.com/zeit/next.js/blob/709850154754278d2fc86b987eebe1b3f0565255/packages/next/build/babel/plugins/commonjs.ts#L5 -L32

@sheerun Wie ich auch in #7011 erwähnt habe, können Sie unaufgelöste next/router Abhängigkeiten beseitigen, indem Sie das next Modul mit dem next-transpile-modules Plugin transpilieren.

Ich habe ein Beispiel für einen benutzerdefinierten Express-Server gegabelt und angepasst, um die Lösung zu veranschaulichen: https://github.com/ElvenMonky/next.js/tree/custom-next-server-express/examples/custom-server-express

PS: Ich bin immer noch sehr begeistert von #5927, egal, dass meine Anwendung alles erfordert, was in TODO aufgeführt ist, ganz zu schweigen von dynamischen Routen und der Bereitstellung statischer Inhalte.
Die gute Nachricht ist, dass die obige Lösung gut mit https://www.npmjs.com/package/next-serverless benutzerdefinierten Server-Setup zu spielen scheint, so dass es ohne die oben genannten Einschränkungen als nächstes in beispielsweise AWS Lambda bereitgestellt werden kann.

Beachten Sie, dass Sie seit der nächsten 8 in Ihrer server.js 'next-server' anstelle von 'next' verlangen können und Sie dadurch während der lokalen Entwicklung nur heißes Neuladen verlieren.

Ich habe diesen Rat verwendet, kann aber leider die Laufzeitkonfiguration nicht verwenden, da dies next/config erfordert, was next erfordert.

Ich weiß nicht warum, aber require('next/config') früher in der Produktion funktioniert, ohne dass next in node_modules mit der nächsten Version 8.0.3 installiert war, funktioniert aber nicht mit der nächsten Version 8.1.0

Ist es möglich, next/config in ein anderes Paket wie next-runtime-config ?
Oder next-runtime-vars (wobei der Begriff config vermieden wird, um Verwechslungen mit next.config.js zu vermeiden).

Lassen Sie es mich wissen, wenn es akzeptabel ist, ich werde eine PR erstellen.

Hallo allerseits! Dieses Problem wurde seit Next.js 8 implementiert und ist in Next.js 9 immer noch vorhanden. Ich werde dies als abgeschlossen schließen. 😌

Tut mir leid, dass ich mit diesem Problem verwirrt bin: https://github.com/zeit/next.js/issues/7011
Ich habe nicht mit Ziel überprüft: "serverlos"


Siehe gelöschten Kommentar

Einige "next/*" können durch "next-server/*" , wie zum Beispiel:

  • next/config -> next-server/config
  • next/amp -> next-server/amp
  • next/dynamic -> next-server/dynamic
  • next/constants -> next-server/constants
  • next/head -> next-server/head

Aber es gibt einige, für die es keine Unterstützung für eine solche Optimierung gibt, die vom OP dieses Problems erwähnt wird.

  • next/router -> next-server/dist/lib/router/router (vielleicht)? (Sollte leer sein oder sollte bei Verwendung auf dem Server einen Fehler auslösen)
  • weiter/Link ?

Nicht erforderlich, da sie sogar im Server (AKAIK) integriert sind

  • weiter/app
  • weiter/Dokument

Hallo allerseits! Dieses Problem wurde seit Next.js 8 implementiert und ist in Next.js 9 immer noch vorhanden. Ich werde dies als abgeschlossen schließen.

Hallo @Timer -

Wenn wir next durch next server ersetzen, ändert dies die Größe des Ordners node_modules nicht, es sei denn, die Abhängigkeiten von package.json werden ebenfalls aktualisiert.

Gibt es für beide Ansätze ein Beispiel? mit serverless ist mein Anwendungsfall die Bereitstellung in AWS Lambda.

Der in der ersten Ausgabe beschriebene Ansatz hat sich zum Ziel serverless entwickelt. Wir empfehlen Ihnen, dieses zu verwenden.

@timneutkens serverless target kann und kann keine Probleme mit benutzerdefinierten Servern lösen, die dynamische Routen verwenden. #5927 Ist keine Lösung für viele reale Geschäftsanwendungen wie in meinem Fall, wo wir dynamisch generierte Seiten, Asset-Präfixe, benutzerdefinierte _app, _document und _err verwenden müssen: im Grunde alles, was in der TODO-Liste angegeben ist.
next-server bietet uns eine Teillösung für die Bereitstellung in der Produktion ohne seltsame Abhängigkeiten nur von der Entwicklung, wie Webpack und Babel. Dies kann jedoch mit einigen Hacks und Woodoo-Tanzen erreicht werden, die wir hier besprechen.

Ich hatte den Eindruck, dass Sie diesen Unterschied verstehen und hoffte, eines Tages eine robustere Lösung für das ursprüngliche Problem zu sehen, wie es von @rauchg beschrieben wird

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

timneutkens picture timneutkens  ·  3Kommentare

sospedra picture sospedra  ·  3Kommentare

DvirSh picture DvirSh  ·  3Kommentare

olifante picture olifante  ·  3Kommentare

jesselee34 picture jesselee34  ·  3Kommentare